Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 139 additions & 0 deletions policy/diamond/policy/ulims/ulims.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package diamond.policy.ulims

# import data.diamond.data
import data.diamond.policy.admin
import data.diamond.policy.session
import data.diamond.policy.token
import rego.v1

# --- Start section copied from tiled.rego ---

subject := data.diamond.data.subjects[token.claims.fedid]

# METADATA
# title: Beamlines
# description: |
# Identifies all beamlines the subject is authorized to access
# based on their assigned permissions.
beamlines contains beamline if {
token.claims.fedid
not admin.is_admin(token.claims.fedid)
some p in subject.permissions
some beamline in object.get(data.diamond.data.admin, p, [])
}

# Aggregates all session IDs the subject is authorized to view.
# Admins receive a wildcard "*" granting access to all sessions.
# Regular users gain session access through three pathways:
# 1. Direct session membership
# 2. Access via beamline-level permissions
# 3. Access via proposal-level permissions
user_sessions contains "*" if {
subject
admin.is_admin(token.claims.fedid)
}

user_sessions contains format_int(session, 10) if {
subject
not admin.is_admin(token.claims.fedid)
some session in subject.sessions
}

user_sessions contains format_int(session, 10) if {
subject
not admin.is_admin(token.claims.fedid)
some beamline in beamlines
some session in data.diamond.data.beamlines[beamline].sessions
}

user_sessions contains format_int(session, 10) if {
subject
not admin.is_admin(token.claims.fedid)
some p in subject.proposals
some i in data.diamond.data.proposals[format_int(p, 10)]
some session in i
}

# service account check
user_sessions contains format_int(session, 10) if {
not subject
some session in data.diamond.data.beamlines[token.claims.beamline].sessions
}

# --- End section copied from tiled.rego ---

# METADATA
# description: Allow verified tokens
# entrypoint: true
main := {"allow": allow}

default allow := false

allow if {
token.verified[0]
}

# METADATA
# title: Session Restrictions
# description: |
# Return the instrument sessions the current user is allowed to see, or null if the user is an admin
# Requires:
# - `input.token`, a JWT
# entrypoint: true
default session_restrictions := []

session_restrictions := null if {
admin.is_admin(token.claims.fedid)
}

session_restrictions := [data.diamond.data.sessions[session_id] | some session_id in user_sessions] if {
not admin.is_admin(token.claims.fedid)
}

session_restrictions := [data.diamond.data.sessions[session_id] | some session_id in user_sessions] if {
not token.claims.fedid
}

# METADATA
# title: Filter sessions
# description: |
# Filter a provided list of instrument sessions, returning just those that the user has access to
# Requires:
# - `input.token`, a JWT
# - `input.instrument_sessions`, an array representing a list of instrument sessions, [(proposal, visit), ...]
# entrypoint: true
filter_sessions contains session if {
"*" in user_sessions
some session in input.instrument_sessions
}

filter_sessions contains session if {
some session in input.instrument_sessions
proposal_number := format_int(session[0], 10)
session_number := format_int(session[1], 10)
format_int(data.diamond.data.proposals[proposal_number].sessions[session_number], 10) in user_sessions
}

# METADATA
# title: Filter instruments
# description: |
# Filter a provided list of instruments, returning just those that the user has access to
# Requires:
# - `input.token`, a JWT
# - `input.instruments`, an array of strings representing a list of instruments
# entrypoint: true
filter_instruments contains instrument if {
some instrument in input.instruments
instrument in beamlines
}

filter_instruments contains instrument if {
admin.is_admin(token.claims.fedid)
some instrument in input.instruments
}

filter_instruments contains instrument if {
token.claims.beamline
some instrument in input.instruments
instrument == token.claims.beamline
}
162 changes: 162 additions & 0 deletions policy/diamond/policy/ulims/ulims_test.rego
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package diamond.policy.ulims_test

import data.diamond.policy.ulims
import rego.v1

