Skip to content

Commit

Permalink
Lots of refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
augustuswm committed Feb 26, 2024
1 parent 71d801b commit cf25ae0
Show file tree
Hide file tree
Showing 26 changed files with 2,464 additions and 2,248 deletions.
80 changes: 42 additions & 38 deletions v-api-permissions/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use std::{collections::BTreeSet, fmt::Debug, hash::Hash};
use std::{collections::BTreeSet, fmt::Debug};

use diesel::{
backend::Backend,
Expand All @@ -17,26 +17,16 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize};
use uuid::Uuid;

pub trait Permission:
Clone + Debug + Ord + Eq + PartialEq + Hash + Serialize + DeserializeOwned + Send + Sync + 'static
Clone + Debug + Serialize + DeserializeOwned + PartialEq + Send + Sync + 'static
{
}
impl<T> Permission for T where
T: Clone
+ Debug
+ Ord
+ Eq
+ PartialEq
+ Hash
+ Serialize
+ DeserializeOwned
+ Send
+ Sync
+ 'static
T: Clone + Debug + Serialize + DeserializeOwned + PartialEq + Send + Sync + 'static
{
}

#[derive(Clone, Debug)]
pub struct Caller<T: Permission> {
#[derive(Debug, Clone)]
pub struct Caller<T> {
pub id: Uuid,
pub permissions: Permissions<T>,
}
Expand Down Expand Up @@ -66,14 +56,11 @@ where

#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, FromSqlRow, AsExpression, JsonSchema)]
#[diesel(sql_type = Jsonb)]
pub struct Permissions<T: Ord>(BTreeSet<T>);
pub struct Permissions<T>(Vec<T>);

impl<T> Default for Permissions<T>
where
T: Permission,
{
impl<T> Default for Permissions<T> {
fn default() -> Self {
Self::new()
Self(Vec::new())
}
}

Expand All @@ -82,7 +69,7 @@ where
T: Permission,
{
pub fn new() -> Self {
Self(BTreeSet::new())
Self(Vec::new())
}

pub fn all(&self, permissions: &[&T]) -> bool {
Expand All @@ -100,24 +87,40 @@ where
}

pub fn intersect(&self, other: &Permissions<T>) -> Permissions<T> {
self.0
.intersection(&other.0)
.into_iter()
.map(|p| p.clone())
.collect::<BTreeSet<_>>()
.into()
let mut new_permissions = vec![];
for perm in &self.0 {
if other.iter().any(|other_perm| perm == other_perm) {
new_permissions.push(perm.clone());
}
}

Permissions(new_permissions)
}

pub fn insert(&mut self, item: T) -> bool {
self.0.insert(item)
if !self.can(&item) {
self.0.push(item);
true
} else {
false
}
}

pub fn append(&mut self, other: &mut Self) {
self.0.append(&mut other.0)
}

pub fn remove(&mut self, item: &T) -> bool {
self.0.remove(item)
let mut removed = false;
self.0.retain(|perm| {
if perm == item {
removed = true;
}

perm == item
});

removed
}

pub fn iter(&self) -> impl Iterator<Item = &T> {
Expand All @@ -142,16 +145,17 @@ where
T: Permission,
{
fn from(value: BTreeSet<T>) -> Self {
Self(value)
Self(value.into_iter().collect::<Vec<_>>())
}
}

impl<T> From<Vec<T>> for Permissions<T>
impl<T, U> From<Vec<T>> for Permissions<U>
where
T: Permission,
U: Permission + From<T>,
{
fn from(value: Vec<T>) -> Self {
Self::from_iter(value)
Self::from_iter(value.into_iter().map(|v| v.into()))
}
}

Expand All @@ -160,15 +164,15 @@ where
T: Permission,
{
fn from_iter<Iter: IntoIterator<Item = T>>(iter: Iter) -> Self {
let mut set = BTreeSet::new();
set.extend::<Iter>(iter);
Self(set)
let mut v = Vec::new();
v.extend::<Iter>(iter);
Self(v)
}
}

impl<T> ToSql<Jsonb, Pg> for Permissions<T>
where
T: Serialize + Debug + Ord,
T: Serialize + Debug,
{
fn to_sql(&self, out: &mut Output<Pg>) -> serialize::Result {
let value = serde_json::to_value(self)?;
Expand All @@ -178,7 +182,7 @@ where

impl<T> FromSql<Jsonb, Pg> for Permissions<T>
where
T: DeserializeOwned + Debug + Ord,
T: DeserializeOwned + Debug,
{
fn from_sql(bytes: <Pg as Backend>::RawValue<'_>) -> deserialize::Result<Self> {
let value = <serde_json::Value as FromSql<Jsonb, Pg>>::from_sql(bytes)?;
Expand Down
18 changes: 12 additions & 6 deletions v-api/src/authn/jwt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,14 @@ use serde::{Deserialize, Serialize};
use thiserror::Error;
use tracing::instrument;
use uuid::Uuid;
use v_api_permissions::Permission;
use v_model::ApiUserProvider;
use v_api_permissions::{Permission, Permissions};
use v_model::{ApiUser, ApiUserProvider};

use crate::{config::AsymmetricKey, context::VContext, permissions::ApiPermission, User};
use crate::{
config::AsymmetricKey,
context::VContext,
permissions::{AsScope, PermissionStorage, VPermission},
};

use super::{Signer, SigningKeyError};

Expand Down Expand Up @@ -62,13 +66,14 @@ pub struct Claims {
impl Claims {
pub fn new<T>(
ctx: &VContext<T>,
user: &User,
user: &ApiUser<T>,
provider: &ApiUserProvider,
scope: Option<Vec<String>>,
expires_at: DateTime<Utc>,
) -> Self
where
T: Permission + From<ApiPermission>,
T: Permission + From<VPermission> + AsScope,
Permissions<T>: PermissionStorage,
{
Claims {
iss: ctx.public_url().to_string(),
Expand All @@ -86,7 +91,8 @@ impl Claims {
impl Jwt {
pub async fn new<T>(ctx: &VContext<T>, token: &str) -> Result<Self, JwtError>
where
T: Permission + From<ApiPermission>,
T: Permission + From<VPermission> + AsScope,
Permissions<T>: PermissionStorage,
{
tracing::trace!("Decode JWT from headers");

Expand Down
10 changes: 9 additions & 1 deletion v-api/src/authn/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ 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,
config::AsymmetricKey,
context::ApiContext,
permissions::{PermissionStorage, VAppPermission},
util::{cloud_kms_client, response::unauthorized},
};

Expand Down Expand Up @@ -59,7 +61,13 @@ impl Debug for AuthToken {

impl AuthToken {
// Extract an AuthToken from a Dropshot request
pub async fn extract(rqctx: &RequestContext<impl ApiContext>) -> Result<AuthToken, AuthError> {
pub async fn extract<T>(
rqctx: &RequestContext<impl ApiContext<AppPermissions = T>>,
) -> Result<AuthToken, AuthError>
where
T: VAppPermission,
Permissions<T>: PermissionStorage,
{
// Ensure there is a bearer, without it there is nothing else to do
let bearer = BearerAuth::from_request(rqctx).await.map_err(|err| {
tracing::info!(?err, "Failed to extract bearer auth");
Expand Down
Loading

0 comments on commit cf25ae0

Please sign in to comment.