Allow organisations to be marked as public, granting VISIBLE to everyone
Fixes #25
Diff
chartered-db/src/crates.rs | 5 +++++
chartered-db/src/organisations.rs | 35 +++++++++++++++++++++++++----------
chartered-db/src/schema.rs | 1 +
migrations/2021-08-31-214501_create_crates_table/up.sql | 3 ++-
chartered-web/src/endpoints/web_api/crates/mod.rs | 2 +-
chartered-web/src/endpoints/web_api/crates/recently_created.rs | 2 +-
6 files changed, 31 insertions(+), 17 deletions(-)
@@ -90,6 +90,11 @@
crate::schema::user_organisation_permissions::permissions.nullable(),
0,
))
.bitwise_or(diesel::dsl::sql::<diesel::sql_types::Integer>(&format!(
"(CASE WHEN {} THEN {} OR 0 END)",
"organisations.public",
UserPermission::VISIBLE.bits(),
)))
};
}
@@ -1,5 +1,6 @@
use crate::{
crates::Crate, permissions::UserPermission, users::User, BitwiseExpressionMethods, Error,
coalesce, crates::Crate, permissions::UserPermission, users::User, BitwiseExpressionMethods,
Error,
};
use super::{
@@ -12,23 +13,36 @@
use std::sync::Arc;
macro_rules! select_permissions {
() => {
coalesce(
crate::schema::user_organisation_permissions::permissions.nullable(),
0,
)
.bitwise_or(diesel::dsl::sql::<diesel::sql_types::Integer>(&format!(
"COALESCE(CASE WHEN {} THEN {} OR 0 END, 0)",
"public",
UserPermission::VISIBLE.bits(),
)))
};
}
#[derive(Identifiable, Queryable, Associations, PartialEq, Eq, Hash, Debug)]
pub struct Organisation {
pub id: i32,
pub uuid: SqlUuid,
pub name: String,
pub description: String,
pub public: bool,
}
impl Organisation {
pub async fn list(conn: ConnectionPool, requesting_user_id: i32) -> Result<Vec<Organisation>> {
use user_organisation_permissions::dsl::permissions;
tokio::task::spawn_blocking(move || {
let conn = conn.get()?;
organisations::table
.inner_join(
.left_join(
user_organisation_permissions::table.on(user_organisation_permissions::user_id
.eq(requesting_user_id)
.and(
@@ -37,7 +51,7 @@
)),
)
.filter(
permissions
select_permissions!()
.bitwise_and(UserPermission::VISIBLE.bits())
.eq(UserPermission::VISIBLE.bits()),
)
@@ -68,17 +82,10 @@
)),
)
.filter(organisation_name.eq(given_name))
.select((
user_organisation_permissions::dsl::permissions.nullable(),
organisations::all_columns,
))
.get_result::<(Option<UserPermission>, _)>(&conn)
.select((select_permissions!(), organisations::all_columns))
.get_result(&conn)
.optional()?
.ok_or(Error::MissingOrganisation)?;
let permissions = permissions.ok_or(Error::MissingOrganisationPermission(
UserPermission::VISIBLE,
))?;
Ok(OrganisationWithPermissions {
organisation,
@@ -36,6 +36,7 @@
uuid -> Binary,
name -> Text,
description -> Text,
public -> Bool,
}
}
@@ -16,7 +16,8 @@
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
uuid BINARY(128) NOT NULL UNIQUE,
name VARCHAR(255) NOT NULL UNIQUE,
description TEXT NOT NULL DEFAULT ""
description TEXT NOT NULL DEFAULT "",
public BOOLEAN NOT NULL DEFAULT FALSE
);
INSERT INTO organisations (id, uuid, name, description) VALUES (1, X'936DA01F9ABD4D9D80C702AF85C822A8', "core", "My first organisation");
@@ -1,9 +1,9 @@
mod info;
mod members;
mod most_downloaded;
mod recently_created;
mod recently_updated;
mod search;
mod recently_created;
use axum::{
body::{Body, BoxBody},
@@ -1,8 +1,8 @@
use axum::{extract, Json};
use chartered_db::{crates::Crate, users::User, ConnectionPool};
use chrono::{DateTime, TimeZone, Utc};
use serde::Serialize;
use std::sync::Arc;
use chrono::{DateTime, TimeZone, Utc};
use thiserror::Error;
#[derive(Error, Debug)]