comparison src/nabble/view/lib/Permissions.java @ 0:7ecd1a4ef557

add content
author Franklin Schmidt <fschmidt@gmail.com>
date Thu, 21 Mar 2019 19:15:52 -0600
parents
children 18cf4872fd7f
comparison
equal deleted inserted replaced
-1:000000000000 0:7ecd1a4ef557
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 }