schema: |-
definition user {
relation self: user
// Only ONE of the following relations is ever present for a given user (XOR)
relation organization: organization
relation installation: installation
// permissions
permission read_info = self + organization->member + organization->owner + installation->admin
permission write_info = self
permission delete = self + organization->owner + installation->admin
permission make_admin = installation->admin + organization->installation_admin
// administrate is for changes such as blocking or verifiying, i.e. things that only admins can do on user
permission admin_control = installation->admin + organization->installation_admin
permission read_ssh = self
permission write_ssh = self
permission read_tokens = self
permission write_tokens = self
permission read_env_var = self
permission write_env_var = self
// only used in specified cell, check EXP-1084
permission write_temporary_token = organization->installation_admin
permission code_sync = self
}
// There's only one global installation
definition installation {
// only users that are not owned by an org are considered installation-level users
relation member: user
relation admin: user
// orgs can only be created by installation-level users
permission create_organization = member + admin
// any global runtime configurations, such as the list of blocked repositories
permission configure = admin
}
definition organization {
relation installation: installation
// Every user in an organization is automatically a member
relation member: user
// Some users in an organization may additionally have the `owner` role
relation owner: user
// users who can snapshot workspaces
relation snapshoter: organization#member
// Some users in an organization may additionally have the `collaborator` role
// collaborator can't access members, projects and usage
relation collaborator: user
// synthetic permission for installation->admin (because https://github.com/authzed/spicedb/issues/15)
permission installation_admin = installation->admin
permission installation_member = installation->member
// General operations on organization
permission read_info = member + owner + collaborator + installation->admin
permission write_info = owner + installation->admin
permission delete = owner + installation->admin
permission read_settings = member + owner + collaborator + installation->admin
permission write_settings = owner + installation->admin
permission read_env_var = member + owner + collaborator + installation->admin
permission write_env_var = owner + installation->admin
permission read_audit_logs = owner + installation->admin
// Maintenance mode permission
permission maintenance = owner + installation->admin
// Operations on Organization's Members
permission read_members = member + owner + installation->admin
permission invite_members = member + owner + installation->admin
permission write_members = owner + installation->admin
permission leave = owner + member + collaborator + installation->admin
// Permissions on (sub-)resources
permission create_project = member + owner + installation->admin
permission read_git_provider = owner + member + collaborator + installation->admin
permission write_git_provider = owner + installation->admin
permission read_billing = member + owner + installation->admin
permission write_billing = owner + installation->admin
// Note that there are two different read_prebuild permissions: this one, guarding primarily the listPrebuilds method in the API and then the other under projects, which is the actual permission used for checking if a user can use a prebuild for a repository.
// Today, the difference is that collaborators can't read prebuilds on an org but can on a repository (project).
permission read_prebuild = member + owner + installation->admin
permission create_workspace = member + collaborator
permission read_sessions = owner + installation->admin
// can add credit notes and change the spending limits even for free users
permission write_billing_admin = installation->admin
}
definition project {
relation org: organization
// A subject is a viewer, if:
// * the users with access are directly assigned as a viewer
// * the project has granted access to all members in an organization
// * the project has granted access to _any_ user on this installation
relation viewer: user | organization#member | user:*
// All org members are editors for now, to model the existing behavior.
permission editor = org->member
permission read_info = viewer + editor + org->owner + org->installation_admin
permission write_info = editor + org->owner + org->installation_admin
permission delete = editor + org->owner + org->installation_admin
permission read_env_var = viewer + editor + org->collaborator + org->owner + org->installation_admin
permission write_env_var = editor + org->owner + org->installation_admin
permission read_prebuild = viewer + editor + org->collaborator + org->owner + org->installation_admin
permission write_prebuild = editor + org->owner
}
definition workspace {
relation org: organization
// The user that created the workspace
relation owner: user
// Whether this workspace is shared (globally)
relation shared: user:*
// Whether a user can access a workspace (with an IDE)
permission access = owner + shared + org->installation_admin
// Note: All of this is modelled after current behavior.
// There are a lot of improvements we can make here in the light of Organizations, but we explicitly do that as a separate step
permission start = owner
permission stop = owner + org->installation_admin + org->owner
permission delete = owner
// Whether a user can read basic info/metadata of a workspace
permission read_info = owner + shared + org->member
permission create_snapshot = owner & org->snapshoter
// Whether someone is allowed to do administrative tasks on a workspace, e.g. un-delete etc.
permission admin_control = org->installation_admin
}
relationships: |-
// we have one installation
installation:installation_0#member@user:user_0
user:user_0#installation@installation:installation_0
installation:installation_0#admin@user:user_admin
// We have an organization org_1, which has some members & owners
organization:org_1#installation@installation:installation_0
organization:org_1#member@user:user_0
organization:org_1#owner@user:user_0
organization:org_1#member@user:user_1
organization:org_1#member@user:user_2
user:user_0#organization@organization:org_1
user:user_1#organization@organization:org_1
user:user_2#organization@organization:org_1
// org_1 has a project
project:project_1#org@organization:org_1
// project_1 can be accessed by anyone in the organization - it's visibility is public
project:project_1#viewer@organization:org_1#member
// We have another organization org_2, which has some users, some of which are also members of org_1
organization:org_2#member@user:user_0
organization:org_2#owner@user:user_0
organization:org_2#member@user:user_1
organization:org_2#member@user:user_10
// user_2 is a collaborator of org_2
organization:org_2#collaborator@user:user_2
user:user_10#organization@organization:org_2
// org_2 has a project project_2
project:project_2#org@organization:org_2
// user_1 is viewer of project_2
project:project_2#viewer@user:user_1
workspace:workspace_1#org@organization:org_1
workspace:workspace_1#owner@user:user_1
workspace:workspace_2_shared#org@organization:org_1
workspace:workspace_2_shared#owner@user:user_1
workspace:workspace_2_shared#shared@user:*
validation:
installation:installation_0#member:
- "[user:user_0] is <installation:installation_0#member>"
installation:installation_0#admin:
- "[user:user_admin] is <installation:installation_0#admin>"
organization:org_1#member:
- "[user:user_0] is <organization:org_1#member>"
- "[user:user_1] is <organization:org_1#member>"
- "[user:user_2] is <organization:org_1#member>"
organization:org_1#owner:
- "[user:user_0] is <organization:org_1#owner>"
project:project_1#org:
- "[organization:org_1] is <project:project_1#org>"
assertions:
assertTrue:
- organization:org_1#read_info@user:user_0
- organization:org_1#read_git_provider@user:user_1
- project:project_1#write_info@user:user_0
- organization:org_1#write_settings@user:user_0
- organization:org_1#write_git_provider@user:user_0
- organization:org_1#read_members@user:user_0
- organization:org_1#write_members@user:user_0
- organization:org_1#invite_members@user:user_0
- organization:org_1#read_members@user:user_1
- organization:org_1#invite_members@user:user_1
- organization:org_1#delete@user:user_0
- project:project_1#delete@user:user_0
- project:project_1#delete@user:user_1
- project:project_1#read_info@user:user_1
- organization:org_1#create_project@user:user_1
- project:project_2#write_info@user:user_10
- installation:installation_0#create_organization@user:user_0
- project:project_1#delete@user:user_admin
- organization:org_1#delete@user:user_admin
- organization:org_1#write_settings@user:user_admin
- organization:org_1#write_git_provider@user:user_admin
- installation:installation_0#create_organization@user:user_admin
- workspace:workspace_1#access@user:user_1
- workspace:workspace_2_shared#access@user:user_1
- workspace:workspace_2_shared#access@user:user_2
- user:user_0#write_temporary_token@user:user_admin
- user:user_1#write_temporary_token@user:user_admin
- user:user_2#write_temporary_token@user:user_admin
assertFalse:
- project:project_1#read_info@user:user_10
- organization:org_1#read_info@user:user_3
- organization:org_1#write_info@user:user_3
- organization:org_1#write_settings@user:user_1
- organization:org_1#read_members@user:user_3
- organization:org_1#write_members@user:user_3
- organization:org_1#invite_members@user:user_3
- organization:org_1#write_members@user:user_1
- organization:org_1#write_git_provider@user:user_1
- organization:org_1#delete@user:user_1
- workspace:workspace_1#access@user:user_2
- organization:org_2#read_members@user:user_2
- project:project_2#read_info@user:user_2
- project:project_2#write_info@user:user_2
- project:project_2#delete@user:user_2
- organization:org_2#read_billing@user:user_2
- user:user_1#write_temporary_token@user:user_0
- user:user_10#write_temporary_token@user:user_admin