quokka-admin 0.1.0

An admin panel for quokka
Documentation
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 Group {
    pub id: i32,
    pub name: String,
    pub created_at: time::OffsetDateTime,
    pub updated_at: time::OffsetDateTime,
}

#[derive(Clone, sqlx::FromRow, serde::Deserialize, serde::Serialize)]
pub struct UserGroup {
    pub user_id: i32,
    pub group_id: i32,
    pub created_at: time::OffsetDateTime,
    pub updated_at: time::OffsetDateTime,
}

#[derive(Clone, FromState)]
pub struct GroupRepository {
    database: Database,
}

#[derive(Clone, FromState)]
pub struct UserGroupRepository {
    database: Database,
}

impl GroupRepository {
    #[query_optional(query = "SELECT * FROM \"group\" WHERE name = {name}")]
    pub async fn get_group_by_name(&self, name: &str) -> quokka::Result<Option<Group>>;
}

impl BaseRepository for GroupRepository {
    type Entity = Group;

    type PkType = i32;

    #[query_all(
        query = "SELECT * FROM \"group\" 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\" WHERE id = {pk}")]
    fn get_entity(&self, pk: Self::PkType) -> quokka::Result<Self::Entity>;

    #[execute(
        query = "UPDATE \"group\" SET name = {entity.name}, updated_at = NOW() WHERE id = {entity.id}",
        write
    )]
    fn update_entity(&self, entity: Self::Entity) -> quokka::Result<u64>;

    #[query_one(
        query = "INSERT INTO \"group\" (id, name) VALUES ({entity.id}, {entity.name}) RETURNING *",
        write
    )]
    fn create_entity(&self, entity: Self::Entity) -> quokka::Result<Self::Entity>;

    #[execute(query = "DELETE FROM \"group\" WHERE id = {pk}", write)]
    fn delete_entity(&self, pk: Self::PkType) -> quokka::Result<u64>;
}

impl GroupRepository {
    #[query_all(query = r#"SELECT "group".*
        FROM "group"
        INNER JOIN "user_group" gu
            ON "group".id = gu.group_id
        INNER JOIN "user"
            ON "user".id = gu.user_id
        WHERE
            "user".username = {username}"#)]
    pub async fn get_group_of_user(&self, username: &str) -> quokka::Result<Vec<Group>>;
}

impl BaseRepository for UserGroupRepository {
    type Entity = UserGroup;

    type PkType = (i32, i32);

    #[query_all(
        query = "SELECT * FROM \"user_group\" 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_group\" WHERE user_id = {pk.0} AND group_id = {pk.1}"
    )]
    fn get_entity(&self, pk: Self::PkType) -> quokka::Result<Self::Entity>;

    /// There is nothing to be updated here
    #[execute(
        query = "UPDATE \"user_group\" SET updated_at = NOW() WHERE user_id = {entity.user_id} AND group_id = {entity.group_id}",
        write
    )]
    fn update_entity(&self, entity: Self::Entity) -> quokka::Result<u64>;

    #[query_one(
        query = "INSERT INTO \"user_group\" (user_id, group_id) VALUES ({entity.user_id}, {entity.group_id}) RETURNING *",
        write
    )]
    fn create_entity(&self, entity: Self::Entity) -> quokka::Result<Self::Entity>;

    #[execute(
        query = "DELETE FROM \"user_group\" WHERE user_id = {pk.0} AND group_id = {pk.1}",
        write
    )]
    fn delete_entity(&self, pk: Self::PkType) -> quokka::Result<u64>;
}