0
|
1 package nabble.view.lib;
|
|
2
|
|
3 import fschmidt.db.Listener;
|
|
4 import fschmidt.db.ListenerList;
|
|
5 import fschmidt.util.java.Filter;
|
|
6 import nabble.model.Db;
|
|
7 import nabble.model.Init;
|
|
8 import nabble.model.Node;
|
|
9 import nabble.model.Person;
|
|
10 import nabble.model.Site;
|
|
11 import nabble.model.User;
|
|
12
|
|
13 import java.util.ArrayList;
|
|
14 import java.util.Collections;
|
|
15 import java.util.List;
|
|
16 import java.util.Set;
|
|
17
|
|
18
|
|
19 public final class Permissions {
|
|
20 private Permissions() {} // never
|
|
21
|
|
22 private static String encode(String s) {
|
|
23 StringBuilder buf = new StringBuilder();
|
|
24 int n = s.length();
|
|
25 for( int i=0; i<n; i++ ) {
|
|
26 char c = s.charAt(i);
|
|
27 if( c == '\'' )
|
|
28 buf.append('\'');
|
|
29 buf.append(c);
|
|
30 }
|
|
31 return buf.toString();
|
|
32 }
|
|
33
|
|
34 private static void dbCheck(Site site) {
|
|
35 if( !site.getDb().isInTransaction() )
|
|
36 throw new RuntimeException("not in transaction");
|
|
37 }
|
|
38
|
|
39 public static boolean isInGroup(User user,String group) {
|
|
40 return user.getSite().hasTags(null,user,
|
|
41 "label='group:" + encode(group) + "'"
|
|
42 );
|
|
43 }
|
|
44
|
|
45 public static void addToGroup(User user,String group) {
|
|
46 Site site = user.getSite();
|
|
47 dbCheck(site);
|
|
48 site.addTag( null, user, "group:" + group );
|
|
49 groupChangeListeners.event(site);
|
|
50 }
|
|
51
|
|
52 public static void removeFromGroup(User user,String group) {
|
|
53 Site site = user.getSite();
|
|
54 dbCheck(site);
|
|
55 user.getSite().deleteTags(null,user,
|
|
56 "label='group:" + encode(group) + "'"
|
|
57 );
|
|
58 groupChangeListeners.event(site);
|
|
59 }
|
|
60
|
|
61 public static void removeGroup(Site site,String group) {
|
|
62 site.deleteTags(
|
|
63 "node_id is null and user_id is not null and label='group:" + encode(group) + "'"
|
|
64 );
|
|
65 groupChangeListeners.event(site);
|
|
66 }
|
|
67
|
|
68 public static void removeGroups(User user) {
|
|
69 user.getSite().deleteTags(null,user,
|
|
70 "label like 'group:%'"
|
|
71 );
|
|
72 groupChangeListeners.event(user.getSite());
|
|
73 }
|
|
74
|
|
75 private static List<String> getGroups(Site site,String sqlCondition) {
|
|
76 List<String> list = new ArrayList<String>();
|
|
77 for( String label : site.findTagLabels(sqlCondition) ) {
|
|
78 list.add( label.substring(6) );
|
|
79 }
|
|
80 return list;
|
|
81 }
|
|
82
|
|
83 public static List<String> getGroups(User user) {
|
|
84 return getGroups( user.getSite(),
|
|
85 "node_id is null and user_id=" + user.getId() + " and label like 'group:%'"
|
|
86 );
|
|
87 }
|
|
88
|
|
89 public static List<String> getGroups(Site site) {
|
|
90 return getGroups( site,
|
|
91 "node_id is null and user_id is not null and label like 'group:%'"
|
|
92 );
|
|
93 }
|
|
94
|
|
95 public static List<User> getUsersInGroup(Site site,String group) {
|
|
96 return site.findTagUsers(
|
|
97 "node_id is null and user_id is not null and label='group:" + encode(group) + "'"
|
|
98 );
|
|
99 }
|
|
100
|
|
101 public static void addPermission(Node node,String permission) {
|
|
102 Site site = node.getSite();
|
|
103 dbCheck(site);
|
|
104 site.addTag( node, null, "permission:" + permission );
|
|
105 permissionChangeListeners.event(site);
|
|
106 }
|
|
107
|
|
108 public static void addPermission(Node node,String permission,String group) {
|
|
109 Site site = node.getSite();
|
|
110 dbCheck(site);
|
|
111 if( !nodeHasPermission(node,permission) )
|
|
112 addPermission(node,permission);
|
|
113 site.addTag( node, null, "permission:" + permission + ":" + group );
|
|
114 permissionChangeListeners.event(site);
|
|
115 }
|
|
116
|
|
117 public static void addPermission(Site site,String permission,String group) {
|
|
118 dbCheck(site);
|
|
119 if( !siteHasPermission(site,permission) )
|
|
120 site.addTag( null, null, "permission:" + permission );
|
|
121 site.addTag( null, null, "permission:" + permission + ":" + group );
|
|
122 permissionChangeListeners.event(site);
|
|
123 }
|
|
124
|
|
125 public static void removePermission(Node node,String permission,String group) {
|
|
126 Site site = node.getSite();
|
|
127 dbCheck(site);
|
|
128 site.deleteTags(node,null,
|
|
129 "label='permission:" + encode(permission) + ":" + encode(group) + "'"
|
|
130 );
|
|
131 permissionChangeListeners.event(site);
|
|
132 }
|
|
133
|
|
134 public static void removePermission(Node node,String permission) {
|
|
135 Site site = node.getSite();
|
|
136 site.deleteTags(node,null,
|
|
137 "(label = 'permission:" + encode(permission) + "'"
|
|
138 + " or label like 'permission:" + encode(permission) + ":%')"
|
|
139 );
|
|
140 permissionChangeListeners.event(site);
|
|
141 }
|
|
142
|
|
143 public static void removePermissions(Node node) {
|
|
144 Site site = node.getSite();
|
|
145 dbCheck(site);
|
|
146 site.deleteTags(node,null,
|
|
147 "label like 'permission:%'"
|
|
148 );
|
|
149 permissionChangeListeners.event(site);
|
|
150 }
|
|
151
|
|
152 public static boolean isPermissionVersion(Site site,String version) {
|
|
153 return site.hasTags(null,null,
|
|
154 "label='permission-version:" + version + "'"
|
|
155 );
|
|
156 }
|
|
157
|
|
158 public static void setPermissionVersion(Site site,String version) {
|
|
159 dbCheck(site);
|
|
160 deletePermissionVersion(site);
|
|
161 site.addTag( null, null, "permission-version:" + version );
|
|
162 }
|
|
163
|
|
164 public static void deletePermissionVersion(Site site) {
|
|
165 site.deleteTags(null,null,
|
|
166 "(label like 'permission:%' or label like 'site_default_permission:%' or label like 'permission-version:%')"
|
|
167 );
|
|
168 }
|
|
169
|
|
170 private static String query(Node node) {
|
|
171 return node==null ? "node_id is null" : "node_id=" + node.getId();
|
|
172 }
|
|
173
|
|
174 private static boolean siteHasPermission(Site site,String permission) {
|
|
175 return site.hasTags(null,null,
|
|
176 "label='permission:" + encode(permission) + "'"
|
|
177 );
|
|
178 }
|
|
179
|
|
180 public static boolean nodeHasPermission(Node node,String permission) {
|
|
181 return node.getSite().hasTags(node,null,
|
|
182 "label='permission:" + encode(permission) + "'"
|
|
183 );
|
|
184 }
|
|
185
|
|
186 public static Node getPermissionNode(Node node,String permission) {
|
|
187 for( Node n : node.getAncestors() ) {
|
|
188 if( nodeHasPermission(n,permission) )
|
|
189 return n;
|
|
190 }
|
|
191 return null;
|
|
192 }
|
|
193
|
|
194 public static List<String> getGroupsWithPermission(Node node,String permission) {
|
|
195 Site site = node.getSite();
|
|
196 node = getPermissionNode(node,permission);
|
|
197 if( node == null && !siteHasPermission(site,permission) )
|
|
198 return Collections.emptyList();
|
|
199 List<String> list = new ArrayList<String>();
|
|
200 String labelStart = "permission:" + encode(permission) + ":";
|
|
201 int i = labelStart.length();
|
|
202 for( String label : site.findTagLabels(
|
|
203 query(node) + " and user_id is null and label like '" + labelStart + "%'"
|
|
204 ) ) {
|
|
205 list.add( label.substring(i) );
|
|
206 }
|
|
207 return list;
|
|
208 }
|
|
209
|
|
210 public static boolean hasGroupsWithPermission(Node node,String permission) {
|
|
211 Site site = node.getSite();
|
|
212 node = getPermissionNode(node,permission);
|
|
213 if( node == null && !siteHasPermission(site,permission) )
|
|
214 return false;
|
|
215 return site.hasTags(node,null,
|
|
216 "label like 'permission:" + encode(permission) + ":%'"
|
|
217 );
|
|
218 }
|
|
219
|
|
220 public static final String ANYONE_GROUP = "Anyone";
|
|
221 public static final String REGISTERED_GROUP = "Registered";
|
|
222 public static final String AUTHOR_GROUP = "Authors";
|
|
223 public static final String ADMINISTRATORS_GROUP = "Administrators";
|
|
224
|
|
225 public static List<String> getPersonGroups(Person person) {
|
|
226 List<String> groups;
|
|
227 if (person instanceof User) {
|
|
228 User user = (User) person;
|
|
229 groups = getGroups((User) person);
|
|
230 if (user.isRegistered())
|
|
231 groups.add(REGISTERED_GROUP);
|
|
232 } else {
|
|
233 groups = new ArrayList<String>();
|
|
234 }
|
|
235 groups.add(ANYONE_GROUP);
|
|
236 return groups;
|
|
237 }
|
|
238
|
|
239 public static boolean hasPermission(Node permissionNode,Node targetNode,Person person,String permission) {
|
|
240 Person owner = targetNode.getOwner();
|
|
241 Site site = permissionNode.getSite();
|
|
242 permissionNode = getPermissionNode(permissionNode,permission);
|
|
243 if( permissionNode == null && !siteHasPermission(site,permission) )
|
|
244 return false;
|
|
245 String s = "label='permission:" + encode(permission) + ":";
|
|
246 List<String> groups = getPersonGroups(person);
|
|
247 if( owner.equals(person) )
|
|
248 groups.add(AUTHOR_GROUP);
|
|
249 for( String group : groups ) {
|
|
250 if( site.hasTags(permissionNode,null, s + encode(group) + "'" ) )
|
|
251 return true;
|
|
252 }
|
|
253 return false;
|
|
254 }
|
|
255
|
|
256 public static boolean hasPermission(Node node,String group,String permission) {
|
|
257 Site site = node.getSite();
|
|
258 node = getPermissionNode(node,permission);
|
|
259 if( node == null && !siteHasPermission(site,permission) )
|
|
260 return false;
|
|
261 return hasPermission(site,node,group,permission);
|
|
262 }
|
|
263
|
|
264 private static boolean hasPermission(Site site,Node node,String group,String permission) {
|
|
265 return site.hasTags(node,null,
|
|
266 "label='permission:" + encode(permission) + ":" + encode(group) + "'"
|
|
267 );
|
|
268 }
|
|
269
|
|
270 public static boolean hasPermission(Site site,String group,String permission) {
|
|
271 return siteHasPermission(site,permission) && site.hasTags(null,null,
|
|
272 "label='permission:" + encode(permission) + ":" + encode(group) + "'"
|
|
273 );
|
|
274 }
|
|
275
|
|
276 public static List<User> getUsersWithPermission(Node node,String permission) {
|
|
277 Site site = node.getSite();
|
|
278 node = getPermissionNode(node,permission);
|
|
279 if( node == null && !siteHasPermission(site,permission) )
|
|
280 return Collections.emptyList();
|
|
281 if (hasPermission(site, node, ANYONE_GROUP,permission))
|
|
282 return site.getUsers(null);
|
|
283 else if (hasPermission(site, node, REGISTERED_GROUP,permission))
|
|
284 return site.getUsers("registered is not null");
|
|
285 String labelStart = "permission:" + encode(permission) + ":";
|
|
286 int i = labelStart.length();
|
|
287 return site.findTagUsers(
|
|
288 "node_id is null and user_id is not null and label in ("
|
|
289 + "select 'group:' || substring(label," + (i+1) + ") from tag where " + query(node) + " and user_id is null and label like '" + labelStart + "%'"
|
|
290 +")"
|
|
291 );
|
|
292 }
|
|
293
|
|
294
|
|
295 public static final String VIEW_PERMISSION = "View";
|
|
296
|
|
297 public static boolean isPrivate(Node node) {
|
|
298 return getPrivateNode(node) != null;
|
|
299 }
|
|
300
|
|
301 public static boolean canBeViewedByParentViewers(Node node) {
|
|
302 if( node.getKind() != Node.Kind.APP )
|
|
303 return true;
|
|
304 if( !nodeHasPermission(node,VIEW_PERMISSION) )
|
|
305 return true;
|
|
306 Node parent = node.getParent();
|
|
307 if( parent != null )
|
|
308 parent = getPrivateNode(parent);
|
|
309 if( parent == null && !siteHasPermission(node.getSite(),VIEW_PERMISSION) )
|
|
310 return !isPrivate(node);
|
|
311 return !node.getSite().hasTags(parent,null,
|
|
312 "label like 'permission:View:%'"
|
|
313 +" and label not in (select label from tag where node_id=" + node.getId() + " and user_id is null and label like 'permission:View:%')"
|
|
314 );
|
|
315 }
|
|
316
|
|
317 public static final Filter<Node> canBeViewedByParentViewersFilter = new Filter<Node>() {
|
|
318 public boolean ok(Node node) {
|
|
319 return canBeViewedByParentViewers(node);
|
|
320 }
|
|
321 };
|
|
322
|
|
323 public static boolean canBeViewedByPerson(Node node,Person person) {
|
|
324 if( person instanceof User ) {
|
|
325 User user = (User)person;
|
|
326 if( isSysAdmin(user) )
|
|
327 return true;
|
|
328 if( isInGroup(user,ADMINISTRATORS_GROUP) )
|
|
329 return true;
|
|
330 }
|
|
331 if( node.getSite().getRootNode().getOwner().equals(person) )
|
|
332 return true;
|
|
333 Node permissionNode = node.getApp();
|
|
334 if( permissionNode==null )
|
|
335 permissionNode = node.getSite().getRootNode();
|
|
336 return hasPermission(permissionNode,node,person,VIEW_PERMISSION);
|
|
337 }
|
|
338
|
|
339 public static final Filter<Node> canBeViewedByPersonFilter(final Person person) {
|
|
340 return new Filter<Node>() {
|
|
341 public boolean ok(Node node) {
|
|
342 return canBeViewedByPerson(node,person);
|
|
343 }
|
|
344 };
|
|
345 }
|
|
346
|
|
347 public static Node getPrivateNode(Node node) {
|
|
348 node = getPermissionNode(node,VIEW_PERMISSION);
|
|
349 return node==null || hasPermission(node.getSite(),node,ANYONE_GROUP,VIEW_PERMISSION) ? null : node;
|
|
350 }
|
|
351
|
|
352 public static Node getPrivateNodeForSearch(Node node) {
|
|
353 node = getPrivateNode(node);
|
|
354 while( node != null && canBeViewedByParentViewers(node) ) {
|
|
355 node = getPrivateNode(node.getParent());
|
|
356 }
|
|
357 return node;
|
|
358 }
|
|
359
|
|
360 // Banning ------------------------------------------------------
|
|
361
|
|
362 public static boolean isBanned(User user) {
|
|
363 return user.getSite().hasTags(null,user,"label='banned'");
|
|
364 }
|
|
365
|
|
366 public static void ban(User user) {
|
|
367 user.getSite().addTag(null, user, "banned");
|
|
368 }
|
|
369
|
|
370 public static void unban(User user) {
|
|
371 user.getSite().deleteTags(null,user,"label='banned'");
|
|
372 }
|
|
373
|
|
374 public static List<User> getBannedUsers(Site site) {
|
|
375 return site.findTagUsers(
|
|
376 "node_id is null and user_id is not null and label='banned'"
|
|
377 );
|
|
378 }
|
|
379
|
|
380
|
|
381
|
|
382 private static final Set<String> sysadmins = Init.get("sysadmins",Collections.<String>emptySet());
|
|
383
|
|
384 public static boolean isSysAdmin(User user) {
|
|
385 return sysadmins.contains(user.getEmail());
|
|
386 }
|
|
387
|
|
388
|
|
389 // site permissions
|
|
390
|
|
391 public static void addSitePermission(Site site,String permission) {
|
|
392 dbCheck(site);
|
|
393 site.addTag( null, null, "site_permission:" + permission );
|
|
394 }
|
|
395
|
|
396 public static void addSiteDefaultPermission(Site site,String permission) {
|
|
397 dbCheck(site);
|
|
398 site.addTag( null, null, "site_default_permission:" + permission );
|
|
399 }
|
|
400
|
|
401 private static boolean hasSitePermission(Site site,String permission) {
|
|
402 return site.hasTags(null,null,
|
|
403 "label='site_permission:" + encode(permission) + "'"
|
|
404 );
|
|
405 }
|
|
406
|
|
407 public static boolean siteHasSitePermission(Site site,String permission) {
|
|
408 return hasSitePermission(site,permission);
|
|
409 }
|
|
410
|
|
411 private static boolean hasSiteDefaultPermission(Site site,String permission) {
|
|
412 return site.hasTags(null,null,
|
|
413 "label='site_default_permission:" + encode(permission) + "'"
|
|
414 );
|
|
415 }
|
|
416
|
|
417 public static void addSitePermission(Site site,String permission,String group) {
|
|
418 dbCheck(site);
|
|
419 if( !hasSitePermission(site,permission) )
|
|
420 site.addTag( null, null, "site_permission:" + permission );
|
|
421 site.addTag( null, null, "site_permission:" + permission + ":" + group );
|
|
422 }
|
|
423
|
|
424 public static void addSiteDefaultPermission(Site site,String permission,String group) {
|
|
425 dbCheck(site);
|
|
426 if( !hasSiteDefaultPermission(site,permission) )
|
|
427 site.addTag( null, null, "site_default_permission:" + permission );
|
|
428 site.addTag( null, null, "site_default_permission:" + permission + ":" + group );
|
|
429 }
|
|
430
|
|
431 public static void removeSitePermission(Site site,String permission,String group) {
|
|
432 dbCheck(site);
|
|
433 site.deleteTags(null,null,
|
|
434 "label='site_permission:" + encode(permission) + ":" + encode(group) + "'"
|
|
435 );
|
|
436 }
|
|
437
|
|
438 public static void removeSitePermission(Site site,String permission) {
|
|
439 site.deleteTags(null,null,
|
|
440 "(label = 'site_permission:" + encode(permission) + "'"
|
|
441 + " or label like 'site_permission:" + encode(permission) + ":%')"
|
|
442 );
|
|
443 }
|
|
444
|
|
445 public static void removeSitePermissions(Site site) {
|
|
446 dbCheck(site);
|
|
447 site.deleteTags(null,null,
|
|
448 "label like 'site_permission:%'"
|
|
449 );
|
|
450 }
|
|
451
|
|
452 private static String sitePermissionLabel(Site site,String permission) {
|
|
453 if( hasSitePermission(site,permission) )
|
|
454 return "site_permission:" + encode(permission);
|
|
455 else if( hasSiteDefaultPermission(site,permission) )
|
|
456 return "site_default_permission:" + encode(permission);
|
|
457 else
|
|
458 return null;
|
|
459 }
|
|
460
|
|
461 public static List<String> getGroupsWithSitePermission(Site site,String permission) {
|
|
462 String labelStart = sitePermissionLabel(site,permission);
|
|
463 if( labelStart == null )
|
|
464 return Collections.emptyList();
|
|
465 List<String> list = new ArrayList<String>();
|
|
466 int i = labelStart.length();
|
|
467 for( String label : site.findTagLabels(
|
|
468 "node_id is null and user_id is null and label like '" + labelStart + ":%'"
|
|
469 ) ) {
|
|
470 list.add( label.substring(i) );
|
|
471 }
|
|
472 return list;
|
|
473 }
|
|
474
|
|
475 public static boolean hasGroupsWithSitePermission(Site site,String permission) {
|
|
476 String labelStart = sitePermissionLabel(site,permission);
|
|
477 if( labelStart == null )
|
|
478 return false;
|
|
479 return site.hasTags(null,null,
|
|
480 "label like '" + labelStart + ":%'"
|
|
481 );
|
|
482 }
|
|
483
|
|
484 public static boolean hasSitePermission(Site site,Person person,String permission) {
|
|
485 String labelStart = sitePermissionLabel(site,permission);
|
|
486 if( labelStart == null )
|
|
487 return false;
|
|
488 String s = "label='" + labelStart + ":";
|
|
489 List<String> groups = getPersonGroups(person);
|
|
490 for( String group : groups ) {
|
|
491 if( site.hasTags(null,null, s + encode(group) + "'" ) )
|
|
492 return true;
|
|
493 }
|
|
494 return false;
|
|
495 }
|
|
496
|
|
497 public static boolean hasSitePermission(Site site,String group,String permission) {
|
|
498 String labelStart = sitePermissionLabel(site,permission);
|
|
499 if( labelStart == null )
|
|
500 return false;
|
|
501 return site.hasTags(null,null,
|
|
502 "label='" + labelStart + ":" + encode(group) + "'"
|
|
503 );
|
|
504 }
|
|
505
|
|
506 public static boolean hasSiteDefaultPermission(Site site,String group,String permission) {
|
|
507 return hasSiteDefaultPermission(site,permission) && site.hasTags(null,null,
|
|
508 "label='site_default_permission:" + encode(permission) + ":" + encode(group) + "'"
|
|
509 );
|
|
510 }
|
|
511
|
|
512 public static List<User> getUsersWithSitePermission(Site site,String permission) {
|
|
513 String labelStart = sitePermissionLabel(site,permission);
|
|
514 if (labelStart == null)
|
|
515 return Collections.emptyList();
|
|
516 if (hasSitePermission(site,ANYONE_GROUP,permission))
|
|
517 return site.getUsers(null);
|
|
518 else if (hasSitePermission(site,REGISTERED_GROUP,permission))
|
|
519 return site.getUsers("registered is not null");
|
|
520 labelStart += ":";
|
|
521 int i = labelStart.length();
|
|
522 return site.findTagUsers(
|
|
523 "node_id is null and user_id is not null and label in ("
|
|
524 + "select 'group:' || substring(label," + (i+1) + ") from tag where node is null and user_id is null and label like '" + labelStart + "%'"
|
|
525 +")"
|
|
526 );
|
|
527 }
|
|
528
|
|
529
|
|
530 private static final ListenerList<Site> groupChangeListeners = new ListenerList<Site>();
|
|
531
|
|
532 public static void addGroupChangeListener(final Listener<Site> listener) {
|
|
533 groupChangeListeners.add(listener);
|
|
534 }
|
|
535
|
|
536 private static final ListenerList<Site> permissionChangeListeners = new ListenerList<Site>();
|
|
537
|
|
538 public static void addPermissionChangeListener(final Listener<Site> listener) {
|
|
539 permissionChangeListeners.add(listener);
|
|
540 }
|
|
541
|
|
542 }
|