Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

This is getting messy. I think we could use a more robust alternative to implement this. But first, here are the authorization checks we have implemented or want to implement in the MTB timeframe (described in terms of access to objects in the REST API, rather than through the several endpoints that are needed to expose each object in the API itself, and skipping participant-facing APIs):. Then as well look at alternatives for implementation, I’ll show what modeling enrollment would look like.

Authorization Rules

Object

Assoc(1)

Role

Permissions(2)

AccountSummary

global (but filtered)

researcher

read

Study (“participant”)

researcher

read

Organization (“member”)

org admin

read

App

all

read

dev, admin

update

superadmin

create, delete

AppConfig

public

read (filtered)

dev

create, read, write, delete

AppConfigElement

dev

create, read, write, delete

Assessment

Organization (“owner”)

dev

create, read, write

admin

delete

AssessmentConfig

public

read

Organization (“owner”)

dev

write

Enrollment(Detail)

Account (“self”)

any

create, read, delete

Study

researcher

create, read, delete

Study

admin

create, read, delete

AssessmentResource

Organization (“owner”)

developer

create, read, delete

admin

delete

FileMetadata/Revision

developer

create, read, write

admin

delete

HealthDataRecord(Ex3)

participant

create

worker

write

MasterScheduleConfig

superadmin

create, read, write, delete

NotificationMessage

self, admin, researcher

create

NotificationRegistration

self, researcher, admin

read

NotificationTopic

developer

create, read, write

admin

delete

Organization

any

read

Account (“membership”)

org_admin

write

admin

create, delete

RecordExportStatusRequest

worker

write

ReportData

Study

any/public

read

Study

dev, worker

create, delete

ReportIndex

Study

any

read

Study

dev

create, write

RequestInfo

Account (“self”)

RequestInfo

Study

researcher

read

admin, worker

read

SchedulePlan

developer, researcher, worker

read

developer

create, write

admin

delete

SmsTemplate

Account

worker

create

Study

org_admin

create

Organization (“sponsors”)

org_admin

create, read, delete

StudyConsent

dev

create, read

StudyParticipant

Study (“enrolled”)

researcher

create, read, write

worker

read

Participant (“self”)

read, write

admin

create

Subpopulation

dev

create, read, write

researcher

read

admin

delete

Survey

dev, researcher, worker

read

dev

create, write

admin

delete

Tag

public

read

superadmin

create, delete

Template/TemplateRevision

dev

create, read, write

admin

delete

Upload

dev, admin, worker

read

UploadSchema

dev

create, read, write

admin

delete

...

This is the most complex option available, but we could use the method-based security via annotations. Our service methods could declare the security using complex expression rules.

Modeling EnrollmentService, it would look like this (ignoring the work necessary to make it work):

Code Block
languagejava
public class EnrollmentService {

    @Secure("principal.id == callerUserId or hasRole('ADMIN') or " + 
      "(hasRole('RESEARCHER') and hasOrgSponsoredStudy(studyId))")
    public PagedResourceList<EnrollmentDetail> getEnrollmentsForStudy(...) {
    }
    
    @Secure("principal.id == callerUserId or hasRole('ADMIN') or " + 
      "(hasRole('RESEARCHER') and hasOrgSponsoredStudy(studyId))")
    public List<EnrollmentDetail> getEnrollmentsForUser(...) {
    }
    
    @Secure("principal.id == callerUserId or hasRole('ADMIN') or " + 
      "(hasRole('RESEARCHER') and hasOrgSponsoredStudy(studyId))")
    public Enrollment enroll(...) {
    }
    
    @Secure("principal.id == callerUserId or hasRole('ADMIN') or " + 
      "(hasRole('RESEARCHER') and hasOrgSponsoredStudy(studyId))")
    public void updateEnrollment(...) {
    }
    
    @Secure("principal.id == callerUserId or hasRole('ADMIN') or " + 
      "(hasRole('RESEARCHER') and hasOrgSponsoredStudy(studyId))")
    public Enrollment unenroll(...) {
    }
}

Pros

  1. It’s a standardized thing so other developers should have an easier time working with it;

  2. Ultimately, security would be expressed in annotations, which seems nice;

  3. One step closer to implementing a major change to something like storing access rights in a database (so far we haven’t seen anything in Bridge that requires that level of authorization, but)

...