1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package eu.ehri.project.commands;
21
22 import com.google.common.collect.Iterables;
23 import com.google.common.collect.Lists;
24 import com.tinkerpop.blueprints.CloseableIterable;
25 import com.tinkerpop.frames.FramedGraph;
26 import eu.ehri.project.acl.ContentTypes;
27 import eu.ehri.project.acl.PermissionType;
28 import eu.ehri.project.core.GraphManager;
29 import eu.ehri.project.core.GraphManagerFactory;
30 import eu.ehri.project.exceptions.ItemNotFound;
31 import eu.ehri.project.models.ContentType;
32 import eu.ehri.project.models.DocumentaryUnit;
33 import eu.ehri.project.models.EntityClass;
34 import eu.ehri.project.models.Group;
35 import eu.ehri.project.models.Permission;
36 import eu.ehri.project.models.PermissionGrant;
37 import eu.ehri.project.models.Repository;
38 import eu.ehri.project.models.base.Accessible;
39 import eu.ehri.project.models.base.Entity;
40 import eu.ehri.project.models.base.Identifiable;
41 import eu.ehri.project.models.base.PermissionScope;
42 import eu.ehri.project.models.cvoc.Concept;
43 import eu.ehri.project.models.events.SystemEventQueue;
44 import eu.ehri.project.models.idgen.IdGeneratorUtils;
45 import org.apache.commons.cli.CommandLine;
46 import org.apache.commons.cli.Option;
47 import org.apache.commons.cli.Options;
48
49 import java.util.List;
50
51 import static eu.ehri.project.models.EntityClass.CVOC_CONCEPT;
52 import static eu.ehri.project.models.EntityClass.DOCUMENTARY_UNIT;
53 import static eu.ehri.project.models.EntityClass.HISTORICAL_AGENT;
54 import static eu.ehri.project.models.EntityClass.REPOSITORY;
55 import static eu.ehri.project.persistence.ActionManager.GLOBAL_EVENT_ROOT;
56
57
58
59
60 public class Check extends BaseCommand {
61
62 final static String NAME = "check";
63 private static final String QUICK = "quick";
64
65 @Override
66 public String getHelp() {
67 return "Perform various checks on the graph structure";
68 }
69
70 @Override
71 public String getUsage() {
72 return NAME + " [OPTIONS]";
73 }
74
75 @Override
76 protected void setCustomOptions(Options options) {
77 options.addOption(Option.builder()
78 .longOpt(QUICK)
79 .desc("Run fast, basic sanity checks only")
80 .build());
81 }
82
83 @Override
84 public int execWithOptions(FramedGraph<?> graph,
85 CommandLine cmdLine) throws Exception {
86
87 GraphManager manager = GraphManagerFactory.getInstance(graph);
88 checkInitialization(graph, manager);
89 if (!cmdLine.hasOption(QUICK)) {
90 checkPermissionScopes(graph, manager);
91 checkOwnerPermGrantsHaveNoScope(manager);
92 }
93
94 return 0;
95 }
96
97 private void checkInitialization(FramedGraph<?> graph, GraphManager manager) {
98 if (graph.getBaseGraph().getVertices().iterator().hasNext()) {
99 try {
100 SystemEventQueue queue =
101 manager.getEntity(GLOBAL_EVENT_ROOT, EntityClass.SYSTEM, SystemEventQueue.class);
102 if (!queue.getSystemEvents().iterator().hasNext()) {
103 System.err.println("Global event iterator is empty!");
104 }
105 } catch (ItemNotFound itemNotFound) {
106 System.err.println("Unable to read event root in graph!");
107 }
108
109 try {
110 manager.getEntity(Group.ADMIN_GROUP_IDENTIFIER, Group.class);
111
112 for (PermissionType pt : PermissionType.values()) {
113 manager.getEntity(pt.getName(), Permission.class);
114 }
115 for (ContentTypes ct : ContentTypes.values()) {
116 manager.getEntity(ct.getName(), ContentType.class);
117 }
118 } catch (ItemNotFound itemNotFound) {
119 System.err.println("Unable to find item in graph with id: " + itemNotFound.getValue());
120 }
121 } else {
122 System.err.println("Graph contains no vertices (has it been initialized?)");
123 }
124 }
125
126
127
128
129
130
131
132
133
134
135
136
137 private void checkPermissionScopes(FramedGraph<?> graph,
138 GraphManager manager) {
139
140 List<EntityClass> types = Lists.newArrayList(DOCUMENTARY_UNIT, REPOSITORY, CVOC_CONCEPT, HISTORICAL_AGENT);
141
142 for (EntityClass entityClass : types) {
143 try (CloseableIterable<? extends Entity> items = manager.getEntities(entityClass, entityClass.getJavaClass())) {
144 for (Entity item : items) {
145 Accessible entity = item.as(Accessible.class);
146 PermissionScope scope = entity.getPermissionScope();
147 if (scope == null) {
148 System.err.println("Missing scope: " + entity.getId() + " (" + entity.asVertex().getId() + ")");
149 } else {
150 switch (manager.getEntityClass(item)) {
151 case DOCUMENTARY_UNIT:
152 checkIdGeneration(graph.frame(item.asVertex(), DocumentaryUnit.class), scope);
153 break;
154 case REPOSITORY:
155 checkIdGeneration(graph.frame(item.asVertex(), Repository.class), scope);
156 break;
157 case CVOC_CONCEPT:
158 checkIdGeneration(graph.frame(item.asVertex(), Concept.class), scope);
159 case HISTORICAL_AGENT:
160 checkIdGeneration(graph.frame(item.asVertex(), Concept.class), scope);
161 default:
162 }
163 }
164 }
165 }
166 }
167 }
168
169 private void checkIdGeneration(Identifiable doc, PermissionScope scope) {
170 if (scope != null) {
171 String ident = doc.getIdentifier();
172 List<String> path = Lists.newArrayList(Iterables.concat(scope.idPath(), Lists.newArrayList(ident)));
173 String finalId = IdGeneratorUtils.joinPath(path);
174 if (!finalId.equals(doc.getId())) {
175 System.err.println(String.format("Generated ID does not match scopes: '%s' -> %s + %s",
176 doc.getId(), path, ident));
177 }
178 }
179 }
180
181 private void checkOwnerPermGrantsHaveNoScope(GraphManager manager) {
182 try (CloseableIterable<PermissionGrant> items = manager
183 .getEntities(EntityClass.PERMISSION_GRANT, PermissionGrant.class)) {
184 for (PermissionGrant grant : items) {
185 Entity scope = grant.getScope();
186 Entity perm = grant.getPermission();
187 if (scope != null && perm != null && perm.getId().equals(PermissionType.OWNER.getName())) {
188 System.err.println(
189 String.format("Owner permission grant with scope: %s", grant.asVertex().getId()));
190 }
191 }
192 }
193
194 }
195 }