-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Store user info in DB and make them searchable in ACL UI (#1027)
Fixes #951 (also removing our dummy users from the code, unblocking the release) The main goal of this PR was to make the ACL UI user selection work nicely. I.e. that one can search through users to add user entries to the ACL. Previously we had a bunch of hardcoded dummy users (which also made us unable to release Tobira). This is now done, but lots of related changed had to be done as well. There is also a configuration option which controls whether users can actually be searched by name or whether they can only be found by typing the exact username/email. The latter mode is the default for data privacy reasons. User information is remembered whenever a user logs into Tobira or does anything there. It is also possible to import users from a JSON file. **Important**: this PR introduces a breaking change as it makes a "user role" mandatory for users. See second commit. I doubt this is a problem for anyone, but it's still technically breaking. --- This can probably be reviewed commit by commit. The commit messages should be read for sure. However, the changes to `ui/Access.tsx` are likely very annoying to review because it's also lots of refactoring, over multiple commits. So yeah, not 100% sure how to best approach that. --- Finally, there are a few things that still have to be improved. But not in this PR, it's already large enough. I will create issues for these after merging. - [ ] Potentially add some basic user stats to `/~metrics`, e.g. "active user in last 24h - [ ] Re-add the paste functionality - [ ] Stop sending a list of all known groups to the frontend, that makes stuff slow.
- Loading branch information
Showing
47 changed files
with
1,367 additions
and
372 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"ROLE_USER_SABINE": { "username": "sabine", "displayName": "Sabine Rudolfs", "email": "[email protected]" }, | ||
"ROLE_USER_BJOERK": { "username": "björk", "displayName": "Prof. Björk Guðmundsdóttir", "email": "[email protected]" }, | ||
"ROLE_USER_MORGAN": { "username": "morgan", "displayName": "Morgan Yu", "email": "[email protected]" }, | ||
"ROLE_USER_JOSE": { "username": "jose", "displayName": "José Carreño Quiñones" } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
use juniper::GraphQLObject; | ||
use postgres_types::BorrowToSql; | ||
|
||
use crate::{api::{util::TranslatedString, Context, err::ApiResult}, db::util::select}; | ||
|
||
|
||
|
||
|
||
pub(crate) type Acl = Vec<AclItem>; | ||
|
||
/// A role being granted permission to perform certain actions. | ||
#[derive(Debug, GraphQLObject)] | ||
#[graphql(context = Context)] | ||
pub(crate) struct AclItem { | ||
/// Role. In arrays of AclItems, no two items have the same `role`. | ||
pub role: String, | ||
|
||
/// List of actions this role can perform (e.g. `read`, `write`, | ||
/// `annotate`). This is a set, i.e. no duplicate elements. | ||
pub actions: Vec<String>, | ||
|
||
/// Additional info we have about the role. Is `null` if the role is unknown | ||
/// or is `ROLE_ANONYMOUS`, `ROLE_ADMIN` or `ROLE_USER`, as those are | ||
/// handled in a special way in the frontend. | ||
pub info: Option<RoleInfo>, | ||
} | ||
|
||
/// Some extra information we know about a role. | ||
#[derive(Debug, GraphQLObject)] | ||
#[graphql(context = Context)] | ||
pub(crate) struct RoleInfo { | ||
/// A user-facing label for this role (group or person). If the label does | ||
/// not depend on the language (e.g. a name), `{ "_": "Peter" }` is | ||
/// returned. | ||
pub label: TranslatedString<String>, | ||
|
||
/// For user roles this is `null`. For groups, it defines a list of other | ||
/// group roles that this role implies. I.e. a user with this role always | ||
/// also has these other roles. | ||
pub implies: Option<Vec<String>>, | ||
|
||
/// Is `true` if this role represents a large group. Used to warn users | ||
/// accidentally giving write access to large groups. | ||
pub large: bool, | ||
} | ||
|
||
pub(crate) async fn load_for<P, I>( | ||
context: &Context, | ||
raw_roles: &str, | ||
params: I, | ||
) -> ApiResult<Acl> | ||
where | ||
P: BorrowToSql, | ||
I: IntoIterator<Item = P> + std::fmt::Debug, | ||
I::IntoIter: ExactSizeIterator, | ||
{ | ||
// First: load labels for roles from the DB. For that we use the `users` | ||
// and `known_groups` table. | ||
let (selection, mapping) = select!( | ||
role: "roles.role", | ||
actions, | ||
implies, | ||
large: "coalesce(known_groups.large, false)", | ||
label: "coalesce( | ||
known_groups.label, | ||
case when users.display_name is null | ||
then null | ||
else hstore('_', users.display_name) | ||
end | ||
)", | ||
); | ||
let sql = format!("\ | ||
with raw_roles as ({raw_roles}), | ||
roles as ( | ||
select role, array_agg(action) as actions | ||
from raw_roles | ||
group by role | ||
) | ||
select {selection} | ||
from roles | ||
left join users on users.user_role = role | ||
left join known_groups on known_groups.role = roles.role\ | ||
"); | ||
|
||
context.db.query_mapped(&sql, params, |row| { | ||
AclItem { | ||
role: mapping.role.of(&row), | ||
actions: mapping.actions.of(&row), | ||
info: mapping.label.of::<Option<_>>(&row).map(|label| RoleInfo { | ||
label, | ||
implies: mapping.implies.of(&row), | ||
large: mapping.large.of(&row), | ||
}), | ||
} | ||
}).await.map_err(Into::into) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.