/**
 * @license
 * Copyright 2018 The FOAM Authors. All Rights Reserved.
 * http://www.apache.org/licenses/LICENSE-2.0
 */

package foam.nanos.auth;

import foam.core.FObject;
import foam.core.X;
import foam.dao.DAO;
import foam.dao.ProxyDAO;
import foam.util.SafetyUtil;

/**
 * Custom authentication for groupDAO
 *
 * Features:
 *   - If creating a group, you can only give it permissions implied by those
 *     that you already have.
 *   - If updating a group, you can't modify the permissions array to have a
 *     permission that isn't implied by one you have.
 *   - If updating a group, you can't modify the parent of the group such that
 *     the group gains a permission that isn't implied by one you have.
 */
public class AuthenticatedGroupDAO extends ProxyDAO {
  public AuthenticatedGroupDAO(X x, DAO delegate) {
    super(x, delegate);
  }

  /**
   * Make sure that the user has all permissions in the given group.
   */
  public void checkUserHasAllPermissionsInGroup(X x, Group toCheck) {
    AuthService auth = (AuthService) x.get("auth");
    String groupId;
    Group group = toCheck;

    while ( true ) {
      Permission[] permissions = group.getPermissions();

      for ( Permission permission : permissions ) {
        String id = permission.getId();
        if ( ! auth.check(x, id) ) {
          throw new AuthorizationException("Permission Denied. You do not have the '" + id + "' permission.");
        }
      }

      groupId = group.getParent();

      if ( SafetyUtil.isEmpty(groupId) ) {
        break;
      }

      group = (Group) getDelegate().find_(x, groupId);

      if ( group == null ) {
        throw new RuntimeException("The '" + toCheck.getId() + "' group has a null ancestor named '" + groupId + "'.");
      }
    }
  }

  @Override
  public FObject put_(X x, FObject obj) {
    checkUserHasAllPermissionsInGroup(x, (Group) obj);
    return super.put_(x, obj);
  }
}

@@ -847,24 +847,340 @@
 legate);%0A  %7D
+%0A  public void enforceNameSpaceForGroupName(X x, Group toCheck) %7B%0A    AuthService auth = (AuthService) x.get(%22auth%22);%0A    Group group = toCheck;%0A    if ( ! auth.check(x, %22group.create.%22 + group.getId()) ) %7B%0A    throw new AuthorizationException(%22Permission Denied. Your group name must begin with your spid.%22); %0A  %7D%0A%7D
 %0A%0A  /**%0A   *
@@ -2135,24 +2135,131 @@
 ject obj) %7B%0A
+    if ( getDelegate().find_(x, obj) == null ) %7B%0A      enforceNameSpaceForGroupName(x, (Group) obj);%0A    %7D%0A
     checkUse

Validate that groupNames start with spid