caps and delete
This commit is contained in:
+52
-12
@@ -19,6 +19,8 @@ use uuid::Uuid;
|
||||
use crate::{
|
||||
auth::{
|
||||
api_tokens::{find_active_token_by_secret, touch_api_token},
|
||||
capability_sets::load_capability_set,
|
||||
jwt::{AccessTokenContext, PrincipalKind},
|
||||
passkeys::{
|
||||
AuthenticationChallengeResponse, PasskeyLoginFinishPayload, PasskeyLoginStartPayload,
|
||||
PasskeyRegistrationFinishPayload, PasskeySummary, RegistrationChallengeResponse,
|
||||
@@ -27,8 +29,8 @@ use crate::{
|
||||
},
|
||||
error::{AppError, AppResult},
|
||||
models::{
|
||||
ApiTokenCapability, MagicToken, MagicTokenKind, NewUser, NewUserSession, TenantStatus,
|
||||
User, UserSession,
|
||||
ApiCapability, MagicToken, MagicTokenKind, NewUser, NewUserSession, TenantStatus, User,
|
||||
UserMembership, UserSession,
|
||||
},
|
||||
schema::{
|
||||
magic_tokens::dsl as magic_dsl, tenants::dsl as tenant_dsl,
|
||||
@@ -160,7 +162,7 @@ pub enum LoginResponseVariants {
|
||||
crate::auth::passkeys::PasskeyRegistrationFinishPayload,
|
||||
crate::auth::passkeys::PasskeyLoginStartPayload,
|
||||
crate::auth::passkeys::PasskeyLoginFinishPayload,
|
||||
crate::models::ApiTokenCapability,
|
||||
crate::models::ApiCapability,
|
||||
))
|
||||
)]
|
||||
pub struct AuthApiDoc;
|
||||
@@ -230,7 +232,7 @@ pub async fn api_token_exchange(
|
||||
|
||||
let mut conn = state.db_unscoped()?;
|
||||
|
||||
let token = find_active_token_by_secret(&mut conn, None, secret, ApiTokenCapability::Api)?
|
||||
let token = find_active_token_by_secret(&mut conn, None, secret, ApiCapability::ProfileRead)?
|
||||
.ok_or_else(AppError::unauthorized)?;
|
||||
|
||||
let user: User = dsl::users.find(token.user_id).first(&mut conn)?;
|
||||
@@ -239,21 +241,36 @@ pub async fn api_token_exchange(
|
||||
let membership = memberships_dsl::user_memberships
|
||||
.filter(memberships_dsl::user_id.eq(user.id))
|
||||
.filter(memberships_dsl::tenant_id.eq(token.tenant_id))
|
||||
.select(memberships_dsl::tenant_id)
|
||||
.first::<Uuid>(&mut conn)
|
||||
.first::<UserMembership>(&mut conn)
|
||||
.optional()?;
|
||||
clear_user_guc(&mut conn)?;
|
||||
|
||||
if membership.is_none() {
|
||||
return Err(AppError::unauthorized());
|
||||
}
|
||||
let membership = membership.ok_or_else(AppError::unauthorized)?;
|
||||
|
||||
let membership_capability_set = membership.capability_set_id.ok_or_else(|| {
|
||||
AppError::new(
|
||||
StatusCode::FORBIDDEN,
|
||||
"membership has no capability set assigned",
|
||||
)
|
||||
})?;
|
||||
|
||||
let token_capability_set = load_capability_set(&mut conn, token.capability_set_id)?;
|
||||
let _membership_set = load_capability_set(&mut conn, membership_capability_set)?;
|
||||
|
||||
apply_tenant_guc(&mut conn, token.tenant_id)?;
|
||||
touch_api_token(&mut conn, token.id)?;
|
||||
|
||||
let access_token = state
|
||||
.jwt
|
||||
.generate_token(user.id, token.tenant_id, &user.username)
|
||||
.generate_token(AccessTokenContext {
|
||||
user_id: user.id,
|
||||
tenant_id: token.tenant_id,
|
||||
username: user.username.clone(),
|
||||
principal_kind: PrincipalKind::ApiToken,
|
||||
principal_id: token.id,
|
||||
capability_set_id: token_capability_set.id,
|
||||
cap_version: token_capability_set.cap_version,
|
||||
})
|
||||
.map_err(AppError::from)?;
|
||||
|
||||
let tenant_name: String = tenant_dsl::tenants
|
||||
@@ -856,10 +873,33 @@ fn issue_session(
|
||||
clear_user_guc(conn)?;
|
||||
clear_user_session_hash(conn)?;
|
||||
|
||||
let membership: UserMembership = memberships_dsl::user_memberships
|
||||
.filter(memberships_dsl::user_id.eq(user.id))
|
||||
.filter(memberships_dsl::tenant_id.eq(tenant_id))
|
||||
.first(conn)?;
|
||||
|
||||
let capability_set_id = membership.capability_set_id.ok_or_else(|| {
|
||||
AppError::new(
|
||||
StatusCode::FORBIDDEN,
|
||||
"membership has no capability set assigned",
|
||||
)
|
||||
})?;
|
||||
|
||||
let capability_set = load_capability_set(conn, capability_set_id)?;
|
||||
|
||||
let now = Utc::now();
|
||||
let session_id = Uuid::new_v4();
|
||||
let access_token = state
|
||||
.jwt
|
||||
.generate_token(user.id, tenant_id, &user.username)
|
||||
.generate_token(AccessTokenContext {
|
||||
user_id: user.id,
|
||||
tenant_id,
|
||||
username: user.username.clone(),
|
||||
principal_kind: PrincipalKind::UserSession,
|
||||
principal_id: session_id,
|
||||
capability_set_id,
|
||||
cap_version: capability_set.cap_version,
|
||||
})
|
||||
.map_err(AppError::from)?;
|
||||
|
||||
let tenant_name: String = tenant_dsl::tenants
|
||||
@@ -873,7 +913,7 @@ fn issue_session(
|
||||
let refresh_expires_at = now + ChronoDuration::days(state.config.refresh_token_expiry_days);
|
||||
|
||||
let new_session = NewUserSession {
|
||||
id: Uuid::new_v4(),
|
||||
id: session_id,
|
||||
user_id: user.id,
|
||||
token_hash: session_hash,
|
||||
issued_at: now.naive_utc(),
|
||||
|
||||
Reference in New Issue
Block a user