Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Documentation
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Rachael Hu
Documentation
Commits
3af7467f
Commit
3af7467f
authored
Apr 14, 2016
by
Tom Laudeman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add new DBUser spec file, update requirements and spec to match actual code
parent
9757b688
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
306 additions
and
218 deletions
+306
-218
DBUser API.md
Requirements/DBUser API.md
+119
-218
DBUser API.md
Specifications/DBUser API.md
+187
-0
No files found.
Requirements/DBUser API.md
View file @
3af7467f
...
...
@@ -11,35 +11,72 @@ For background about users, please see:
### What data and features must be provided
-
user must have a unique id, which we mint when creating the
database record
-
user must be able to authenticate (log in), which is currently handled outside DBUser by OpenID.
-
user must be authorized for specific system features, which relies on role(s).
-
user must have a unique id, which we mint when creating the
user database record in the database. The id is
supplied by the database as a record id, which is a unique integer. User must have a unique username, which
is some string; we currently use an email address for username
User id must be unique for all time, and thus, user ids may not be reused. We have a unique user id internal
to the system, which is the row id from table appuser. We do not currently have (or need) a textual user id
such as "mst3k", although email address must be unique to our system and serves an identifier. For example:
"mst3k@example.com" should be unique for all time, but (in theory) could be reused with a new, unique system
use rid.
-
support for data necessary to authenticate (log in), which is currently handled outside DBUser by
OpenID. This data includes an access token and expires time
Accounts need an active flag. Deleted accounts might be kept inactive, as an easy way to prevent accidentally
creating an account with the same name at some future time.
-
support for user authorization for specific system features. This requirement relies on role(s).
The list of features are described in more detail in other requirements docs although we list them below with
roles. Requirements here will cover implementation of authorization, and of management of authorization.
-
create user, requries a username which we default to the email address string. We also expect that the email
field will contain an email address. There was some discussion of multiple email addresses per user. That
has not been implemented.
-
update user, all fields except the ID and username; ID must never be modified. Changing username will have
unpredictable consequences.
-
delete or inactivate user
-
create role
-
add role to user
-
remove role from user
-
delete role (probably inadvisable, but we make it possible)
-
allow multiple roles per user
-
create session
-
extend session expiration time
-
add session to user
-
remove session from user
-
remove all sessions from user
User id must be unique for all time, and thus, user ids may not be reused. We have a numerical unique user id
internal to the system, which is the row id from table appuser. We added a textual username which
traditionally would be something such as "mst3k" or an email address. We default to using an email address as
username. Currently, email address in the email address field is not necessarily across our system, and
therefore is not a reliable identifier.
Accounts have an active flag. Deleted accounts might be kept in an inactive state in the database. It is
unclear what information in an inactive account is important historically. An inactive account would prevent
using that account's username due to username being unique in table appuser. User ID values cannot be
accidentally reused because the database creates them from a Postgres sequence.
Some features are described in more detail in other requirements docs although we list them below with
roles. Requirements here will cover data necessary to support implementation of authorization, and support
management of authorization.
Each user has account info:
-
id (not editable, database assigned record id)
-
id (not editable, database assigned integer record id)
-
username, unique string, we currently use an email address string
-
active (boolean)
-
first name
-
last name
-
full name
-
email which serves as a unique identifier in some special contexts
-
user id which may be email, should probably be unique
-
email, not unique
-
avatar
-
avatar small
-
avatar large
-
password, stored
encrypt
ed
-
password, stored
hash
ed
When logged in, a user has at least one "session", and the session has some associated data. We anticipate
that there could be multiple simultaneous sessions per user, and each session needs its own unique data.
...
...
@@ -51,16 +88,17 @@ Current session data includes:
The REST API requires the same session data. REST API users will have the same Au/Az constraints
The system has roles conceptually, extensively integrated throughout
. Each user is granted one or more roles.
Each user has one or more roles, as many as necessary.
The system has roles conceptually, extensively integrated throughout
the DBUser API. Each user is granted one
or more roles.
Each user has one or more roles, as many as necessary.
### Roles
The SNAC permission system is based entirely on roles (groups). SNAC is authorizing uses to run various
functions. Ownership is a non-concept, but essentially the system ("root") owns all functions. In a situation
like SNAC where there is a single owner, the concept of "owner" has no use in authorization. That leaves SNAC
with a role-only system.
The SNAC permission system is based entirely on roles (groups). SNAC is authorizing users to run various
functions. Ownership is a non-concept, but essentially the system owns all functions. In a situation like SNAC
where there is a single owner, the concept of "owner" has no utility in authorization. The Linux concept of
"other" doesn't apply to SNAC as "other" is only allowed to perform read-only actions such as search. That
leaves SNAC needing only a role system.
(Optional paragraph) Not having "files", there is no concept of "file has no privileges" for user, group, or
other. An example of what SNAC does not have is the shared web server situation where user grants privileges
...
...
@@ -70,7 +108,8 @@ user, no one in group user has any access. Actual access then is granted only to
read-write-execute (rwx) for that directory. Apache runs as suexec for each user, and thus each user's CGI
scripts gain access to only that user's directory via the user privs.
SNAC lacks this "subtractive" permission, and instead has only additive permissions.
SNAC lacks the Linux "subtractive" permission which is sometimes used with groups permissions. Instead SNAC
has only additive permissions.
In a global sense, the cumulative collection of users and roles is complicated. However, that complexity is
essential (not accidental) and on a per-user or per-role basis, things are very manageable. When managing the
...
...
@@ -78,20 +117,22 @@ system, imagine asking these typical, and manageable questions:
-
List all users affiliated with California Digital Library (CDL).
-
List all user affiliated with UC Irvine.
-
List all users affiliated with UC Irvine.
-
List all users who can enroll new users for any affiliation
-
List all users who can
enroll new users.
-
List all users who can
only enroll new users for NYPL
-
List all users who can publish constellations.
-
List all users who may run reports for their own affiliation.
Below is an example. Anyone who can log in can get a dashboard, so there are no specific dashboard permissions
(yet). The user id "public" and the role "research
er" may not make any sense. Everyone has role "Public HRT",
so there's no reason to restrict or authorize it. This table initially had a user id "public" with role
"Public HRT", and every user also had the role "Public HRT", but that is simply redundant. When it comes to
i
mplementation, the authorization system will use some convention for testing role. The feature "Public HRT"
can call a role test that always returns true
.
(yet). The user id "public" and the role "research
" may not make any sense. Conceptually, everyone has role
"Public HRT", so there's no reason to restrict or authorize it. In actual implementation the "what is public"
divide is simply any published record or read-only actition on published constellations. The table below
i
nitially had a user id "public" with role "Public HRT", and every user also had the role "Public HRT", but
that was simply redundant
.
The roles below are real, but do not imply any actual policy or any relation to persons living or dead.
...
...
@@ -102,64 +143,70 @@ Pulling a couple of random details from the table below, and wording them in Eng
| user | description | roles |
|------------------
+----------------+
-------------------------------------------------------------------------------------------------|
|------------------
|----------------|
-------------------------------------------------------------------------------------------------|
| Marley Turner | content expert | contribute, affiliation-none |
| Remy Roberts | power editor | contribute, change-status-any, change owner, publish, affiliation-any |
| Casey Miyazaki | editor CDL | contribute, change-status-own, publish, NACO approve, affiliation-cdl, report
er-own-affiliation
|
| Jessie Coughlin | admin NYPL | affiliation-nypl, enroll-own-affiliation report
er-own-affiliation, role-assign-own
|
| Avery Valenzuela | super admin | enroll-any, report
er-any, role-assign-any
|
| Casey Miyazaki | editor CDL | contribute, change-status-own, publish, NACO approve, affiliation-cdl, report
-own-affiliation
|
| Jessie Coughlin | admin NYPL | affiliation-nypl, enroll-own-affiliation report
-own-affiliation, role-assign-own
|
| Avery Valenzuela | super admin | enroll-any, report
-any, role-assign-any
|
Roles have a number of traits
:
Roles have a number of traits
.
-
Created by developers, and maintained by admins with role-granting privileges
-
There is (ideally) a single privilege per role
-
Roles and privileges must be coordinated with work flows and application features
-
One role exists per institutional affiliation
-
Every user has the implied role Public HRT
-
Roles are additive, and all roles of a user define that user's authorized functions
-
Roles are created and maintained by admins and developers.
-
Some instance roles (such as affiliation) can be created by admins as needed.
-
Roles (ideally) have a single privilege per role. Roles are very granular.
-
Roles and privileges must be coordinated with work flows and application features.
-
One role exists per institutional affiliation.
-
Every user has the conceptually role Public HRT, although no actual role exists for read-only access to published constellations
-
Potentially, we can have roles for ad hoc groups (sub-institution, department, professional orgs, etc.)
-
Roles can be deprecated, but re-purposing roles is inadvisable from a security standpoint
-
Need explicit, on-going policy guidance
-
Roles can be deprecated, but re-purposing roles is inadvisable from a security standpoint
.
-
Roles need explicit, on-going policy guidance.
Every account will have the "Public HRT" role which has the same privileges as the general public, but with a
TBD set of basic privileges including: search history, certain researcher reports. An account is not necessary
to use SNAC. Members of the public are mostly identical to Researchers. The primary feature gained by having
an account is a persistent dashboard.
The minimal role "Research" grants privileges for search history, and certain research reports. Members of
the public are mostly identical to Researchers. The primary feature gained by having an account is a
persistent dashboard. As already noted, "Public HRT" not an actual role, but instead is conceptual.
(Comment: I just noticed that roles are mostly verbs: research, contribute, delete, propose, approve, block,
embargo, enrole, assign. It seems like a nice idea to enshrine this as a convention. We would have to change
"administrator" to "administer", and we need to come up with a verbs for the remaining roles, especially
"affiliation".)
| Role | Role Description |
|------------------------------+-----------------------------------------------------------------------------|
| Public HRT | No account, but may use HRT public interfaces to SNAC |
| Researcher | (Same as Public HRT?) Use discovery interface and dashboard, has an account |
|------------------------------+----------------------------------------------------------------------------|
| Research | Use discovery interface and dashboard, has an account |
| Contribute | Create and edit constellations but cannot publish (contributor) |
| Publish | Approve constellation publication
(editor)
|
| Change status any | Change
status, removing locks, and so on, any affiliation
|
| Publish | Approve constellation publication
, change status to "published" (editor)
|
| Change status any | Change
any status, removing locks, and so on, any affiliation
|
| Change owner any | Change constellation user, changing which user has a lock, any affiliation |
| Change status own | Change
status, removing locks, and so on, own affiliation only
|
| Change status own | Change
any status, removing locks, and so on, own affiliation only
|
| Change owner own | Change constellation user, changing user lock, own affiliation only |
| Delete/embargo | Delete or embargo constellations (editor) |
| Propose delete/embargo | Propose delete or embargo |
| Ontology propose | Propose headings in ontologies, but cannot approve headings |
| Ontology approve | Approve ontology headings (editor) |
| Propose NACO | Create(?) NACO contributions, but not push(?) to NACO |
|
NACO approve/finalize/submit | Approve NACO contributions (editor)
|
|
Approve NACO | Approve, finalize, submit NACO contributions (editor)
|
| Enroll | Enroll new SNAC participants, create new users |
| Role assign own institution | Assign new roles for own-institution users |
| Role assign any institution | Assign new roles for any institution users |
| System administrator | Maintains server hardware and operating systems |
| Developer | Writes the SNAC application, a programmer |
| Web administrator | (duplicate? historical?) May perform admin tasks via the web interface |
| Database administrator
| Create and maintain the SQL database
|
| Database administrator
(DBA) | Create and maintain the SQL database
|
| Block upload | Do bulk uploads of EAC-CPF, finding aids, etc. |
| Reporter own | Run own-institutional reports |
| Reporter any | Run any report, super reporter |
| Report own | Run own-institutional reports |
| Report any | Run any report, super reporter |
| Report admin | Run special administrative reports |
| Affiliation X | Affiliated with institution X. |
| Affiliation any | Affiliated with all institutions, a super role (discuss?) |
More e
xample user types, with their role(s) and description.
E
xample user types, with their role(s) and description.
| User type | Role(s) | User Description |
...
...
@@ -167,176 +214,30 @@ More example user types, with their role(s) and description.
| Sysadmin | System administrator | Maintain server, backups, etc. |
| Database Administrator | DBA | Schema maintenance, data dumps, etc. |
| Software engineer | Developer + DBA | Coding, testing, QA, release management, data loading, etc. |
| Manager | Enroll + Role assign
+ Inst. Reporter
| SNAC accounts: create, manage, assign roles, run reports |
| Manager | Enroll + Role assign
own + Report own
| SNAC accounts: create, manage, assign roles, run reports |
| Peer vetting | Enroll | Approve moderators, reviewers, content experts |
| Moderator |
Editor-publish
| Approve maintenance changes, posting those changes |
| Reviewer/editor | Contribut
or + Editor-publish
| Maintainer privileges, interacts with moderators |
| Content expert | Contribut
or
| Domain expert, may have zero institutional roles |
| Documentary editor | Contribut
or
| (Any distinguishing roles?) |
| Maintenance | Contribut
or, constellation | May be older terminology for "contributor"
|
| Research
er | Researcher
| Use the discovery interface and history dashboard |
| Moderator |
Publish
| Approve maintenance changes, posting those changes |
| Reviewer/editor | Contribut
e + publish
| Maintainer privileges, interacts with moderators |
| Content expert | Contribut
e
| Domain expert, may have zero institutional roles |
| Documentary editor | Contribut
e
| (Any distinguishing roles?) |
| Maintenance | Contribut
e, constellation | May be older terminology for "contribute"
|
| Research
| Research
| Use the discovery interface and history dashboard |
| Archival description donor | Block upload | May do bulk uploads of EAC-CPF, finding aids, etc. |
| Name authority manager | Name authority | (superseded by Editor-NACO?) |
| Institutional admins |
Institutional reporter
| May run own-institutional reports |
| Public |
Public
| No SNAC account, single session dashboard |
| Institutional admins |
Report own
| May run own-institutional reports |
| Public |
n/a
| No SNAC account, single session dashboard |
| Contributor | Contribute + Ontology propose | Creates/edit constellations, propose ontology headings |
| Author | Contribute + Publish + Propose Del/Emb+Propose NACO |
A contributor, with additional privileges
|
| Author | Contribute + Publish + Propose Del/Emb+Propose NACO |
Contribute, with additional privileges
|
| Editor | Contribute + Publish + Delete/embargo + NACO | Review constellations, approve and publish |
| Author-NACO |
Create provisional NACO
| Creates NACO entries, sends to editor for submission |
| Administrator |
Author + editor + enroll + assign
| Everything, only own institution |
| Administrator-super | Administrator
+ any institution
| Admin plus assign roles for any user of any institution |
| Author-NACO |
Propose NACO
| Creates NACO entries, sends to editor for submission |
| Administrator |
Contributor roles + Editor roles + enroll + assign
| Everything, only own institution |
| Administrator-super | Administrator
roles + any institution
| Admin plus assign roles for any user of any institution |
### API
Most of the API depends on a User object. That object must at least contain an email address. When creating,
saving, or updating a user, all available fields are written to the database except id (aka appUserID). The ID
is generated from the database.
createUser() creates a new id, overwriting any existing id.
saveUser() requires a valid id in order to update. The ID is not changed.
readUser() requires a valid id. The ID is not changed.
A user object has only a single session. There may be several active sessions per account. We assume that each
HTTP request will include unique session, keeping all concurrent sessions separate.
Role management works.
---
`checkSessionActive(snac\data\User $user)`
Check that a session is active (not expired) for $user. Time is assumed to be "now". Return a $user with valid
appUserID upon success, or false on failure. Adds the user to the db if the user does not already
exist. Creates a session if a session does not already exist.
If a session exists, that session expires is checked against now() as UTC. If the session has expired, then
the session is deleted, and the $user token is cleared by setting 'access_token' to '' and expires to zero.
The user is created based on email being unique. Any existing userID inside $user is ignored, then
overwritten.
The new user is not assigned a default role, but there is a function to add a default role if we need that.
---
`createUser(snac\data\User $user)`
Add a user record. Minimal requirements is a unique email. Return the new User object. The current
implementation has no concept of failure. Adds a default role if we have one. We do not currently have a
default role.
---
`
saveUser(snac\data\User $user)`
Update a user record. Overwrite everthing else with values from the User object. Please contact the developers
before using this function.
---
`findUserID($email)`
Get the user id if you only know the email address. We assume the email addresses are unique. Returns integer appUserID or false.
---
`readUser($userID)`
Return a User object for the user id or email. Return false on failure. Fills in the role list in the User object.
---
`readUserByEmail($email)`
Return a User object based on email address. Return false on failure.
---
`disableUser(snac\data\User $user)`
Disable log in to this account. Update table appuser.active to false. Return true on success.
Proably has not been tested. The concept of inactive accounts is not well defined.
---
`roleList()`
List all system roles as a list of Role objects.
---
`addUserRole(snac\data\User $user, $newRole)`
Add a role to the User via table appuser_role_link. Return true on success. $newRole is a Role object.
---
`addDefaultRole($user)`
Add default roles to $user, if any default roles exist. Currently does nothing. If we had default roles, it
would change $user in place. Would return true on success, false otherwise.
---
`listUserRole($user)`
List all the roles a user currently has as an array of Role objects.
----
`checkRoleByLabel($user, $label)`
Check for role by label. Returns the role if user has it, else false;
----
`removeUserRole($user, $role)`
Remove a role from the User by deleting the role link from table appuser_role_link.
----
`createRole($label, $description)`
Create a new role with $label and $description. Return the role on success. Currently, it has no concept of
failure.
---
`checkPassword(snac\data\User $user, $passwd)`
Check $passwd matches the password stored for snac
\d
ata
\U
ser. Return true on success.
---
`addSession(snac\data\User $user)`
Add a new session token $user->getToken()
[
'access_token'
]
with expiration time $user->getToken()
[
'expires'
]
for $user. Update the session if $accessToken exists.
---
`sessionExists($user)`
Find out if a session exists and if that session is associated with $user, and has not expired.
---
`removeSession($user)`
Remove a session. Assume that tokens are unique, which is important. Delete all sessions with the token
$user->getToken()
[
'access_token'
]
matter what user has that token.
----
See the specifications for the API functions.
`clearAllSessions(snac\data\User $user)`
Delete all session records for $user.
[
User Management API Specifications
](
Specifications/DBUser
API.md)
----
Specifications/DBUser API.md
0 → 100644
View file @
3af7467f
### Introduction
Most of the API depends on a User object which contains a list of Role object. Before being written to the
database, a User must at least contain an username which we are defaulting to the email address string. After
being written to the database, a user must contain the userid (aka appUserID, aka id) and username. When
creating, saving, or updating a user, all available fields are written to the database except id (aka
appUserID) and username. The ID is generated from the database, and the username was supplied when the user
was first created. We assume that neither will ever change.
If there is an ID present in a User prior to the user being created, that ID will be overwritten. This might
occur where fields from a User come from an outside system with its own concept of user id.
createUser() creates a new id, overwriting any existing id in the User object
saveUser() requires a valid id in order to update. The ID is not changed.
readUser() requires a valid id. The ID is not changed.
A User object has only a single session. There may be several active sessions per account. We assume that each
HTTP request will include unique session, thus keeping all concurrent sessions separate.
### API
---
`checkSessionActive($user)`
Don't use this. Instead use granualar functions such as: sessionExists(), sessionActive(), addSession(),
sessionExtend(), readUser(), and createUser().
This does multiple actions including check that a session is active (not expired) for $user. Time is assumed
to be "now" UTC in seconds since the epoch. Return a $user with valid appUserID upon success, or false on
failure. Adds the user to the db if the user does not already exist. Creates a session with included token and
expires if a session does not already exist.
If a session exists, that session expiration time is checked against now() as UTC. If the session has expired,
then the session is deleted, and the User token is cleared by setting 'access_token' to '' and expires to
zero.
The User is created based on email being unique. Any existing userID inside $user is ignored, then
overwritten with the database supplied value which is an integer.
The new user is not assigned a default role, but there is a function to add a default role if we need that.
---
`createUser($user)`
Add a user record. Minimal requirements is a unique email. Return the new User object. The current
implementation has no concept of failure. Adds a default role if we have one. We do not currently have a
default role.
---
`
saveUser($user)`
Update a user record. Overwrite everthing except user id with values from the User object. Please contact the developers
before using this function because there is no sanity checking in the function. This function is currently
unused and while it seems reasonable to have this function, it may be removed.
---
`findUserID($email)`
Get the user id if you only know the email address. We assume the email addresses are unique. Returns integer appUserID or false.
This is a nice low level function, but you probably want the high level readUserByEmail() which returns a User object.
---
`readUser($userID)`
Return a User object for the user id or email. Return false on failure. Fills in the role list in the User
object. This is a nice low level function, but you probably want readUserByEmail() which returns a User object.
---
`readUserByEmail($email)`
Return a User object based on email address. Return false on failure.
---
`disableUser($user)`
Disable this account. Definition of "disable" is evolving. Update table appuser.active to false. Return true on success.
Proably has not been tested. The concept of inactive accounts is not well defined.
---
`roleList()`
List all system roles as a list of Role objects.
---
`addUserRole($user, $newRole)`
Add a role to the User via table appuser_role_link. Return true on success. $newRole is a Role object, and you
probably want to call roleList() to get a list of available roles.
---
`addDefaultRole($user)`
Add default roles to $user, if any default roles exist. Currently does nothing. If we had default roles, it
would change $user in place. Would return true on success, false otherwise.
---
`listUserRole($user)`
List all the roles a user currently has as an array of Role objects.
----
`checkRoleByLabel($user, $label)`
Check a User object for role by label. Returns the role if user has it, else false;
----
`removeUserRole($user, $role)`
Remove a role from the User by deleting the role link from table appuser_role_link. Returns true.
The User object is modified in place, getting the updated list of roles.
----
`createRole($label, $description)`
Create a new role with $label and $description. Return the role on success.
---
`checkPassword($user, $passwd)`
Check $passwd matches the password stored for User. Return true on success.
Not used with OpenID, and not tested, but it is very simple.
---
`addSession($user)`
Add a new session to the database for the token $user->getToken()
[
'access_token'
]
with expiration time
$user->getToken()
[
'expires'
]
for $user. Update the session if $accessToken exists.
---
`sessionExists($user)`
Find out if a session exists for this User. Expiration time is ignored, so this is only answers "Does the session exist?"
---
`removeSession($user)`
Remove a session. Assume that tokens are unique, which is important. Delete all sessions with the token
$user->getToken()
[
'access_token'
]
matter what user has that token.
----
`clearAllSessions($user)`
Delete all session records for $user.
---
`writePassword($user, $passwd)`
Write a hashed password to the database for User. The password itself it not part of the User object, so we
use some additional functions to manage passwords. This is not used during OpenID authentication.
----
`getSQL()`
Used only for testing. Returns the SQL object so that sql functions can be called directly.
---
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment