blob: d791586a4592f5b1d70f17d079b0f4d590178fcd [file] [log] [blame]
// 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.v23.security.BlessingPattern;
import io.v.v23.security.access.Constants;
import io.v.v23.security.access.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> vAccessListToUserIds(io.v.v23.security.access.AccessList accessList) {
if (!accessList.getNotIn().isEmpty()) {
throw new RuntimeException("Non-empty not-in section: " + accessList);
}
Set<String> res = new HashSet<>();
for (BlessingPattern bp : accessList.getIn()) {
// TODO(sadovsky): Ignore cloud peer's blessing pattern?
res.add(Syncbase.getEmailFromBlessingPattern(bp));
}
return res;
}
/**
* Creates an empty access list.
*/
public AccessList() {
this.users = new HashMap<>();
}
protected AccessList(Permissions perms) {
Set<String> resolvers = vAccessListToUserIds(perms.get(Constants.RESOLVE.getValue()));
Set<String> readers = vAccessListToUserIds(perms.get(Constants.READ.getValue()));
Set<String> writers = vAccessListToUserIds(perms.get(Constants.WRITE.getValue()));
Set<String> admins = vAccessListToUserIds(perms.get(Constants.ADMIN.getValue()));
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(io.v.v23.security.access.AccessList accessList, BlessingPattern bp) {
if (!accessList.getIn().contains(bp)) {
accessList.getIn().add(bp);
}
}
private static void removeFromVAccessList(io.v.v23.security.access.AccessList accessList, BlessingPattern bp) {
accessList.getIn().remove(bp);
}
/**
* Applies delta to perms, modifying perms in place.
*/
protected static void applyDelta(Permissions perms, AccessList delta) {
for (String userId : delta.users.keySet()) {
AccessLevel level = delta.users.get(userId);
BlessingPattern bp = Syncbase.getBlessingPatternFromEmail(userId);
if (level == null) {
removeFromVAccessList(perms.get(Constants.RESOLVE.getValue()), bp);
removeFromVAccessList(perms.get(Constants.READ.getValue()), bp);
removeFromVAccessList(perms.get(Constants.WRITE.getValue()), bp);
removeFromVAccessList(perms.get(Constants.ADMIN.getValue()), bp);
continue;
}
switch (level) {
case READ:
addToVAccessList(perms.get(Constants.RESOLVE.getValue()), bp);
addToVAccessList(perms.get(Constants.READ.getValue()), bp);
removeFromVAccessList(perms.get(Constants.WRITE.getValue()), bp);
removeFromVAccessList(perms.get(Constants.ADMIN.getValue()), bp);
break;
case READ_WRITE:
addToVAccessList(perms.get(Constants.RESOLVE.getValue()), bp);
addToVAccessList(perms.get(Constants.READ.getValue()), bp);
addToVAccessList(perms.get(Constants.WRITE.getValue()), bp);
removeFromVAccessList(perms.get(Constants.ADMIN.getValue()), bp);
break;
case READ_WRITE_ADMIN:
addToVAccessList(perms.get(Constants.RESOLVE.getValue()), bp);
addToVAccessList(perms.get(Constants.READ.getValue()), bp);
addToVAccessList(perms.get(Constants.WRITE.getValue()), bp);
addToVAccessList(perms.get(Constants.ADMIN.getValue()), bp);
break;
}
}
}
}