🏡 index : ~doyle/chartered.git

author Jordan Doyle <jordan@doyle.la> 2021-09-07 16:19:49.0 +01:00:00
committer Jordan Doyle <jordan@doyle.la> 2021-09-07 16:19:49.0 +01:00:00
commit
998db8626d668c412e6d1cbc2cbc633e4418e10d [patch]
tree
8a7de61ed238d41c1836e9fb9080b15feed4ce81
parent
c492deffa5a75e3771b7f62a59ce033c16ddca0b
download
998db8626d668c412e6d1cbc2cbc633e4418e10d.tar.gz

Implement user permissions as bitflags



Diff

 Cargo.lock                |  1 +
 chartered-db/Cargo.toml   |  1 +
 chartered-db/src/users.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index c1ff201..e59057b 100644
--- a/Cargo.lock
+++ a/Cargo.lock
@@ -186,6 +186,7 @@
name = "chartered-db"
version = "0.1.0"
dependencies = [
 "bitflags",
 "chartered-fs",
 "diesel",
 "displaydoc",
diff --git a/chartered-db/Cargo.toml b/chartered-db/Cargo.toml
index f22b0af..d458b17 100644
--- a/chartered-db/Cargo.toml
+++ a/chartered-db/Cargo.toml
@@ -8,6 +8,7 @@
[dependencies]
chartered-fs = { path = "../chartered-fs" }

bitflags = "1"
diesel = { version = "1", features = ["sqlite", "r2d2"] }
displaydoc = "0.2"
itertools = "0.10"
diff --git a/chartered-db/src/users.rs b/chartered-db/src/users.rs
index 34dec2e..5be434e 100644
--- a/chartered-db/src/users.rs
+++ a/chartered-db/src/users.rs
@@ -1,8 +1,9 @@
use super::{
    schema::{user_api_keys, user_crate_permissions, user_ssh_keys, users},
    ConnectionPool, Result,
};
use diesel::{prelude::*, Associations, Identifiable, Queryable};
use std::sync::Arc;

#[derive(Identifiable, Queryable, Associations, PartialEq, Eq, Hash, Debug)]
pub struct User {
@@ -36,8 +37,6 @@
    ) -> Result<Option<User>> {
        use crate::schema::user_ssh_keys::dsl::ssh_key;

        eprintln!("looking up by ssh key: {:x?}", given_ssh_key);

        tokio::task::spawn_blocking(move || {
            let conn = conn.get()?;

@@ -47,6 +46,26 @@
                .select((users::dsl::id, users::dsl::username))
                .get_result(&conn)
                .optional()?)
        })
        .await?
    }

    pub async fn accessible_crates(
        self: Arc<Self>,
        conn: ConnectionPool,
    ) -> Result<Vec<(UserCratePermissionValue, crate::crates::Crate)>> {
        use crate::schema::crates;

        tokio::task::spawn_blocking(move || {
            let conn = conn.get()?;

            Ok(UserCratePermission::belonging_to(&*self)
                .inner_join(crate::schema::crates::table)
                .select((
                    user_crate_permissions::permissions,
                    (crates::dsl::id, crates::dsl::name),
                ))
                .load(&conn)?)
        })
        .await?
    }
@@ -58,6 +77,30 @@
    pub id: i32,
    pub user_id: i32,
    pub api_key: String,
}

bitflags::bitflags! {
    #[derive(FromSqlRow, AsExpression)]
    pub struct UserCratePermissionValue: i32 {
        const VISIBLE         = 0b0000_0000_0000_0000_0000_0000_0000_0001;
        const PUBLISH_VERSION = 0b0000_0000_0000_0000_0000_0000_0000_0010;
        const YANK_VERSION    = 0b0000_0000_0000_0000_0000_0000_0000_0100;
        const MANAGE_USERS    = 0b0000_0000_0000_0000_0000_0000_0000_1000;
    }
}

impl<B: diesel::backend::Backend> diesel::deserialize::FromSql<diesel::sql_types::Integer, B>
    for UserCratePermissionValue
where
    i32: diesel::deserialize::FromSql<diesel::sql_types::Integer, B>,
{
    fn from_sql(
        bytes: Option<&B::RawValue>,
    ) -> std::result::Result<UserCratePermissionValue, Box<dyn std::error::Error + Send + Sync>>
    {
        let val = i32::from_sql(bytes)?;
        Ok(UserCratePermissionValue::from_bits_truncate(val))
    }
}

#[derive(Identifiable, Queryable, Associations, PartialEq, Eq, Hash, Debug)]
@@ -66,7 +109,7 @@
    pub id: i32,
    pub user_id: i32,
    pub crate_id: i32,
    pub permissions: i32,
    pub permissions: UserCratePermissionValue,
}

#[derive(Identifiable, Queryable, Associations, PartialEq, Eq, Hash, Debug)]