1use quokka::{
2 helper::database::{
3 execute, query_all, query_one, query_optional, BaseRepository, PaginationOrder,
4 },
5 state::{Database, FromState},
6};
7
8#[derive(Clone, sqlx::FromRow, serde::Deserialize, serde::Serialize)]
9pub struct Permission {
10 pub id: i32,
11 pub verb: String,
12 pub resource: String,
13 pub created_at: time::OffsetDateTime,
14 pub updated_at: time::OffsetDateTime,
15}
16
17#[derive(Clone, sqlx::FromRow, serde::Deserialize, serde::Serialize)]
18pub struct UserPermission {
19 pub user_id: i32,
20 pub permission_id: i32,
21 pub created_at: time::OffsetDateTime,
22 pub updated_at: time::OffsetDateTime,
23}
24
25#[derive(Clone, sqlx::FromRow, serde::Deserialize, serde::Serialize)]
26pub struct GroupPermission {
27 pub group_id: i32,
28 pub permission_id: i32,
29 pub created_at: time::OffsetDateTime,
30 pub updated_at: time::OffsetDateTime,
31}
32
33#[derive(Clone, FromState)]
34pub struct PermissionRepository {
35 database: Database,
36}
37
38#[derive(Clone, FromState)]
39pub struct UserPermissionRepository {
40 database: Database,
41}
42
43#[derive(Clone, FromState)]
44pub struct GroupPermissionRepository {
45 database: Database,
46}
47
48impl BaseRepository for PermissionRepository {
49 type Entity = Permission;
50
51 type PkType = i32;
52
53 #[query_all(
54 query = "SELECT * FROM \"permission\" ORDER BY {#order_by} {#direction.to_string()} LIMIT {#page_size} OFFSET {#page_size * page}"
55 )]
56 async fn get_entities(
57 &self,
58 page: i32,
59 page_size: i32,
60 order_by: &'static str,
61 direction: PaginationOrder,
62 ) -> quokka::Result<Vec<Self::Entity>>;
63
64 #[query_one(query = "SELECT * FROM \"permission\" WHERE id = {pk}")]
65 fn get_entity(&self, pk: Self::PkType) -> quokka::Result<Self::Entity>;
66
67 #[execute(
68 query = "UPDATE \"permission\" SET verb = {entity.verb}, resource = {entity.resource}, updated_at = NOW() WHERE id = {entity.id}",
69 write
70 )]
71 fn update_entity(&self, entity: Self::Entity) -> quokka::Result<u64>;
72
73 #[query_one(
74 query = "INSERT INTO \"permission\" (id, verb, resource) VALUES ({entity.id}, {entity.verb}, {entity.resource}) RETURNING *",
75 write
76 )]
77 fn create_entity(&self, entity: Self::Entity) -> quokka::Result<Self::Entity>;
78
79 #[execute(query = "DELETE FROM \"permission\" WHERE id = {pk}", write)]
80 fn delete_entity(&self, pk: Self::PkType) -> quokka::Result<u64>;
81}
82
83impl PermissionRepository {
84 #[query_optional(query = r#"SELECT "permission".*
85 FROM "permission"
86 INNER JOIN "user_permission" up
87 ON up.permission_id = "permission".id
88 INNER JOIN "user"
89 ON "user".id = up.user_id
90 WHERE "user".username = {username} AND "permission".verb = {verb} AND {resource} LIKE "permission".resource"#)]
91 pub async fn get_of_user(
92 &self,
93 username: &str,
94 verb: &str,
95 resource: &str,
96 ) -> quokka::Result<Option<Permission>>;
97
98 #[query_optional(query = r#"SELECT "permission".*
99 FROM "permission"
100 INNER JOIN "group_permission" gp
101 ON gp.permission_id = "permission".id
102 INNER JOIN "group"
103 ON "group".id = gp.group_id
104 WHERE "group".name = {name} AND "permission".verb = {verb} AND {resource} LIKE "permission".resource"#)]
105 pub async fn get_of_group(
106 &self,
107 name: &str,
108 verb: &str,
109 resource: &str,
110 ) -> quokka::Result<Option<Permission>>;
111}
112
113impl BaseRepository for UserPermissionRepository {
114 type Entity = UserPermission;
115
116 type PkType = (i32, i32);
117
118 #[query_all(
119 query = "SELECT * FROM \"user_permission\" ORDER BY {#order_by} {#direction.to_string()} LIMIT {#page_size} OFFSET {#page_size * page}"
120 )]
121 async fn get_entities(
122 &self,
123 page: i32,
124 page_size: i32,
125 order_by: &'static str,
126 direction: PaginationOrder,
127 ) -> quokka::Result<Vec<Self::Entity>>;
128
129 #[query_one(
130 query = "SELECT * FROM \"user_permission\" WHERE user_id = {pk.0} AND permission_id = {pk.1}"
131 )]
132 fn get_entity(&self, pk: Self::PkType) -> quokka::Result<Self::Entity>;
133
134 #[execute(
136 query = "UPDATE \"user_permission\" SET updated_at = NOW() WHERE user_id = {entity.user_id} AND permission_id = {entity.permission_id}",
137 write
138 )]
139 fn update_entity(&self, entity: Self::Entity) -> quokka::Result<u64>;
140
141 #[query_one(
142 query = "INSERT INTO \"user_permission\" (user_id, permission_id) VALUES ({entity.user_id}, {entity.permission_id}) RETURNING *",
143 write
144 )]
145 fn create_entity(&self, entity: Self::Entity) -> quokka::Result<Self::Entity>;
146
147 #[execute(
148 query = "DELETE FROM \"user_permission\" WHERE user_id = {pk.0} AND permission_id = {pk.1}",
149 write
150 )]
151 fn delete_entity(&self, pk: Self::PkType) -> quokka::Result<u64>;
152}
153
154impl BaseRepository for GroupPermissionRepository {
155 type Entity = GroupPermission;
156
157 type PkType = (i32, i32);
158
159 #[query_all(
160 query = "SELECT * FROM \"group_permission\" ORDER BY {#order_by} {#direction.to_string()} LIMIT {#page_size} OFFSET {#page_size * page}"
161 )]
162 async fn get_entities(
163 &self,
164 page: i32,
165 page_size: i32,
166 order_by: &'static str,
167 direction: PaginationOrder,
168 ) -> quokka::Result<Vec<Self::Entity>>;
169
170 #[query_one(
171 query = "SELECT * FROM \"group_permission\" WHERE group_id = {pk.0} AND permission_id = {pk.1}"
172 )]
173 fn get_entity(&self, pk: Self::PkType) -> quokka::Result<Self::Entity>;
174
175 #[execute(
177 query = "UPDATE \"group_permission\" SET updated_at = NOW() WHERE group_id = {entity.group_id} AND permission_id = {entity.permission_id}",
178 write
179 )]
180 fn update_entity(&self, entity: Self::Entity) -> quokka::Result<u64>;
181
182 #[query_one(
183 query = "INSERT INTO \"group_permission\" (group_id, permission_id) VALUES ({entity.group_id}, {entity.permission_id}) RETURNING *",
184 write
185 )]
186 fn create_entity(&self, entity: Self::Entity) -> quokka::Result<Self::Entity>;
187
188 #[execute(
189 query = "DELETE FROM \"group_permission\" WHERE group_id = {pk.0} AND permission_id = {pk.1}",
190 write
191 )]
192 fn delete_entity(&self, pk: Self::PkType) -> quokka::Result<u64>;
193}