1#![allow(clippy::suspicious_else_formatting)]
2#![allow(clippy::toplevel_ref_arg)]
3use crate::Error;
4use casbin::{error::AdapterError, Error as CasbinError, Filter, Result};
5use sqlx::error::Error as SqlxError;
6
7use crate::models::{CasbinRule, NewCasbinRule};
8
9#[cfg(feature = "postgres")]
10use sqlx::postgres::PgQueryResult;
11
12#[cfg(feature = "mysql")]
13use sqlx::mysql::MySqlQueryResult;
14
15#[cfg(feature = "sqlite")]
16use sqlx::sqlite::SqliteQueryResult;
17
18#[cfg(feature = "postgres")]
19pub type ConnectionPool = sqlx::PgPool;
20
21#[cfg(feature = "mysql")]
22pub type ConnectionPool = sqlx::MySqlPool;
23
24#[cfg(feature = "sqlite")]
25pub type ConnectionPool = sqlx::SqlitePool;
26
27#[cfg(feature = "postgres")]
28pub async fn new(conn: &ConnectionPool) -> Result<PgQueryResult> {
29 sqlx::query!(
30 "CREATE TABLE IF NOT EXISTS casbin_rule (
31 id SERIAL PRIMARY KEY,
32 ptype VARCHAR NOT NULL,
33 v0 VARCHAR NOT NULL,
34 v1 VARCHAR NOT NULL,
35 v2 VARCHAR NOT NULL,
36 v3 VARCHAR NOT NULL,
37 v4 VARCHAR NOT NULL,
38 v5 VARCHAR NOT NULL,
39 CONSTRAINT unique_key_sqlx_adapter UNIQUE(ptype, v0, v1, v2, v3, v4, v5)
40 );
41 "
42 )
43 .execute(conn)
44 .await
45 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))
46}
47
48#[cfg(feature = "sqlite")]
49pub async fn new(conn: &ConnectionPool) -> Result<SqliteQueryResult> {
50 sqlx::query!(
51 "CREATE TABLE IF NOT EXISTS casbin_rule (
52 id SERIAL PRIMARY KEY,
53 ptype VARCHAR NOT NULL,
54 v0 VARCHAR NOT NULL,
55 v1 VARCHAR NOT NULL,
56 v2 VARCHAR NOT NULL,
57 v3 VARCHAR NOT NULL,
58 v4 VARCHAR NOT NULL,
59 v5 VARCHAR NOT NULL,
60 CONSTRAINT unique_key_sqlx_adapter UNIQUE(ptype, v0, v1, v2, v3, v4, v5)
61 );
62 "
63 )
64 .execute(conn)
65 .await
66 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))
67}
68
69#[cfg(feature = "mysql")]
70pub async fn new(conn: &ConnectionPool) -> Result<MySqlQueryResult> {
71 sqlx::query!(
72 "CREATE TABLE IF NOT EXISTS casbin_rule (
73 id INT NOT NULL AUTO_INCREMENT,
74 ptype VARCHAR(12) NOT NULL,
75 v0 VARCHAR(128) NOT NULL,
76 v1 VARCHAR(128) NOT NULL,
77 v2 VARCHAR(128) NOT NULL,
78 v3 VARCHAR(128) NOT NULL,
79 v4 VARCHAR(128) NOT NULL,
80 v5 VARCHAR(128) NOT NULL,
81 PRIMARY KEY(id),
82 CONSTRAINT unique_key_sqlx_adapter UNIQUE(ptype, v0, v1, v2, v3, v4, v5)
83 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;",
84 )
85 .execute(conn)
86 .await
87 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))
88}
89
90#[cfg(feature = "postgres")]
91pub async fn remove_policy(conn: &ConnectionPool, pt: &str, rule: Vec<String>) -> Result<bool> {
92 let rule = normalize_casbin_rule(rule);
93 sqlx::query!(
94 "DELETE FROM casbin_rule WHERE
95 ptype = $1 AND
96 v0 = $2 AND
97 v1 = $3 AND
98 v2 = $4 AND
99 v3 = $5 AND
100 v4 = $6 AND
101 v5 = $7",
102 pt,
103 rule[0],
104 rule[1],
105 rule[2],
106 rule[3],
107 rule[4],
108 rule[5]
109 )
110 .execute(conn)
111 .await
112 .map(|n| PgQueryResult::rows_affected(&n) == 1)
113 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))
114}
115
116#[cfg(feature = "sqlite")]
117pub async fn remove_policy(conn: &ConnectionPool, pt: &str, rule: Vec<String>) -> Result<bool> {
118 let rule = normalize_casbin_rule(rule);
119 sqlx::query!(
120 "DELETE FROM casbin_rule WHERE
121 ptype = ?1 AND
122 v0 = ?2 AND
123 v1 = ?3 AND
124 v2 = ?4 AND
125 v3 = ?5 AND
126 v4 = ?6 AND
127 v5 = ?7",
128 pt,
129 rule[0],
130 rule[1],
131 rule[2],
132 rule[3],
133 rule[4],
134 rule[5]
135 )
136 .execute(conn)
137 .await
138 .map(|n| SqliteQueryResult::rows_affected(&n) == 1)
139 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))
140}
141
142#[cfg(feature = "mysql")]
143pub async fn remove_policy(conn: &ConnectionPool, pt: &str, rule: Vec<String>) -> Result<bool> {
144 let rule = normalize_casbin_rule(rule);
145 sqlx::query!(
146 "DELETE FROM casbin_rule WHERE
147 ptype = ? AND
148 v0 = ? AND
149 v1 = ? AND
150 v2 = ? AND
151 v3 = ? AND
152 v4 = ? AND
153 v5 = ?",
154 pt,
155 rule[0],
156 rule[1],
157 rule[2],
158 rule[3],
159 rule[4],
160 rule[5]
161 )
162 .execute(conn)
163 .await
164 .map(|n| MySqlQueryResult::rows_affected(&n) == 1)
165 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))
166}
167
168#[cfg(feature = "postgres")]
169pub async fn remove_policies(
170 conn: &ConnectionPool,
171 pt: &str,
172 rules: Vec<Vec<String>>,
173) -> Result<bool> {
174 let mut transaction = conn
175 .begin()
176 .await
177 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
178 for rule in rules {
179 let rule = normalize_casbin_rule(rule);
180 sqlx::query!(
181 "DELETE FROM casbin_rule WHERE
182 ptype = $1 AND
183 v0 = $2 AND
184 v1 = $3 AND
185 v2 = $4 AND
186 v3 = $5 AND
187 v4 = $6 AND
188 v5 = $7",
189 pt,
190 rule[0],
191 rule[1],
192 rule[2],
193 rule[3],
194 rule[4],
195 rule[5]
196 )
197 .execute(&mut *transaction)
198 .await
199 .and_then(|n| {
200 if PgQueryResult::rows_affected(&n) == 1 {
201 Ok(true)
202 } else {
203 Err(SqlxError::RowNotFound)
204 }
205 })
206 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
207 }
208 transaction
209 .commit()
210 .await
211 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
212 Ok(true)
213}
214
215#[cfg(feature = "sqlite")]
216pub async fn remove_policies(
217 conn: &ConnectionPool,
218 pt: &str,
219 rules: Vec<Vec<String>>,
220) -> Result<bool> {
221 let mut transaction = conn
222 .begin()
223 .await
224 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
225 for rule in rules {
226 let rule = normalize_casbin_rule(rule);
227 sqlx::query!(
228 "DELETE FROM casbin_rule WHERE
229 ptype = ?1 AND
230 v0 = ?2 AND
231 v1 = ?3 AND
232 v2 = ?4 AND
233 v3 = ?5 AND
234 v4 = ?6 AND
235 v5 = ?7",
236 pt,
237 rule[0],
238 rule[1],
239 rule[2],
240 rule[3],
241 rule[4],
242 rule[5]
243 )
244 .execute(&mut *transaction)
245 .await
246 .and_then(|n| {
247 if SqliteQueryResult::rows_affected(&n) == 1 {
248 Ok(true)
249 } else {
250 Err(SqlxError::RowNotFound)
251 }
252 })
253 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
254 }
255 transaction
256 .commit()
257 .await
258 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
259 Ok(true)
260}
261
262#[cfg(feature = "mysql")]
263pub async fn remove_policies(
264 conn: &ConnectionPool,
265 pt: &str,
266 rules: Vec<Vec<String>>,
267) -> Result<bool> {
268 let mut transaction = conn
269 .begin()
270 .await
271 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
272 for rule in rules {
273 let rule = normalize_casbin_rule(rule);
274 sqlx::query!(
275 "DELETE FROM casbin_rule WHERE
276 ptype = ? AND
277 v0 = ? AND
278 v1 = ? AND
279 v2 = ? AND
280 v3 = ? AND
281 v4 = ? AND
282 v5 = ?",
283 pt,
284 rule[0],
285 rule[1],
286 rule[2],
287 rule[3],
288 rule[4],
289 rule[5]
290 )
291 .execute(&mut *transaction)
292 .await
293 .and_then(|n| {
294 if MySqlQueryResult::rows_affected(&n) == 1 {
295 Ok(true)
296 } else {
297 Err(SqlxError::RowNotFound)
298 }
299 })
300 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
301 }
302 transaction
303 .commit()
304 .await
305 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
306 Ok(true)
307}
308
309#[cfg(feature = "postgres")]
310pub async fn remove_filtered_policy(
311 conn: &ConnectionPool,
312 pt: &str,
313 field_index: usize,
314 field_values: Vec<String>,
315) -> Result<bool> {
316 let field_values = normalize_casbin_rule_option(field_values);
317 let boxed_query = if field_index == 5 {
318 Box::new(sqlx::query!(
319 "DELETE FROM casbin_rule WHERE
320 ptype = $1 AND
321 (v5 is NULL OR v5 = COALESCE($2,v5))",
322 pt.to_string(),
323 field_values[0]
324 ))
325 } else if field_index == 4 {
326 Box::new(sqlx::query!(
327 "DELETE FROM casbin_rule WHERE
328 ptype = $1 AND
329 (v4 is NULL OR v4 = COALESCE($2,v4)) AND
330 (v5 is NULL OR v5 = COALESCE($3,v5))",
331 pt,
332 field_values[0],
333 field_values[1]
334 ))
335 } else if field_index == 3 {
336 Box::new(sqlx::query!(
337 "DELETE FROM casbin_rule WHERE
338 ptype = $1 AND
339 (v3 is NULL OR v3 = COALESCE($2,v3)) AND
340 (v4 is NULL OR v4 = COALESCE($3,v4)) AND
341 (v5 is NULL OR v5 = COALESCE($4,v5))",
342 pt,
343 field_values[0],
344 field_values[1],
345 field_values[2]
346 ))
347 } else if field_index == 2 {
348 Box::new(sqlx::query!(
349 "DELETE FROM casbin_rule WHERE
350 ptype = $1 AND
351 (v2 is NULL OR v2 = COALESCE($2,v2)) AND
352 (v3 is NULL OR v3 = COALESCE($3,v3)) AND
353 (v4 is NULL OR v4 = COALESCE($4,v4)) AND
354 (v5 is NULL OR v5 = COALESCE($5,v5))",
355 pt,
356 field_values[0],
357 field_values[1],
358 field_values[2],
359 field_values[3]
360 ))
361 } else if field_index == 1 {
362 Box::new(sqlx::query!(
363 "DELETE FROM casbin_rule WHERE
364 ptype = $1 AND
365 (v1 is NULL OR v1 = COALESCE($2,v1)) AND
366 (v2 is NULL OR v2 = COALESCE($3,v2)) AND
367 (v3 is NULL OR v3 = COALESCE($4,v3)) AND
368 (v4 is NULL OR v4 = COALESCE($5,v4)) AND
369 (v5 is NULL OR v5 = COALESCE($6,v5))",
370 pt,
371 field_values[0],
372 field_values[1],
373 field_values[2],
374 field_values[3],
375 field_values[4]
376 ))
377 } else {
378 Box::new(sqlx::query!(
379 "DELETE FROM casbin_rule WHERE
380 ptype = $1 AND
381 (v0 is NULL OR v0 = COALESCE($2,v0)) AND
382 (v1 is NULL OR v1 = COALESCE($3,v1)) AND
383 (v2 is NULL OR v2 = COALESCE($4,v2)) AND
384 (v3 is NULL OR v3 = COALESCE($5,v3)) AND
385 (v4 is NULL OR v4 = COALESCE($6,v4)) AND
386 (v5 is NULL OR v5 = COALESCE($7,v5))",
387 pt,
388 field_values[0],
389 field_values[1],
390 field_values[2],
391 field_values[3],
392 field_values[4],
393 field_values[5]
394 ))
395 };
396
397 boxed_query
398 .execute(conn)
399 .await
400 .map(|n| PgQueryResult::rows_affected(&n) >= 1)
401 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))
402}
403
404#[cfg(feature = "sqlite")]
405pub async fn remove_filtered_policy(
406 conn: &ConnectionPool,
407 pt: &str,
408 field_index: usize,
409 field_values: Vec<String>,
410) -> Result<bool> {
411 let field_values = normalize_casbin_rule_option(field_values);
412 let boxed_query = if field_index == 5 {
413 Box::new(sqlx::query!(
414 "DELETE FROM casbin_rule WHERE
415 ptype = $1 AND
416 (v5 is NULL OR v5 = COALESCE(?2,v5))",
417 pt,
418 field_values[0]
419 ))
420 } else if field_index == 4 {
421 Box::new(sqlx::query!(
422 "DELETE FROM casbin_rule WHERE
423 ptype = ?1 AND
424 (v4 is NULL OR v4 = COALESCE(?2,v4)) AND
425 (v5 is NULL OR v5 = COALESCE(?3,v5))",
426 pt,
427 field_values[0],
428 field_values[1]
429 ))
430 } else if field_index == 3 {
431 Box::new(sqlx::query!(
432 "DELETE FROM casbin_rule WHERE
433 ptype = ?1 AND
434 (v3 is NULL OR v3 = COALESCE(?2,v3)) AND
435 (v4 is NULL OR v4 = COALESCE(?3,v4)) AND
436 (v5 is NULL OR v5 = COALESCE(?4,v5))",
437 pt,
438 field_values[0],
439 field_values[1],
440 field_values[2]
441 ))
442 } else if field_index == 2 {
443 Box::new(sqlx::query!(
444 "DELETE FROM casbin_rule WHERE
445 ptype = ?1 AND
446 (v2 is NULL OR v2 = COALESCE(?2,v2)) AND
447 (v3 is NULL OR v3 = COALESCE(?3,v3)) AND
448 (v4 is NULL OR v4 = COALESCE(?4,v4)) AND
449 (v5 is NULL OR v5 = COALESCE(?5,v5))",
450 pt,
451 field_values[0],
452 field_values[1],
453 field_values[2],
454 field_values[3]
455 ))
456 } else if field_index == 1 {
457 Box::new(sqlx::query!(
458 "DELETE FROM casbin_rule WHERE
459 ptype = ?1 AND
460 (v1 is NULL OR v1 = COALESCE(?2,v1)) AND
461 (v2 is NULL OR v2 = COALESCE(?3,v2)) AND
462 (v3 is NULL OR v3 = COALESCE(?4,v3)) AND
463 (v4 is NULL OR v4 = COALESCE(?5,v4)) AND
464 (v5 is NULL OR v5 = COALESCE(?6,v5))",
465 pt,
466 field_values[0],
467 field_values[1],
468 field_values[2],
469 field_values[3],
470 field_values[4]
471 ))
472 } else {
473 Box::new(sqlx::query!(
474 "DELETE FROM casbin_rule WHERE
475 ptype = ?1 AND
476 (v0 is NULL OR v0 = COALESCE(?2,v0)) AND
477 (v1 is NULL OR v1 = COALESCE(?3,v1)) AND
478 (v2 is NULL OR v2 = COALESCE(?4,v2)) AND
479 (v3 is NULL OR v3 = COALESCE(?5,v3)) AND
480 (v4 is NULL OR v4 = COALESCE(?6,v4)) AND
481 (v5 is NULL OR v5 = COALESCE(?7,v5))",
482 pt,
483 field_values[0],
484 field_values[1],
485 field_values[2],
486 field_values[3],
487 field_values[4],
488 field_values[5]
489 ))
490 };
491
492 boxed_query
493 .execute(conn)
494 .await
495 .map(|n| SqliteQueryResult::rows_affected(&n) >= 1)
496 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))
497}
498
499#[cfg(feature = "mysql")]
500pub async fn remove_filtered_policy(
501 conn: &ConnectionPool,
502 pt: &str,
503 field_index: usize,
504 field_values: Vec<String>,
505) -> Result<bool> {
506 let field_values = normalize_casbin_rule_option(field_values);
507 let boxed_query = if field_index == 5 {
508 Box::new(sqlx::query!(
509 "DELETE FROM casbin_rule WHERE
510 ptype = ? AND
511 (v5 is NULL OR v5 = COALESCE(?,v5))",
512 pt,
513 field_values[0]
514 ))
515 } else if field_index == 4 {
516 Box::new(sqlx::query!(
517 "DELETE FROM casbin_rule WHERE
518 ptype = ? AND
519 (v4 is NULL OR v4 = COALESCE(?,v4)) AND
520 (v5 is NULL OR v5 = COALESCE(?,v5))",
521 pt.to_string(),
522 field_values[0],
523 field_values[1]
524 ))
525 } else if field_index == 3 {
526 Box::new(sqlx::query!(
527 "DELETE FROM casbin_rule WHERE
528 ptype = ? AND
529 (v3 is NULL OR v3 = COALESCE(?,v3)) AND
530 (v4 is NULL OR v4 = COALESCE(?,v4)) AND
531 (v5 is NULL OR v5 = COALESCE(?,v5))",
532 pt,
533 field_values[0],
534 field_values[1],
535 field_values[2]
536 ))
537 } else if field_index == 2 {
538 Box::new(sqlx::query!(
539 "DELETE FROM casbin_rule WHERE
540 ptype = ? AND
541 (v2 is NULL OR v2 = COALESCE(?,v2)) AND
542 (v3 is NULL OR v3 = COALESCE(?,v3)) AND
543 (v4 is NULL OR v4 = COALESCE(?,v4)) AND
544 (v5 is NULL OR v5 = COALESCE(?,v5))",
545 pt,
546 field_values[0],
547 field_values[1],
548 field_values[2],
549 field_values[3]
550 ))
551 } else if field_index == 1 {
552 Box::new(sqlx::query!(
553 "DELETE FROM casbin_rule WHERE
554 ptype = ? AND
555 (v1 is NULL OR v1 = COALESCE(?,v1)) AND
556 (v2 is NULL OR v2 = COALESCE(?,v2)) AND
557 (v3 is NULL OR v3 = COALESCE(?,v3)) AND
558 (v4 is NULL OR v4 = COALESCE(?,v4)) AND
559 (v5 is NULL OR v5 = COALESCE(?,v5))",
560 pt,
561 field_values[0],
562 field_values[1],
563 field_values[2],
564 field_values[3],
565 field_values[4]
566 ))
567 } else {
568 Box::new(sqlx::query!(
569 "DELETE FROM casbin_rule WHERE
570 ptype = ? AND
571 (v0 is NULL OR v0 = COALESCE(?,v0)) AND
572 (v1 is NULL OR v1 = COALESCE(?,v1)) AND
573 (v2 is NULL OR v2 = COALESCE(?,v2)) AND
574 (v3 is NULL OR v3 = COALESCE(?,v3)) AND
575 (v4 is NULL OR v4 = COALESCE(?,v4)) AND
576 (v5 is NULL OR v5 = COALESCE(?,v5))",
577 pt,
578 field_values[0],
579 field_values[1],
580 field_values[2],
581 field_values[3],
582 field_values[4],
583 field_values[5]
584 ))
585 };
586
587 boxed_query
588 .execute(conn)
589 .await
590 .map(|n| MySqlQueryResult::rows_affected(&n) >= 1)
591 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))
592}
593
594#[cfg(feature = "postgres")]
595pub(crate) async fn load_policy(conn: &ConnectionPool) -> Result<Vec<CasbinRule>> {
596 let casbin_rule: Vec<CasbinRule> = sqlx::query_as!(
597 CasbinRule,
598 "SELECT id, ptype, v0, v1, v2, v3, v4, v5 FROM casbin_rule"
599 )
600 .fetch_all(conn)
601 .await
602 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
603
604 Ok(casbin_rule)
605}
606
607#[cfg(feature = "sqlite")]
608pub(crate) async fn load_policy(conn: &ConnectionPool) -> Result<Vec<CasbinRule>> {
609 let casbin_rule: Vec<CasbinRule> = sqlx::query_as!(
610 CasbinRule,
611 "SELECT id, ptype, v0, v1, v2, v3, v4, v5 FROM casbin_rule"
612 )
613 .fetch_all(conn)
614 .await
615 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
616
617 Ok(casbin_rule)
618}
619
620#[cfg(feature = "mysql")]
621pub(crate) async fn load_policy(conn: &ConnectionPool) -> Result<Vec<CasbinRule>> {
622 let casbin_rule: Vec<CasbinRule> = sqlx::query_as!(
623 CasbinRule,
624 "SELECT id, ptype, v0, v1, v2, v3, v4, v5 FROM casbin_rule"
625 )
626 .fetch_all(conn)
627 .await
628 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
629
630 Ok(casbin_rule)
631}
632
633#[cfg(feature = "postgres")]
634pub(crate) async fn load_filtered_policy(
635 conn: &ConnectionPool,
636 filter: &Filter<'_>,
637) -> Result<Vec<CasbinRule>> {
638 let (g_filter, p_filter) = filtered_where_values(filter);
639
640 let casbin_rule: Vec<CasbinRule> = sqlx::query_as!(
641 CasbinRule,
642 "SELECT id, ptype, v0, v1, v2, v3, v4, v5 from casbin_rule WHERE (
643 ptype LIKE 'g%' AND v0 LIKE $1 AND v1 LIKE $2 AND v2 LIKE $3 AND v3 LIKE $4 AND v4 LIKE $5 AND v5 LIKE $6 )
644 OR (
645 ptype LIKE 'p%' AND v0 LIKE $7 AND v1 LIKE $8 AND v2 LIKE $9 AND v3 LIKE $10 AND v4 LIKE $11 AND v5 LIKE $12 );
646 ",
647 g_filter[0], g_filter[1], g_filter[2], g_filter[3], g_filter[4], g_filter[5],
648 p_filter[0], p_filter[1], p_filter[2], p_filter[3], p_filter[4], p_filter[5],)
649 .fetch_all(conn)
650 .await
651 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
652
653 Ok(casbin_rule)
654}
655
656#[cfg(feature = "sqlite")]
657pub(crate) async fn load_filtered_policy(
658 conn: &ConnectionPool,
659 filter: &Filter<'_>,
660) -> Result<Vec<CasbinRule>> {
661 let (g_filter, p_filter) = filtered_where_values(filter);
662
663 let casbin_rule: Vec<CasbinRule> = sqlx::query_as!(
664 CasbinRule,
665 "SELECT id, ptype, v0, v1, v2, v3, v4, v5 from casbin_rule WHERE (
666 ptype LIKE 'g%' AND v0 LIKE $1 AND v1 LIKE $2 AND v2 LIKE $3 AND v3 LIKE $4 AND v4 LIKE $5 AND v5 LIKE $6 )
667 OR (
668 ptype LIKE 'p%' AND v0 LIKE $7 AND v1 LIKE $8 AND v2 LIKE $9 AND v3 LIKE $10 AND v4 LIKE $11 AND v5 LIKE $12 );
669 ",
670 g_filter[0], g_filter[1], g_filter[2], g_filter[3], g_filter[4], g_filter[5],
671 p_filter[0], p_filter[1], p_filter[2], p_filter[3], p_filter[4], p_filter[5],)
672 .fetch_all(conn)
673 .await
674 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
675
676 Ok(casbin_rule)
677}
678
679#[cfg(feature = "mysql")]
680pub(crate) async fn load_filtered_policy(
681 conn: &ConnectionPool,
682 filter: &Filter<'_>,
683) -> Result<Vec<CasbinRule>> {
684 let (g_filter, p_filter) = filtered_where_values(filter);
685
686 let casbin_rule: Vec<CasbinRule> = sqlx::query_as!(
687 CasbinRule,
688 "SELECT id, ptype, v0, v1, v2, v3, v4, v5 from casbin_rule WHERE (
689 ptype LIKE 'g%' AND v0 LIKE ? AND v1 LIKE ? AND v2 LIKE ? AND v3 LIKE ? AND v4 LIKE ? AND v5 LIKE ? )
690 OR (
691 ptype LIKE 'p%' AND v0 LIKE ? AND v1 LIKE ? AND v2 LIKE ? AND v3 LIKE ? AND v4 LIKE ? AND v5 LIKE ? );
692 ",
693 g_filter[0], g_filter[1], g_filter[2], g_filter[3], g_filter[4], g_filter[5],
694 p_filter[0], p_filter[1], p_filter[2], p_filter[3], p_filter[4], p_filter[5],
695 )
696 .fetch_all(conn)
697 .await
698 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
699
700 Ok(casbin_rule)
701}
702
703fn filtered_where_values<'a>(filter: &Filter<'a>) -> ([&'a str; 6], [&'a str; 6]) {
704 let mut g_filter: [&'a str; 6] = ["%", "%", "%", "%", "%", "%"];
705 let mut p_filter: [&'a str; 6] = ["%", "%", "%", "%", "%", "%"];
706 for (idx, val) in filter.g.iter().enumerate() {
707 if val != &"" {
708 g_filter[idx] = val;
709 }
710 }
711 for (idx, val) in filter.p.iter().enumerate() {
712 if val != &"" {
713 p_filter[idx] = val;
714 }
715 }
716 (g_filter, p_filter)
717}
718
719#[cfg(feature = "postgres")]
720pub(crate) async fn save_policy(
721 conn: &ConnectionPool,
722 rules: Vec<NewCasbinRule<'_>>,
723) -> Result<()> {
724 let mut transaction = conn
725 .begin()
726 .await
727 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
728 sqlx::query!("DELETE FROM casbin_rule")
729 .execute(&mut *transaction)
730 .await
731 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
732 for rule in rules {
733 sqlx::query!(
734 "INSERT INTO casbin_rule ( ptype, v0, v1, v2, v3, v4, v5 )
735 VALUES ( $1, $2, $3, $4, $5, $6, $7 )",
736 rule.ptype,
737 rule.v0,
738 rule.v1,
739 rule.v2,
740 rule.v3,
741 rule.v4,
742 rule.v5
743 )
744 .execute(&mut *transaction)
745 .await
746 .and_then(|n| {
747 if PgQueryResult::rows_affected(&n) == 1 {
748 Ok(true)
749 } else {
750 Err(SqlxError::RowNotFound)
751 }
752 })
753 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
754 }
755 transaction
756 .commit()
757 .await
758 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
759 Ok(())
760}
761
762#[cfg(feature = "sqlite")]
763pub(crate) async fn save_policy(
764 conn: &ConnectionPool,
765 rules: Vec<NewCasbinRule<'_>>,
766) -> Result<()> {
767 let mut transaction = conn
768 .begin()
769 .await
770 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
771 sqlx::query!("DELETE FROM casbin_rule")
772 .execute(&mut *transaction)
773 .await
774 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
775 for rule in rules {
776 sqlx::query!(
777 "INSERT INTO casbin_rule ( ptype, v0, v1, v2, v3, v4, v5 )
778 VALUES ( $1, $2, $3, $4, $5, $6, $7 )",
779 rule.ptype,
780 rule.v0,
781 rule.v1,
782 rule.v2,
783 rule.v3,
784 rule.v4,
785 rule.v5
786 )
787 .execute(&mut *transaction)
788 .await
789 .and_then(|n| {
790 if SqliteQueryResult::rows_affected(&n) == 1 {
791 Ok(true)
792 } else {
793 Err(SqlxError::RowNotFound)
794 }
795 })
796 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
797 }
798 transaction
799 .commit()
800 .await
801 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
802 Ok(())
803}
804
805#[cfg(feature = "mysql")]
806pub(crate) async fn save_policy<'a>(
807 conn: &ConnectionPool,
808 rules: Vec<NewCasbinRule<'a>>,
809) -> Result<()> {
810 let mut transaction = conn
811 .begin()
812 .await
813 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
814 sqlx::query!("DELETE FROM casbin_rule")
815 .execute(&mut *transaction)
816 .await
817 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
818 for rule in rules {
819 sqlx::query!(
820 "INSERT INTO casbin_rule ( ptype, v0, v1, v2, v3, v4, v5 )
821 VALUES ( ?, ?, ?, ?, ?, ?, ? )",
822 rule.ptype,
823 rule.v0,
824 rule.v1,
825 rule.v2,
826 rule.v3,
827 rule.v4,
828 rule.v5
829 )
830 .execute(&mut *transaction)
831 .await
832 .and_then(|n| {
833 if MySqlQueryResult::rows_affected(&n) == 1 {
834 Ok(true)
835 } else {
836 Err(SqlxError::RowNotFound)
837 }
838 })
839 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
840 }
841 transaction
842 .commit()
843 .await
844 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
845 Ok(())
846}
847
848#[cfg(feature = "postgres")]
849pub(crate) async fn add_policy(conn: &ConnectionPool, rule: NewCasbinRule<'_>) -> Result<bool> {
850 sqlx::query!(
851 "INSERT INTO casbin_rule ( ptype, v0, v1, v2, v3, v4, v5 )
852 VALUES ( $1, $2, $3, $4, $5, $6, $7 )",
853 rule.ptype,
854 rule.v0,
855 rule.v1,
856 rule.v2,
857 rule.v3,
858 rule.v4,
859 rule.v5
860 )
861 .execute(conn)
862 .await
863 .map(|n| PgQueryResult::rows_affected(&n) == 1)
864 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
865
866 Ok(true)
867}
868
869#[cfg(feature = "sqlite")]
870pub(crate) async fn add_policy(conn: &ConnectionPool, rule: NewCasbinRule<'_>) -> Result<bool> {
871 sqlx::query!(
872 "INSERT INTO casbin_rule ( ptype, v0, v1, v2, v3, v4, v5 )
873 VALUES ( $1, $2, $3, $4, $5, $6, $7 )",
874 rule.ptype,
875 rule.v0,
876 rule.v1,
877 rule.v2,
878 rule.v3,
879 rule.v4,
880 rule.v5
881 )
882 .execute(conn)
883 .await
884 .map(|n| SqliteQueryResult::rows_affected(&n) == 1)
885 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
886
887 Ok(true)
888}
889
890#[cfg(feature = "mysql")]
891pub(crate) async fn add_policy(conn: &ConnectionPool, rule: NewCasbinRule<'_>) -> Result<bool> {
892 sqlx::query!(
893 "INSERT INTO casbin_rule ( ptype, v0, v1, v2, v3, v4, v5 )
894 VALUES ( ?, ?, ?, ?, ?, ?, ? )",
895 rule.ptype,
896 rule.v0,
897 rule.v1,
898 rule.v2,
899 rule.v3,
900 rule.v4,
901 rule.v5
902 )
903 .execute(conn)
904 .await
905 .map(|n| MySqlQueryResult::rows_affected(&n) == 1)
906 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
907
908 Ok(true)
909}
910
911#[cfg(feature = "postgres")]
912pub(crate) async fn add_policies(
913 conn: &ConnectionPool,
914 rules: Vec<NewCasbinRule<'_>>,
915) -> Result<bool> {
916 let mut transaction = conn
917 .begin()
918 .await
919 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
920 for rule in rules {
921 sqlx::query!(
922 "INSERT INTO casbin_rule ( ptype, v0, v1, v2, v3, v4, v5 )
923 VALUES ( $1, $2, $3, $4, $5, $6, $7 )",
924 rule.ptype,
925 rule.v0,
926 rule.v1,
927 rule.v2,
928 rule.v3,
929 rule.v4,
930 rule.v5
931 )
932 .execute(&mut *transaction)
933 .await
934 .and_then(|n| {
935 if PgQueryResult::rows_affected(&n) == 1 {
936 Ok(true)
937 } else {
938 Err(SqlxError::RowNotFound)
939 }
940 })
941 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
942 }
943 transaction
944 .commit()
945 .await
946 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
947 Ok(true)
948}
949
950#[cfg(feature = "sqlite")]
951pub(crate) async fn add_policies(
952 conn: &ConnectionPool,
953 rules: Vec<NewCasbinRule<'_>>,
954) -> Result<bool> {
955 let mut transaction = conn
956 .begin()
957 .await
958 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
959 for rule in rules {
960 sqlx::query!(
961 "INSERT INTO casbin_rule ( ptype, v0, v1, v2, v3, v4, v5 )
962 VALUES ( $1, $2, $3, $4, $5, $6, $7 )",
963 rule.ptype,
964 rule.v0,
965 rule.v1,
966 rule.v2,
967 rule.v3,
968 rule.v4,
969 rule.v5
970 )
971 .execute(&mut *transaction)
972 .await
973 .and_then(|n| {
974 if SqliteQueryResult::rows_affected(&n) == 1 {
975 Ok(true)
976 } else {
977 Err(SqlxError::RowNotFound)
978 }
979 })
980 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
981 }
982 transaction
983 .commit()
984 .await
985 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
986 Ok(true)
987}
988
989#[cfg(feature = "mysql")]
990pub(crate) async fn add_policies(
991 conn: &ConnectionPool,
992 rules: Vec<NewCasbinRule<'_>>,
993) -> Result<bool> {
994 let mut transaction = conn
995 .begin()
996 .await
997 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
998 for rule in rules {
999 sqlx::query!(
1000 "INSERT INTO casbin_rule ( ptype, v0, v1, v2, v3, v4, v5 )
1001 VALUES ( ?, ?, ?, ?, ?, ?, ? )",
1002 rule.ptype,
1003 rule.v0,
1004 rule.v1,
1005 rule.v2,
1006 rule.v3,
1007 rule.v4,
1008 rule.v5
1009 )
1010 .execute(&mut *transaction)
1011 .await
1012 .and_then(|n| {
1013 if MySqlQueryResult::rows_affected(&n) == 1 {
1014 Ok(true)
1015 } else {
1016 Err(SqlxError::RowNotFound)
1017 }
1018 })
1019 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
1020 }
1021 transaction
1022 .commit()
1023 .await
1024 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
1025 Ok(true)
1026}
1027
1028#[cfg(feature = "postgres")]
1029pub(crate) async fn clear_policy(conn: &ConnectionPool) -> Result<()> {
1030 let mut transaction = conn
1031 .begin()
1032 .await
1033 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
1034 sqlx::query!("DELETE FROM casbin_rule")
1035 .execute(&mut *transaction)
1036 .await
1037 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
1038 transaction
1039 .commit()
1040 .await
1041 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
1042 Ok(())
1043}
1044
1045#[cfg(feature = "sqlite")]
1046pub(crate) async fn clear_policy(conn: &ConnectionPool) -> Result<()> {
1047 let mut transaction = conn
1048 .begin()
1049 .await
1050 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
1051 sqlx::query!("DELETE FROM casbin_rule")
1052 .execute(&mut *transaction)
1053 .await
1054 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
1055 transaction
1056 .commit()
1057 .await
1058 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
1059 Ok(())
1060}
1061
1062#[cfg(feature = "mysql")]
1063pub(crate) async fn clear_policy(conn: &ConnectionPool) -> Result<()> {
1064 let mut transaction = conn
1065 .begin()
1066 .await
1067 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
1068 sqlx::query!("DELETE FROM casbin_rule")
1069 .execute(&mut *transaction)
1070 .await
1071 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
1072 transaction
1073 .commit()
1074 .await
1075 .map_err(|err| CasbinError::from(AdapterError(Box::new(Error::SqlxError(err)))))?;
1076 Ok(())
1077}
1078
1079fn normalize_casbin_rule(mut rule: Vec<String>) -> Vec<String> {
1080 rule.resize(6, String::new());
1081 rule
1082}
1083
1084fn normalize_casbin_rule_option(rule: Vec<String>) -> Vec<Option<String>> {
1085 let mut rule_with_option = rule
1086 .iter()
1087 .map(|x| match x.is_empty() {
1088 true => None,
1089 false => Some(x.clone()),
1090 })
1091 .collect::<Vec<Option<String>>>();
1092 rule_with_option.resize(6, None);
1093 rule_with_option
1094}