Create admin function to use copy-pasted users from ekey, return the ones which don't match to "Donau Linz" rowt user, Fixes #204 (#230)
Reviewed-on: #230
This commit was merged in pull request #230.
	This commit is contained in:
		
							
								
								
									
										22
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										22
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @@ -521,6 +521,27 @@ dependencies = [ | ||||
|  "typenum", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "csv" | ||||
| version = "1.3.0" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" | ||||
| dependencies = [ | ||||
|  "csv-core", | ||||
|  "itoa", | ||||
|  "ryu", | ||||
|  "serde", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "csv-core" | ||||
| version = "0.1.11" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" | ||||
| dependencies = [ | ||||
|  "memchr", | ||||
| ] | ||||
|  | ||||
| [[package]] | ||||
| name = "ctr" | ||||
| version = "0.9.2" | ||||
| @@ -2195,6 +2216,7 @@ dependencies = [ | ||||
|  "argon2", | ||||
|  "chrono", | ||||
|  "chrono-tz", | ||||
|  "csv", | ||||
|  "env_logger", | ||||
|  "futures", | ||||
|  "ics", | ||||
|   | ||||
| @@ -23,6 +23,7 @@ tera =  { version = "1.18", features = ["date-locale"], optional = true} | ||||
| ics = "0.5" | ||||
| futures = "0.3" | ||||
| lettre = "0.11" | ||||
| csv = "1.3" | ||||
|  | ||||
| [target.'cfg(not(windows))'.dependencies] | ||||
| openssl = { version = "0.10", features = [ "vendored" ] } | ||||
|   | ||||
| @@ -45,6 +45,19 @@ WHERE name like ? | ||||
|         .ok() | ||||
|     } | ||||
|  | ||||
|     pub async fn names_from_role(&self, db: &SqlitePool) -> Vec<String> { | ||||
|         let query = format!( | ||||
|             "SELECT u.name | ||||
|          FROM user u | ||||
|          JOIN user_role ur ON u.id = ur.user_id | ||||
|          JOIN role r ON ur.role_id = r.id | ||||
|          WHERE r.id = {} AND deleted=0;", | ||||
|             self.id | ||||
|         ); | ||||
|  | ||||
|         sqlx::query_scalar(&query).fetch_all(db).await.unwrap() | ||||
|     } | ||||
|  | ||||
|     pub async fn mails_from_role(&self, db: &SqlitePool) -> Vec<String> { | ||||
|         let query = format!( | ||||
|             "SELECT u.mail | ||||
|   | ||||
| @@ -266,7 +266,7 @@ impl User { | ||||
|  | ||||
|     pub async fn roles(&self, db: &SqlitePool) -> Vec<String> { | ||||
|         sqlx::query!( | ||||
|             "SELECT r.name FROM role r JOIN user_role ur ON r.id = ur.role_id WHERE ur.user_id = ?;", | ||||
|             "SELECT r.name FROM role r JOIN user_role ur ON r.id = ur.role_id JOIN user u ON u.id = ur.user_id WHERE ur.user_id = ? AND u.deleted = 0;", | ||||
|             self.id | ||||
|         ) | ||||
|             .fetch_all(db) | ||||
|   | ||||
| @@ -1,8 +1,10 @@ | ||||
| use rocket::{get, routes, Route, State}; | ||||
| use csv::ReaderBuilder; | ||||
| use rocket::{form::Form, get, post, routes, FromForm, Route, State}; | ||||
| use rocket_dyn_templates::{context, Template}; | ||||
| use sqlx::SqlitePool; | ||||
|  | ||||
| use crate::{ | ||||
|     model::{log::Log, user::AdminUser}, | ||||
|     model::{log::Log, role::Role, user::AdminUser}, | ||||
|     tera::Config, | ||||
| }; | ||||
|  | ||||
| @@ -25,12 +27,56 @@ async fn show_rss(db: &State<SqlitePool>, _admin: AdminUser) -> String { | ||||
|     Log::show(db).await | ||||
| } | ||||
|  | ||||
| #[get("/list")] | ||||
| async fn show_list(_admin: AdminUser) -> Template { | ||||
|     Template::render("admin/list/index", context!()) | ||||
| } | ||||
|  | ||||
| #[derive(FromForm)] | ||||
| struct ListForm { | ||||
|     list: String, | ||||
| } | ||||
|  | ||||
| #[post("/list", data = "<list_form>")] | ||||
| async fn list(db: &State<SqlitePool>, _admin: AdminUser, list_form: Form<ListForm>) -> Template { | ||||
|     let role = Role::find_by_name(db, "Donau Linz").await.unwrap(); | ||||
|     let acceptable_users = role.names_from_role(db).await; | ||||
|  | ||||
|     let mut rdr = ReaderBuilder::new() | ||||
|         .has_headers(true) | ||||
|         .delimiter(b';') | ||||
|         .from_reader(list_form.list.trim().as_bytes()); | ||||
|  | ||||
|     let mut names_not_in_acceptable_users = Vec::new(); | ||||
|  | ||||
|     for result in rdr.records() { | ||||
|         println!("{result:?}"); | ||||
|         let record = result.unwrap(); | ||||
|  | ||||
|         // Concatenate Vorname and Nachname | ||||
|         let vorname = record.get(2).unwrap_or_default().trim(); | ||||
|         let nachname = record.get(3).unwrap_or_default().trim(); | ||||
|         let full_name = format!("{} {}", vorname, nachname); | ||||
|  | ||||
|         // Check if the concatenated name is not in the acceptable_users vector | ||||
|         if !acceptable_users.contains(&full_name) { | ||||
|             names_not_in_acceptable_users.push(full_name); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     let context = context! { | ||||
|         result: names_not_in_acceptable_users | ||||
|     }; | ||||
|  | ||||
|     Template::render("admin/list/result", &context) | ||||
| } | ||||
|  | ||||
| pub fn routes() -> Vec<Route> { | ||||
|     let mut ret = Vec::new(); | ||||
|     ret.append(&mut user::routes()); | ||||
|     ret.append(&mut boat::routes()); | ||||
|     ret.append(&mut mail::routes()); | ||||
|     ret.append(&mut planned_event::routes()); | ||||
|     ret.append(&mut routes![rss, show_rss]); | ||||
|     ret.append(&mut routes![rss, show_rss, show_list, list]); | ||||
|     ret | ||||
| } | ||||
|   | ||||
							
								
								
									
										12
									
								
								templates/admin/list/index.html.tera
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								templates/admin/list/index.html.tera
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| {% import "includes/macros" as macros %} | ||||
| {% extends "base" %} | ||||
| {% block content %} | ||||
|     {% if flash %}{{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3") }}{% endif %} | ||||
|     <div class="max-w-screen-lg w-full"> | ||||
|         <h1 class="h1">List</h1> | ||||
|         <form action="/admin/list" method="post"> | ||||
|             <textarea name="list" rows="4" cols="50"></textarea> | ||||
|             <input type="submit" /> | ||||
|         </form> | ||||
|     </div> | ||||
| {% endblock content %} | ||||
							
								
								
									
										13
									
								
								templates/admin/list/result.html.tera
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								templates/admin/list/result.html.tera
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| {% import "includes/macros" as macros %} | ||||
| {% extends "base" %} | ||||
| {% block content %} | ||||
|     {% if flash %}{{ macros::alert(message=flash.1, type=flash.0, class="sm:col-span-2 lg:col-span-3") }}{% endif %} | ||||
|     <div class="max-w-screen-lg w-full"> | ||||
|         <h1 class="h1">List - Result</h1> | ||||
| 	<ol> | ||||
| 	{% for person in result%} | ||||
| 		<li>{{person}}</li> | ||||
| 	{% endfor %} | ||||
| 	</ol> | ||||
|     </div> | ||||
| {% endblock content %} | ||||
		Reference in New Issue
	
	Block a user