...
Permission | Object | Association | view(for a study) |
---|---|---|---|
list | Can list the object | Can see the study exists | |
read | Can view the object | Can list members see the details of the association and view themstudy | |
edit | Can view and edit the object | Can list members and edit any member of the associationedit/update the study | |
delete | Can delete the object | Can delete the study | |
admin | Can view, edit, and change permissions of object | Can list, view, edit, see permissions for the study and add/remove members of the associationthem. | |
manage(?) | Add/remove members of an association might need to be split out from editing members (e.g. the power to enroll vs. the power to administer a participant). In that case admin does not include add/remove rights, that is moved to the manage role. |
...
Model/Association | Description |
---|---|
Account | A specific account, probably necessary to model “self” rules in our system. Might be given to all accounts automatically without having to write a record to the permissions table. |
Organization | An organization |
Sponsored Studies * | The studies sponsored by an organization |
Members * | The members of an organization |
Assessment Library * | The assessments owned by an organization (and thus not part of the shared and public library) |
Study | A study |
Study PI * | The PI of a study (a very specific association, always EDIT if it exists) |
Participants * | The participants in a study |
Assessment | An assessment |
...
Code Block | ||
---|---|---|
| ||
public class Permission { String guid; // synthetic key makes create/add/update APIs easier String appId; // most permissions except system-wide, and usually implicit String userId; String roleaccessLevel; // "admin", "developer" String permissionTypeentityType; // "study", "organization", "app", "system" String objectIdentityId; // "studyId", "orgId", "appId" // Suggested toString() descriptor (implicitly scoped to an app): // "2rkp3nU7p8fjUTDVIgjT6T ∈ {organization:sage-bionetworks admin}" } // Each type relates to a specific entity and its ID (indicated in the constructor) public enum PermissionType { ASSESSMENT (ASSESSMENT), STUDY (STUDY), ORGANIZATION (ORGANIZATION), SPONSORED_STUDIES (ORGANIZATION), MEMBERS (ORGANIZATION), ASSESSMENTS (ORGANIZATION), // ASSESSMENT_LIBRARY? STUDY_PI (STUDY), PARTICIPANTS (STUDY); } |
...
Code Block | ||
---|---|---|
| ||
interface PermissionsService { Set<Permission> getPermissionsForUser(String appId, String userId); Permission addPermission(Permission permission); void updatePermission(Permission permission); void removePermission(Permission permissionspermission); Set<Permission> getPermissionsForType(String appId, PermissionType type, String id); // this delete may/** notSpring besecurity cascadedwill byneed a thevery databasefocused andmethod wouldto thencheck, for a // need to be done* manually.given user and voida deletePermissions(Stringgiven appIdobject, PermissionTypedoes type,the Stringuser id);have any of the required /** Spring security will need* aroles very focused method to check, for a * given user and a given object, does the user have any of the required * roles to to perform the request. This method can fudge things like * app-scoped permissions, too. */ boolean isAuthorizedAs(AccountId accountId, PermissionType type, String objectId, Role... roles); } |
...
Method | URL | Description |
---|---|---|
GET | /v1/permissions/{userId} | Get all permissions for a user. |
GET | /v1/permissions/{permissionTypeentityType}/{objectIdentityId} | Get all permissions for an object like organization, study, or app. |
POST | /v1/permissions | Create a permission for a specific object and user. Caller must be an admin for the object. Returns the object with a GUID. |
POST | /v1/permissions/{guid} | Update a permission (caller must be an admin for the object). |
DELETE | /v1/permissions/{guid} | Remove a permission for an object (caller must be an admin for the object). |
...
Add the permissions table, service, APIs, completely separate from existing security so they are completely functional;
Create bridge code so that roles and organization membership changes are mirrored in the permissions table (but not vice versa?);
Migrate all existing account roles to the new permissions tables. Changes made at any time after the migration should also make it to the permissions tables, which still cannot be used;
Annotate our controllers with the new permissions;
Remove old code checking permissions;
Switch over to use the new permissions apis rather than account APIs to manage permissions (probably by throwing errors if roles are changed on an account).
Remove bridge code;
Remove roles from accounts;
Remove code that is granting permissions to studies as a result of organization membership, which is a large external change that will need to be documented and supported in existing tools.
Role to Permission Mapping
This mapping is necessary for steps 2 and 3 in migration. Each role needs to be mimicked by permissions.
Roles manage access to studies and assessments through organization membership. The “sponsored studies” and “assessment library” permissions similarly grant access to studies and assessments based on organization. So the individual “study” and “assessment” permissions should be unnecessary for migration.
The “participant” permission is more complicated because it is handled by individual study. Developers and Study Designers only have access to test accounts. Researchers and Study Coordinators have access to participant data. So mimicking the role means granting “participant” access to each study in their organization.
Entity Type | Access Level | DEVELOPER | RESEARCHER | STUDY_COORDINATOR | STUDY_DESIGNER | ORG_ADMIN | ADMIN | Note |
ASSESSMENT | List | No | No | No | No | No | No | Assessments should be accessible through the assessment library permission. |
Read | No | No | No | No | No | No | ||
Edit | No | No | No | No | No | No | ||
Delete | No | No | No | No | No | No | ||
Admin | No | No | No | No | No | No | ||
ASSESSMENT_LIBRARY | List | Yes | Yes | Yes | Yes | Yes | Yes | The entity ID would be the user's organization, granting permissions to all assessments under that organization. |
Read | Yes | Yes | Yes | Yes | Yes | Yes | ||
Edit | Yes | No | No | Yes | No | Yes | ||
Delete | Yes | No | No | Yes | No | Yes | ||
Admin | No | No | No | No | Yes | Yes | ||
MEMBERS | List | Yes | Yes | Yes | Yes | Yes | Yes | |
Read | Yes | Yes | Yes | Yes | Yes | Yes | ||
Edit | No | No | No | No | Yes | Yes | ||
Delete | No | No | No | No | Yes | Yes | ||
Admin | No | No | No | No | Yes | Yes | ||
ORGANIZATION | List | Yes | Yes | Yes | Yes | Yes | Yes | |
Read | Yes | Yes | Yes | Yes | Yes | Yes | ||
Edit | No | No | No | No | Yes | Yes | ||
Delete | No | No | No | No | Yes | Yes | ||
Admin | No | No | No | No | Yes | Yes | ||
PARTICIPANTS | List | No | Yes | Yes | No | No | Yes | Participant permissions are managed by study ID. So each study in the organization will need these permissions granted to mimic the role's access. |
Read | No | Yes | Yes | No | No | Yes | ||
Edit | No | Yes | Yes | No | No | Yes | ||
Delete | No | Yes | Yes | No | No | Yes | ||
Admin | No | No | No | No | No | Yes | ||
SPONSORED_STUDIES | List | Yes | Yes | Yes | Yes | Yes | Yes | Researchers and Study Coordinators can "phase transition" studies. |
Read | Yes | Yes | Yes | Yes | Yes | Yes | ||
Edit | Yes | Yes | Yes | Yes | No | Yes | ||
Delete | Yes | No | No | Yes | No | Yes | ||
Admin | No | No | No | No | Yes | Yes | ||
STUDY | List | No | No | No | No | No | No | All studies in organization should be covered through the sponsored studies permission. |
Read | No | No | No | No | No | No | ||
Edit | No | No | No | No | No | No | ||
Delete | No | No | No | No | No | No | ||
Admin | No | No | No | No | No | No | ||
STUDY_PI | List | No | No | No | No | No | No | |
Read | No | No | No | No | No | No | ||
Edit | No | No | No | No | No | No | ||
Delete | No | No | No | No | No | No | ||
Admin | No | No | No | No | No | No |
Multiple organization membership
...