foam3

FOAM Permissions

Permission System Architecture

┌─────────────────────────────────────────────────────────────────────────────┐
│                           PERMISSION CHECK FLOW                             │
└─────────────────────────────────────────────────────────────────────────────┘

  ┌──────────┐
  │   User   │ ─────────────────────────┐
  └────┬─────┘                          │
       │ belongs to                     │ owns (CRUNCH)
       ▼                                ▼
  ┌──────────┐                   ┌─────────────────┐
  │  Group   │                   │   Capability    │
  └────┬─────┘                   │  (can expire)   │
       │ has many                └────────┬────────┘
       ▼                                  │ grants
  ┌───────────────────┐                   │
  │ GroupPermission   │                   │
  │    Junction       │                   │
  └────────┬──────────┘                   │
           │ links to                     │
           ▼                              ▼
  ┌─────────────────────────────────────────────────────────────────┐
  │                         Permission                               │
  │  ┌─────────────────────────────────────────────────────────┐    │
  │  │  Permission String Patterns:                             │    │
  │  │                                                          │    │
  │  │  • *                        → Global (do anything)       │    │
  │  │  • service.<name>           → Service access             │    │
  │  │  • <model>.read.<id>        → Read object                │    │
  │  │  • <model>.create           → Create object              │    │
  │  │  • <model>.update.<id>      → Update object              │    │
  │  │  • <model>.remove.<id>      → Delete object              │    │
  │  │  • <model>.ro.<property>    → Read property              │    │
  │  │  • <model>.rw.<property>    → Write property             │    │
  │  │  • <model>.column.<prop>    → View table column          │    │
  │  │  • @<RoleName>              → Inherit Role's permissions │    │
  │  └─────────────────────────────────────────────────────────┘    │
  └─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│                         AUTH SERVICE DECORATOR CHAIN                        │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   Request → PMAuthService → CachingAuthService → CapabilityAuthService      │
│               │                    │                      │                 │
│               ▼                    ▼                      ▼                 │
│          (monitoring)         (caching)            (CRUNCH check)           │
│                                                          │                  │
│             EnabledCheckAuthService ← PasswordExpiryAuthService             │
│                      │                        │                             │
│                      ▼                        ▼                             │
│              (user enabled?)          (password expired?)                   │
│                                                                             │
│                    TwoFactorAuthService → UserAndGroupAuthService           │
│                            │                        │                       │
│                            ▼                        ▼                       │
│                      (2FA check)           (Group permissions)              │
│                                                     │                       │
│                                                     ▼                       │
│                                              ✓ GRANTED / ✗ DENIED           │
└─────────────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────────────┐
│                              ROLE INHERITANCE                               │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│   ┌───────────────┐      @OpsRole       ┌───────────────┐                   │
│   │  AdminGroup   │ ──────────────────► │   OpsRole     │ (Role Group)      │
│   │               │      inherits       │  (no users)   │                   │
│   │ permissions:  │                     │ permissions:  │                   │
│   │  - user.*     │                     │  - report.*   │                   │
│   │  - @OpsRole   │◄────────────────────│  - audit.*    │                   │
│   └───────────────┘   gets all perms    └───────────────┘                   │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

Overview

Permissions in FOAM represent access to system resources and follow Java’s hierarchical naming convention. 1 The system uses wildcard matching where an asterisk can appear by itself or at the end of a name preceded by a dot to signify wildcard matches.

Permission Naming Convention

Valid wildcard patterns:

Invalid patterns:

Examples:

Permission Checking

Primary Interface

boolean foam.core.auth.AuthService.check(X x, String permission)

Main Implementation

UserAndGroupAuthService serves as the primary implementation, decorated with multiple service layers:

Core Data Models

Authentication Models

CRUNCH Models

Permission Patterns

1. Service Access

2. WebAgent Execution

3. DAO Object Operations

4. Property-Level Access

5. Action Permissions

6. UI Section Visibility

7. Table Column Visibility

8. Role Permissions

Permissions of the form @<GroupName> grant all permissions owned by the <GroupName> group. This is typically used to create “Role” Groups which don’t have any direct users but are just used to create collections of Permissions. These types of Groups are prefixed by “Role” by convention. Ex.: "OpsRole", "ReflowRole"

Permission Pattern Summary

Pattern Purpose
service.<serviceName> Service access
service.run.<serviceName> WebAgent execution
<model>.read.<id> Read object
<model>.update.<id> Update object
<model>.remove.<id> Delete object
<model>.create Create object
<model>.ro.<property> Read property
<model>.rw.<property> Write property
<model>.column.<property> View table column
No standard pattern Execute actions
@<RoleName> Grant all Role permissions

User Interface

Permission Management

Notes

The FOAM permission system implements a comprehensive authorization framework with wildcard support, hierarchical naming, and multiple specialized authorizers. 10 The system integrates with both traditional group-based permissions and the advanced CRUNCH capability system for fine-grained access control.

