use quokka::{
helper::database::{
execute, query_all, query_one, query_optional, BaseRepository, PaginationOrder,
},
state::{Database, FromState},
};
#[derive(Clone, sqlx::FromRow, serde::Deserialize, serde::Serialize)]
pub struct Permission {
pub id: i32,
pub verb: String,
pub resource: String,
pub created_at: time::OffsetDateTime,
pub updated_at: time::OffsetDateTime,
}
#[derive(Clone, sqlx::FromRow, serde::Deserialize, serde::Serialize)]
pub struct UserPermission {
pub user_id: i32,
pub permission_id: i32,
pub created_at: time::OffsetDateTime,
pub updated_at: time::OffsetDateTime,
}
#[derive(Clone, sqlx::FromRow, serde::Deserialize, serde::Serialize)]
pub struct GroupPermission {
pub group_id: i32,
pub permission_id: i32,
pub created_at: time::OffsetDateTime,
pub updated_at: time::OffsetDateTime,
}
#[derive(Clone, FromState)]
pub struct PermissionRepository {
database: Database,
}
#[derive(Clone, FromState)]
pub struct UserPermissionRepository {
database: Database,
}
#[derive(Clone, FromState)]
pub struct GroupPermissionRepository {
database: Database,
}
impl BaseRepository for PermissionRepository {
type Entity = Permission;
type PkType = i32;
#[query_all(
query = "SELECT * FROM \"permission\" ORDER BY {#order_by} {#direction.to_string()} LIMIT {#page_size} OFFSET {#page_size * page}"
)]
async fn get_entities(
&self,
page: i32,
page_size: i32,
order_by: &'static str,
direction: PaginationOrder,
) -> quokka::Result<Vec<Self::Entity>>;
#[query_one(query = "SELECT * FROM \"permission\" WHERE id = {pk}")]
fn get_entity(&self, pk: Self::PkType) -> quokka::Result<Self::Entity>;
#[execute(
query = "UPDATE \"permission\" SET verb = {entity.verb}, resource = {entity.resource}, updated_at = NOW() WHERE id = {entity.id}",
write
)]
fn update_entity(&self, entity: Self::Entity) -> quokka::Result<u64>;
#[query_one(
query = "INSERT INTO \"permission\" (id, verb, resource) VALUES ({entity.id}, {entity.verb}, {entity.resource}) RETURNING *",
write
)]
fn create_entity(&self, entity: Self::Entity) -> quokka::Result<Self::Entity>;
#[execute(query = "DELETE FROM \"permission\" WHERE id = {pk}", write)]
fn delete_entity(&self, pk: Self::PkType) -> quokka::Result<u64>;
}
impl PermissionRepository {
#[query_optional(query = r#"SELECT "permission".*
FROM "permission"
INNER JOIN "user_permission" up
ON up.permission_id = "permission".id
INNER JOIN "user"
ON "user".id = up.user_id
WHERE "user".username = {username} AND "permission".verb = {verb} AND {resource} LIKE "permission".resource"#)]
pub async fn get_of_user(
&self,
username: &str,
verb: &str,
resource: &str,
) -> quokka::Result<Option<Permission>>;
#[query_optional(query = r#"SELECT "permission".*
FROM "permission"
INNER JOIN "group_permission" gp
ON gp.permission_id = "permission".id
INNER JOIN "group"
ON "group".id = gp.group_id
WHERE "group".name = {name} AND "permission".verb = {verb} AND {resource} LIKE "permission".resource"#)]
pub async fn get_of_group(
&self,
name: &str,
verb: &str,
resource: &str,
) -> quokka::Result<Option<Permission>>;
}
impl BaseRepository for UserPermissionRepository {
type Entity = UserPermission;
type PkType = (i32, i32);
#[query_all(
query = "SELECT * FROM \"user_permission\" ORDER BY {#order_by} {#direction.to_string()} LIMIT {#page_size} OFFSET {#page_size * page}"
)]
async fn get_entities(
&self,
page: i32,
page_size: i32,
order_by: &'static str,
direction: PaginationOrder,
) -> quokka::Result<Vec<Self::Entity>>;
#[query_one(
query = "SELECT * FROM \"user_permission\" WHERE user_id = {pk.0} AND permission_id = {pk.1}"
)]
fn get_entity(&self, pk: Self::PkType) -> quokka::Result<Self::Entity>;
#[execute(
query = "UPDATE \"user_permission\" SET updated_at = NOW() WHERE user_id = {entity.user_id} AND permission_id = {entity.permission_id}",
write
)]
fn update_entity(&self, entity: Self::Entity) -> quokka::Result<u64>;
#[query_one(
query = "INSERT INTO \"user_permission\" (user_id, permission_id) VALUES ({entity.user_id}, {entity.permission_id}) RETURNING *",
write
)]
fn create_entity(&self, entity: Self::Entity) -> quokka::Result<Self::Entity>;
#[execute(
query = "DELETE FROM \"user_permission\" WHERE user_id = {pk.0} AND permission_id = {pk.1}",
write
)]
fn delete_entity(&self, pk: Self::PkType) -> quokka::Result<u64>;
}
impl BaseRepository for GroupPermissionRepository {
type Entity = GroupPermission;
type PkType = (i32, i32);
#[query_all(
query = "SELECT * FROM \"group_permission\" ORDER BY {#order_by} {#direction.to_string()} LIMIT {#page_size} OFFSET {#page_size * page}"
)]
async fn get_entities(
&self,
page: i32,
page_size: i32,
order_by: &'static str,
direction: PaginationOrder,
) -> quokka::Result<Vec<Self::Entity>>;
#[query_one(
query = "SELECT * FROM \"group_permission\" WHERE group_id = {pk.0} AND permission_id = {pk.1}"
)]
fn get_entity(&self, pk: Self::PkType) -> quokka::Result<Self::Entity>;
#[execute(
query = "UPDATE \"group_permission\" SET updated_at = NOW() WHERE group_id = {entity.group_id} AND permission_id = {entity.permission_id}",
write
)]
fn update_entity(&self, entity: Self::Entity) -> quokka::Result<u64>;
#[query_one(
query = "INSERT INTO \"group_permission\" (group_id, permission_id) VALUES ({entity.group_id}, {entity.permission_id}) RETURNING *",
write
)]
fn create_entity(&self, entity: Self::Entity) -> quokka::Result<Self::Entity>;
#[execute(
query = "DELETE FROM \"group_permission\" WHERE group_id = {pk.0} AND permission_id = {pk.1}",
write
)]
fn delete_entity(&self, pk: Self::PkType) -> quokka::Result<u64>;
}