Skip to content

Commit

Permalink
More permission refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
augustuswm committed Mar 19, 2024
1 parent a186214 commit 42abba4
Show file tree
Hide file tree
Showing 19 changed files with 368 additions and 213 deletions.
8 changes: 3 additions & 5 deletions v-api/src/authn/jwt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use serde::{Deserialize, Serialize};
use thiserror::Error;
use tracing::instrument;
use uuid::Uuid;
use v_api_permissions::{Permission, Permissions};
use v_api_permissions::Permission;
use v_model::{ApiUser, ApiUserProvider};

use crate::{
Expand Down Expand Up @@ -72,8 +72,7 @@ impl Claims {
expires_at: DateTime<Utc>,
) -> Self
where
T: Permission + From<VPermission> + AsScope,
Permissions<T>: PermissionStorage,
T: Permission + From<VPermission> + AsScope + PermissionStorage,
{
Claims {
iss: ctx.public_url().to_string(),
Expand All @@ -91,8 +90,7 @@ impl Claims {
impl Jwt {
pub async fn new<T>(ctx: &VContext<T>, token: &str) -> Result<Self, JwtError>
where
T: Permission + From<VPermission> + AsScope,
Permissions<T>: PermissionStorage,
T: Permission + From<VPermission> + AsScope + PermissionStorage,
{
tracing::trace!("Decode JWT from headers");

Expand Down
4 changes: 1 addition & 3 deletions v-api/src/authn/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ use sha2::{Digest, Sha256};
use std::{fmt::Debug, sync::Arc};
use thiserror::Error;
use tracing::instrument;
use v_api_permissions::Permissions;

use crate::{
authn::key::RawApiKey,
Expand Down Expand Up @@ -65,8 +64,7 @@ impl AuthToken {
rqctx: &RequestContext<impl ApiContext<AppPermissions = T>>,
) -> Result<AuthToken, AuthError>
where
T: VAppPermission,
Permissions<T>: PermissionStorage,
T: VAppPermission + PermissionStorage,
{
// Ensure there is a bearer, without it there is nothing else to do
let bearer = BearerAuth::from_request(rqctx).await.map_err(|err| {
Expand Down
17 changes: 7 additions & 10 deletions v-api/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,7 @@ impl From<VContextCallerError> for HttpError {

impl<T, U> VContextWithCaller<T> for RequestContext<U>
where
T: Permission + From<VPermission> + AsScope,
Permissions<T>: PermissionStorage,
T: Permission + From<VPermission> + AsScope + PermissionStorage,
U: ApiContext<AppPermissions = T>,
{
async fn as_ctx(&self) -> Result<(&VContext<T>, Caller<T>), VContextCallerError> {
Expand Down Expand Up @@ -228,8 +227,7 @@ enum BasePermissions<T: Permission> {

impl<T> VContext<T>
where
T: Permission + From<VPermission> + AsScope,
Permissions<T>: PermissionStorage,
T: Permission + From<VPermission> + AsScope + PermissionStorage,
{
pub async fn new(
public_url: String,
Expand Down Expand Up @@ -351,8 +349,7 @@ where
BasePermissions::Full => user_permissions.clone(),
BasePermissions::Restricted(permissions) => {
let token_permissions =
permissions.expand(&user.id, Some(&user_permissions));

T::expand(permissions, &user.id, Some(&user_permissions));
token_permissions.intersect(&user_permissions)
}
};
Expand Down Expand Up @@ -509,7 +506,7 @@ where
let permissions = groups
.into_iter()
.fold(Permissions::new(), |mut aggregate, group| {
let mut expanded = group.permissions.expand(&user.id, Some(&user.permissions));
let mut expanded = T::expand(&group.permissions, &user.id, Some(&user.permissions));

tracing::trace!(group_id = ?group.id, group_name = ?group.name, permissions = ?expanded, "Transformed group into permission set");
aggregate.append(&mut expanded);
Expand Down Expand Up @@ -810,7 +807,7 @@ where
.await
.map(|opt| {
opt.map(|mut user| {
user.permissions = user.permissions.expand(&user.id, None);
user.permissions = T::expand(&user.permissions, &user.id, None);
user
})
})
Expand Down Expand Up @@ -853,7 +850,7 @@ where
permissions: permissions,
groups: groups,
};
new_user.permissions = new_user.permissions.contract(&new_user.id);
new_user.permissions = T::contract(&new_user.permissions, &new_user.id);
ApiUserStore::upsert(&*self.storage, new_user)
.await
.to_resource_result()
Expand All @@ -872,7 +869,7 @@ where
&VPermission::UpdateApiUser(api_user.id).into(),
&VPermission::UpdateApiUserAll.into(),
]) {
api_user.permissions = api_user.permissions.contract(&api_user.id);
api_user.permissions = T::contract(&api_user.permissions, &api_user.id);
ApiUserStore::upsert(&*self.storage, api_user)
.await
.to_resource_result()
Expand Down
53 changes: 18 additions & 35 deletions v-api/src/endpoints/api_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,7 @@ pub async fn get_self_op<T, U>(
rqctx: &RequestContext<impl ApiContext<AppPermissions = T>>,
) -> Result<HttpResponseOk<GetUserResponse<U>>, HttpError>
where
T: VAppPermission,
Permissions<T>: PermissionStorage,
T: VAppPermission + PermissionStorage,
U: VAppPermissionResponse + From<T> + JsonSchema,
{
let ctx = rqctx.v_ctx();
Expand All @@ -100,8 +99,7 @@ pub async fn get_api_user_op<T, U>(
path: Path<ApiUserPath>,
) -> Result<HttpResponseOk<GetUserResponse<U>>, HttpError>
where
T: VAppPermission,
Permissions<T>: PermissionStorage,
T: VAppPermission + PermissionStorage,
U: VAppPermissionResponse + From<T> + JsonSchema,
{
let ctx = rqctx.v_ctx();
Expand Down Expand Up @@ -132,8 +130,7 @@ pub async fn create_api_user_op<T, U>(
body: TypedBody<ApiUserUpdateParams<T>>,
) -> Result<HttpResponseCreated<ApiUser<U>>, HttpError>
where
T: VAppPermission + JsonSchema,
Permissions<T>: PermissionStorage,
T: VAppPermission + JsonSchema + PermissionStorage,
U: VAppPermissionResponse + From<T> + JsonSchema,
{
let ctx = rqctx.v_ctx();
Expand All @@ -150,8 +147,7 @@ pub async fn create_api_user_inner<T, U>(
body: ApiUserUpdateParams<T>,
) -> Result<HttpResponseCreated<ApiUser<U>>, HttpError>
where
T: VAppPermission + JsonSchema,
Permissions<T>: PermissionStorage,
T: VAppPermission + JsonSchema + PermissionStorage,
U: VAppPermissionResponse + From<T> + JsonSchema,
{
let user = ctx
Expand All @@ -173,8 +169,7 @@ pub async fn update_api_user_op<T, U>(
body: ApiUserUpdateParams<T>,
) -> Result<HttpResponseOk<ApiUser<U>>, HttpError>
where
T: VAppPermission,
Permissions<T>: PermissionStorage,
T: VAppPermission + PermissionStorage,
U: VAppPermissionResponse + From<T> + JsonSchema,
{
let ctx = rqctx.v_ctx();
Expand All @@ -190,8 +185,7 @@ pub async fn update_api_user_inner<T, U>(
body: ApiUserUpdateParams<T>,
) -> Result<HttpResponseOk<ApiUser<U>>, HttpError>
where
T: VAppPermission,
Permissions<T>: PermissionStorage,
T: VAppPermission + PermissionStorage,
U: VAppPermissionResponse + From<T> + JsonSchema,
{
let user = ctx
Expand All @@ -214,8 +208,7 @@ pub async fn list_api_user_tokens_op<T, U>(
path: ApiUserPath,
) -> Result<HttpResponseOk<Vec<ApiKeyResponse<U>>>, HttpError>
where
T: VAppPermission,
Permissions<T>: PermissionStorage,
T: VAppPermission + PermissionStorage,
U: VAppPermissionResponse + From<T> + JsonSchema,
{
let ctx = rqctx.v_ctx();
Expand All @@ -230,8 +223,7 @@ pub async fn list_api_user_tokens_inner<T, U>(
path: ApiUserPath,
) -> Result<HttpResponseOk<Vec<ApiKeyResponse<U>>>, HttpError>
where
T: VAppPermission,
Permissions<T>: PermissionStorage,
T: VAppPermission + PermissionStorage,
U: VAppPermissionResponse + From<T> + JsonSchema,
{
tracing::info!("Fetch token list");
Expand Down Expand Up @@ -277,8 +269,7 @@ pub async fn create_api_user_token_op<T, U>(
body: ApiKeyCreateParams<T>,
) -> Result<HttpResponseCreated<InitialApiKeyResponse<U>>, HttpError>
where
T: VAppPermission,
Permissions<T>: PermissionStorage,
T: VAppPermission + PermissionStorage,
U: VAppPermissionResponse + From<T> + JsonSchema,
{
let ctx = rqctx.v_ctx();
Expand All @@ -294,8 +285,7 @@ pub async fn create_api_user_token_inner<T, U>(
body: ApiKeyCreateParams<T>,
) -> Result<HttpResponseCreated<InitialApiKeyResponse<U>>, HttpError>
where
T: VAppPermission,
Permissions<T>: PermissionStorage,
T: VAppPermission + PermissionStorage,
U: VAppPermissionResponse + From<T> + JsonSchema,
{
let api_user = ctx.get_api_user(&caller, &path.identifier).await?;
Expand Down Expand Up @@ -344,8 +334,7 @@ pub async fn get_api_user_token_op<T, U>(
path: ApiUserTokenPath,
) -> Result<HttpResponseOk<ApiKeyResponse<U>>, HttpError>
where
T: VAppPermission,
Permissions<T>: PermissionStorage,
T: VAppPermission + PermissionStorage,
U: VAppPermissionResponse + From<T> + JsonSchema,
{
let ctx = rqctx.v_ctx();
Expand All @@ -360,8 +349,7 @@ pub async fn get_api_user_token_inner<T, U>(
path: ApiUserTokenPath,
) -> Result<HttpResponseOk<ApiKeyResponse<U>>, HttpError>
where
T: VAppPermission,
Permissions<T>: PermissionStorage,
T: VAppPermission + PermissionStorage,
U: VAppPermissionResponse + From<T> + JsonSchema,
{
let token = ctx
Expand All @@ -381,8 +369,7 @@ pub async fn delete_api_user_token_op<T, U>(
path: ApiUserTokenPath,
) -> Result<HttpResponseOk<ApiKeyResponse<U>>, HttpError>
where
T: VAppPermission,
Permissions<T>: PermissionStorage,
T: VAppPermission + PermissionStorage,
U: VAppPermissionResponse + From<T> + JsonSchema,
{
let ctx = rqctx.v_ctx();
Expand All @@ -397,8 +384,7 @@ pub async fn delete_api_user_token_inner<T, U>(
path: ApiUserTokenPath,
) -> Result<HttpResponseOk<ApiKeyResponse<U>>, HttpError>
where
T: VAppPermission,
Permissions<T>: PermissionStorage,
T: VAppPermission + PermissionStorage,
U: VAppPermissionResponse + From<T> + JsonSchema,
{
let token = ctx
Expand All @@ -424,8 +410,7 @@ pub async fn add_api_user_to_group_op<T, U>(
body: AddGroupBody,
) -> Result<HttpResponseOk<ApiUser<U>>, HttpError>
where
T: VAppPermission,
Permissions<T>: PermissionStorage,
T: VAppPermission + PermissionStorage,
U: VAppPermissionResponse + From<T> + JsonSchema,
{
let ctx = rqctx.v_ctx();
Expand All @@ -451,8 +436,7 @@ pub async fn remove_api_user_from_group_op<T, U>(
path: ApiUserRemoveGroupPath,
) -> Result<HttpResponseOk<ApiUser<U>>, HttpError>
where
T: VAppPermission,
Permissions<T>: PermissionStorage,
T: VAppPermission + PermissionStorage,
U: VAppPermissionResponse + From<T> + JsonSchema,
{
let ctx = rqctx.v_ctx();
Expand All @@ -474,14 +458,13 @@ pub struct ApiUserProviderLinkPayload {
}

#[instrument(skip(rqctx), err(Debug))]
pub async fn link_provider_op<T, U>(
pub async fn link_provider_op<T>(
rqctx: &RequestContext<impl ApiContext<AppPermissions = T>>,
path: ApiUserPath,
body: ApiUserProviderLinkPayload,
) -> Result<HttpResponseUpdatedNoContent, HttpError>
where
T: VAppPermission,
Permissions<T>: PermissionStorage,
T: VAppPermission + PermissionStorage,
{
let ctx = rqctx.v_ctx();
let auth = ctx.authn_token(&rqctx).await?;
Expand Down
4 changes: 1 addition & 3 deletions v-api/src/endpoints/api_user_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use tracing::instrument;
use uuid::Uuid;
use v_api_permissions::Permissions;

use crate::{
context::ApiContext,
Expand Down Expand Up @@ -39,8 +38,7 @@ pub async fn create_link_token_op<T>(
body: TypedBody<ApiUserLinkRequestPayload>,
) -> Result<HttpResponseOk<ApiUserLinkRequestResponse>, HttpError>
where
T: VAppPermission,
Permissions<T>: PermissionStorage,
T: VAppPermission + PermissionStorage,
{
let ctx = rqctx.v_ctx();
let auth = ctx.authn_token(&rqctx).await?;
Expand Down
12 changes: 4 additions & 8 deletions v-api/src/endpoints/group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ pub async fn get_groups_op<T, U>(
rqctx: &RequestContext<impl ApiContext<AppPermissions = T>>,
) -> Result<HttpResponseOk<Vec<AccessGroup<U>>>, HttpError>
where
T: VAppPermission,
Permissions<T>: PermissionStorage,
T: VAppPermission + PermissionStorage,
U: From<T> + Permission + JsonSchema,
{
let ctx = rqctx.v_ctx();
Expand Down Expand Up @@ -70,8 +69,7 @@ pub async fn create_group_op<T, U>(
body: AccessGroupUpdateParams<T>,
) -> Result<HttpResponseCreated<AccessGroup<U>>, HttpError>
where
T: VAppPermission,
Permissions<T>: PermissionStorage,
T: VAppPermission + PermissionStorage,
U: From<T> + Permission + JsonSchema,
{
let ctx = rqctx.v_ctx();
Expand Down Expand Up @@ -104,8 +102,7 @@ pub async fn update_group_op<T, U>(
body: AccessGroupUpdateParams<T>,
) -> Result<HttpResponseOk<AccessGroup<U>>, HttpError>
where
T: VAppPermission,
Permissions<T>: PermissionStorage,
T: VAppPermission + PermissionStorage,
U: From<T> + Permission + JsonSchema,
{
let ctx = rqctx.v_ctx();
Expand All @@ -132,8 +129,7 @@ pub async fn delete_group_op<T, U>(
path: AccessGroupPath,
) -> Result<HttpResponseOk<AccessGroup<U>>, HttpError>
where
T: VAppPermission,
Permissions<T>: PermissionStorage,
T: VAppPermission + PermissionStorage,
U: From<T> + Permission + JsonSchema,
{
let ctx = rqctx.v_ctx();
Expand Down
Loading

0 comments on commit 42abba4

Please sign in to comment.