| // Copyright 2016 The Vanadium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package io.v.syncbase; |
| |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import io.v.syncbase.core.Permissions; |
| |
| /** |
| * Specifies access levels for a set of users. Each user has an associated access level: read-only, |
| * read-write, or read-write-admin. |
| */ |
| public class AccessList { |
| public enum AccessLevel { |
| READ, |
| READ_WRITE, |
| READ_WRITE_ADMIN |
| } |
| |
| public Map<String, AccessLevel> users; |
| |
| private static Set<String> parsedAccessListToUserIds(Map<String, Set<String>> accessList) { |
| Set<String> res = new HashSet<>(); |
| if (accessList.containsKey(Permissions.NOT_IN) && |
| !accessList.get(Permissions.NOT_IN).isEmpty()) { |
| throw new RuntimeException("Non-empty not-in section: " + accessList); |
| } |
| for (String blessingPattern : accessList.get(Permissions.IN)) { |
| // TODO(sadovsky): Ignore cloud peer's blessing pattern? |
| res.add(Syncbase.getEmailFromBlessingPattern(blessingPattern)); |
| } |
| return res; |
| } |
| |
| /** |
| * Creates an empty access list. |
| */ |
| public AccessList() { |
| this.users = new HashMap<>(); |
| } |
| |
| protected AccessList(Permissions corePermissions) { |
| Map<String, Map<String, Set<String>>> parsedPermissions = corePermissions.parse(); |
| Set<String> resolvers = parsedAccessListToUserIds(parsedPermissions.get(Permissions.Tags.RESOLVE)); |
| Set<String> readers = parsedAccessListToUserIds(parsedPermissions.get(Permissions.Tags.READ)); |
| Set<String> writers = parsedAccessListToUserIds(parsedPermissions.get(Permissions.Tags.WRITE)); |
| Set<String> admins = parsedAccessListToUserIds(parsedPermissions.get(Permissions.Tags.ADMIN)); |
| |
| if (!readers.containsAll(writers)) { |
| throw new RuntimeException("Some readers are not resolvers: " + readers + ", " + resolvers); |
| } |
| if (!readers.containsAll(writers)) { |
| throw new RuntimeException("Some writers are not readers: " + writers + ", " + readers); |
| } |
| if (!writers.containsAll(admins)) { |
| throw new RuntimeException("Some admins are not writers: " + admins + ", " + writers); |
| } |
| for (String userId : readers) { |
| users.put(userId, AccessLevel.READ); |
| } |
| for (String userId : writers) { |
| users.put(userId, AccessLevel.READ_WRITE); |
| } |
| for (String userId : admins) { |
| users.put(userId, AccessLevel.READ_WRITE_ADMIN); |
| } |
| } |
| |
| private static void addToVAccessList(Map<String, Set<String>> accessList, String blessing) { |
| if (!accessList.get(Permissions.IN).contains(blessing)) { |
| accessList.get(Permissions.IN).add(blessing); |
| } |
| } |
| |
| private static void removeFromVAccessList(Map<String, Set<String>> accessList, String blessing) { |
| accessList.get(Permissions.IN).remove(blessing); |
| } |
| |
| /** |
| * Computes a new Permissions object based on delta. |
| */ |
| protected static Permissions applyDelta(Permissions corePermissions, AccessList delta) { |
| Map<String, Map<String, Set<String>>> parsedPermissions = corePermissions.parse(); |
| for (String userId : delta.users.keySet()) { |
| AccessLevel level = delta.users.get(userId); |
| String blessing = Syncbase.getBlessingStringFromEmail(userId); |
| if (level == null) { |
| removeFromVAccessList(parsedPermissions.get(Permissions.Tags.RESOLVE), blessing); |
| removeFromVAccessList(parsedPermissions.get(Permissions.Tags.READ), blessing); |
| removeFromVAccessList(parsedPermissions.get(Permissions.Tags.WRITE), blessing); |
| removeFromVAccessList(parsedPermissions.get(Permissions.Tags.ADMIN), blessing); |
| continue; |
| } |
| switch (level) { |
| case READ: |
| addToVAccessList(parsedPermissions.get(Permissions.Tags.RESOLVE), blessing); |
| addToVAccessList(parsedPermissions.get(Permissions.Tags.READ), blessing); |
| removeFromVAccessList(parsedPermissions.get(Permissions.Tags.WRITE), blessing); |
| removeFromVAccessList(parsedPermissions.get(Permissions.Tags.ADMIN), blessing); |
| break; |
| case READ_WRITE: |
| addToVAccessList(parsedPermissions.get(Permissions.Tags.RESOLVE), blessing); |
| addToVAccessList(parsedPermissions.get(Permissions.Tags.READ), blessing); |
| addToVAccessList(parsedPermissions.get(Permissions.Tags.WRITE), blessing); |
| removeFromVAccessList(parsedPermissions.get(Permissions.Tags.ADMIN), blessing); |
| break; |
| case READ_WRITE_ADMIN: |
| addToVAccessList(parsedPermissions.get(Permissions.Tags.RESOLVE), blessing); |
| addToVAccessList(parsedPermissions.get(Permissions.Tags.READ), blessing); |
| addToVAccessList(parsedPermissions.get(Permissions.Tags.WRITE), blessing); |
| addToVAccessList(parsedPermissions.get(Permissions.Tags.ADMIN), blessing); |
| break; |
| } |
| } |
| return new Permissions(parsedPermissions); |
| } |
| } |