diamond_data := {
"subjects": {
"alice": {
"permissions": [],
"proposals": [1],
"sessions": [],
},
"bob": {
"permissions": ["b07_admin"],
"proposals": [],
"sessions": [],
},
"carol": {
"permissions": ["super_admin"],
"proposals": [],
"sessions": [],
},
"desmond": {
"permissions": [],
"proposals": [2],
"sessions": [13],
},
"edna": {
"permissions": [],
"proposals": [2],
"sessions": [13, 14],
},
"oscar": {
"permissions": [],
"proposals": [],
"sessions": [],
},
},
"sessions": {
"11": {
"beamline": "i03",
"proposal_number": 1,
"visit_number": 1,
},
"12": {
"beamline": "b07",
"proposal_number": 1,
"visit_number": 2,
},
"13": {
"beamline": "b07",
"proposal_number": 2,
"visit_number": 1,
},
"14": {
"beamline": "b07",
"proposal_number": 2,
"visit_number": 2,
},
},
"proposals": {
"1": {"sessions": {
"1": 11,
"2": 12,
}},
"2": {"sessions": {
"1": 13,
"2": 14,
}},
},
"beamlines": {"i03": {"sessions": [11]}, "b07": {"sessions": [12, 13, 14]}},
"admin": {"b07_admin": ["b07"]},
}

test_session_restrictions_for_admin if {
ulims.session_restrictions == null with data.diamond.data as diamond_data
with data.diamond.policy.token as {"claims": {"fedid": "carol"}}
}

test_session_restrictions_for_non_admin_1 if {
ulims.session_restrictions == [
{
"beamline": "i03",
"proposal_number": 1,
"visit_number": 1,
},
{
"beamline": "b07",
"proposal_number": 1,
"visit_number": 2,
},
] with data.diamond.data as diamond_data
with data.diamond.policy.token as {"claims": {"fedid": "alice"}}
}

test_session_restrictions_for_non_admin_2 if {
ulims.session_restrictions == [] with data.diamond.data as diamond_data
with data.diamond.policy.token as {"claims": {"fedid": "oscar"}}
}

test_session_restrictions_service_account if {
ulims.session_restrictions == [{
"beamline": "i03",
"proposal_number": 1,
"visit_number": 1,
}] with data.diamond.data as diamond_data
with data.diamond.policy.token.claims as {"beamline": "i03"}
}

test_filter_sessions_for_admin if {
ulims.filter_sessions == {[1, 1], [1, 2], [2, 1], [2, 2]} with data.diamond.data as diamond_data
with input.instrument_sessions as [[1, 1], [1, 2], [2, 1], [2, 2]]
with data.diamond.policy.token as {"claims": {"fedid": "carol"}}
}

test_filter_sessions_beamline_admin if {
ulims.filter_sessions == {[1, 2], [2, 1], [2, 2]} with data.diamond.data as diamond_data
with input.instrument_sessions as [[1, 1], [1, 2], [2, 1], [2, 2]]
with data.diamond.policy.token as {"claims": {"fedid": "bob"}}
}

test_filter_sessions_for_non_admin_1 if {
ulims.filter_sessions == {[1, 1], [1, 2]} with data.diamond.data as diamond_data
with input.instrument_sessions as [[1, 1], [1, 2], [2, 1], [2, 2]]
with data.diamond.policy.token as {"claims": {"fedid": "alice"}}
}

test_filter_sessions_for_non_admin_2 if {
ulims.filter_sessions == set() with data.diamond.data as diamond_data
with input.instrument_sessions as [[1, 1], [1, 2], [2, 1], [2, 2]]
with data.diamond.policy.token as {"claims": {"fedid": "oscar"}}
}

test_filter_sessions_service_account if {
ulims.filter_sessions == {[1, 1]} with data.diamond.data as diamond_data
with input.instrument_sessions as [[1, 1], [1, 2], [2, 1], [2, 2]]
with data.diamond.policy.token as {"claims": {"beamline": "i03"}}
}

test_filter_instruments_user if {
ulims.filter_instruments == set() with data.diamond.data as diamond_data
with input.instruments as ["i03", "b07"]
with data.diamond.policy.token as {"claims": {"fedid": "alice"}}
}

test_filter_instruments_beamline_admin if {
ulims.filter_instruments == {"b07"} with data.diamond.data as diamond_data
with input.instruments as ["i03", "b07"]
with data.diamond.policy.token as {"claims": {"fedid": "bob"}}
}

test_filter_instruments_super_admin if {
ulims.filter_instruments == {"i03", "b07"} with data.diamond.data as diamond_data
with input.instruments as ["i03", "b07"]
with data.diamond.policy.token as {"claims": {"fedid": "carol"}}
}

test_filter_instruments_service_account if {
ulims.filter_instruments == {"i03"} with data.diamond.data as diamond_data
with input.instruments as ["i03", "b07"]
with data.diamond.policy.token as {"claims": {"beamline": "i03"}}
}
Loading