Wiki pages you might want to explore:

Citations

File: src/foam/core/auth/Permission.js (L7-24)

 foam.CLASS({
   package: 'foam.core.auth',
   name: 'Permission',

   documentation: 'A permission represents access to system resources.',

   properties: [
     {
       class: 'String',
       name: 'id',
       tableWidth: 400
     },
     {
       class: 'String',
       name: 'description',
       documentation: 'Description of the Group.'
     }
   ],

File: src/foam/core/auth/pom.js (L16-16)

    { name: "User",                                                   flags: "js|java" },

File: src/foam/core/auth/pom.js (L67-67)

    { name: "Group",                                                  flags: "js|java" },

File: src/foam/core/auth/Relationships.js (L7-14)

foam.RELATIONSHIP({
  cardinality: '*:*',
  sourceModel: 'foam.core.auth.Group',
  targetModel: 'foam.core.auth.Permission',
  forwardName: 'permissions',
  inverseName: 'groups',
  junctionDAOKey: 'groupPermissionJunctionDAO'
});

File: src/foam/core/crunch/Capability.js (L7-14)

foam.CLASS({
  package: 'foam.core.crunch',
  name: 'Capability',

  implements: [
    // See CapabilityRefinement for additional implements
    'foam.core.auth.LifecycleAware'
  ],

File: src/foam/core/auth/AuthorizableAuthorizer.java (L14-44)

public class AuthorizableAuthorizer implements Authorizer {

  protected String permissionPrefix_;

  public AuthorizableAuthorizer(String permissionPrefix) {
    permissionPrefix_ = permissionPrefix;
  }

  public void authorizeOnCreate(X x, FObject obj) throws AuthorizationException {
    if ( obj instanceof Authorizable ) {
      ((Authorizable) obj).authorizeOnCreate(x);
    }
  }

  public void authorizeOnRead(X x, FObject obj) throws AuthorizationException {
    if ( obj instanceof Authorizable ) {
      ((Authorizable) obj).authorizeOnRead(x);
    }
  }

  public void authorizeOnUpdate(X x, FObject oldObj, FObject obj) throws AuthorizationException {
    if ( obj instanceof Authorizable ) {
      ((Authorizable) obj).authorizeOnUpdate(x, oldObj);
    }
  }

  public void authorizeOnDelete(X x, FObject obj) throws AuthorizationException {
    if ( obj instanceof Authorizable ) {
      ((Authorizable) obj).authorizeOnDelete(x);
    }
  }

File: src/foam/lib/PermissionedPropertyPredicate.js (L22-28)

        if ( prop.getReadPermissionRequired() ) {
          String      propName = prop.getName().toLowerCase();
          AuthService auth     = (AuthService) x.get("auth");

          return ( auth != null )
            ? (auth.check(x,  of + ".ro." + propName) || auth.check(x,  of + ".rw." + propName))
            : false;

File: src/foam/core/auth/PermissionTableView.js (L13-39)

foam.CLASS({
  package: 'foam.core.auth',
  name: 'PermissionTableView',
  extends: 'foam.u2.Controller',

  implements: [ 'foam.mlang.Expressions' ],

  requires: [
    'foam.graphics.ScrollCView',
    'foam.core.auth.Group',
    'foam.core.auth.GroupPermissionJunction',
    'foam.core.auth.Permission'
  ],

  imports: [
    'auth',
    'groupDAO',
    'groupPermissionJunctionDAO',
    'permissionDAO',
    'user'
  ],

  constants: {
    COLS: 26,
    ROWS: 17,
    ROLE_PREFIX: 'Role'
  },

File: src/permissions.jrl (L1-10)

p({"class":"foam.core.auth.Permission","id":"*","description":"Do anything global permission."})
p({"class":"foam.core.auth.Permission","id":"menu.auth","description":"Perform authentication related configuration"})
p({"class":"foam.core.auth.Permission","id":"service.*","description":"Global permission for reading of services"})
p({"class":"foam.core.auth.Permission","id":"service.read.*","description":"Global permission for reading of services from a DAO"})
p({"class":"foam.core.auth.Permission","id":"service.auth.checkUser","description":"Permission to grant access to check user permissions."})
p({"class":"foam.core.auth.Permission","id":"emailmessage.read.*","description":""})
p({"class":"foam.core.auth.Permission","id":"smsmessage.read.*","description":""})
p({"class":"foam.core.auth.Permission","id":"menu.read.admin","description":"Ability to use the 'admin' menu."})
p({"class":"foam.core.auth.Permission","id":"menu.read.admin.send-notification","description":"Ability to use Send Notification UI"})
p({"class":"foam.core.auth.Permission","id":"menu.read.admin.customise-theme","description":"Ability to use Theme Customisation UI"})

TODO: difference between cSpecDAO and AuthenticatedCSpecDAO