1use diesel::prelude::*;
2use serde::{Deserialize, Serialize};
3use serde_json;
4
5use crate::{
6 db::{Con, Id},
7 password::hash_password,
8 quco::{Collection, Query},
9 ryz::{err, res::Res},
10 schema,
11 user_change::{self, ChangeAction, NewUserChange},
12 InsertReg, Reg,
13};
14
15#[derive(Serialize, Deserialize, Debug)]
16pub struct User {
17 pub id: Id,
18 pub username: String,
19 pub firstname: Option<String>,
20 pub patronym: Option<String>,
21 pub surname: Option<String>,
22 pub rt: Option<String>,
23}
24
25#[derive(Queryable, Selectable)]
26#[diesel(table_name = schema::appuser)]
27#[diesel(check_for_backend(diesel::pg::Pg))]
28pub struct UserTable {
29 pub id: Id,
30 pub hpassword: String,
31 pub username: String,
32 pub firstname: Option<String>,
33 pub patronym: Option<String>,
34 pub surname: Option<String>,
35 pub rt: Option<String>,
36}
37
38impl Collection<User> for UserTable {
39 fn to_msg(&self) -> User {
40 User {
41 id: self.id.to_owned(),
42 username: self.username.to_owned(),
43 firstname: self.firstname.to_owned(),
44 patronym: self.patronym.to_owned(),
45 surname: self.surname.to_owned(),
46 rt: self.rt.to_owned(),
47 }
48 }
49}
50
51pub fn new(reg: &Reg, con: &mut Con) -> Res<User> {
52 if reg.username.starts_with("archive::") {
53 return err::res_msg("cannot accept archived usernames");
54 }
55 let hpassword = hash_password(®.password).unwrap();
56 let user: UserTable = diesel::insert_into(schema::appuser::table)
57 .values(&InsertReg {
58 username: reg.username.to_owned(),
59 hpassword: hpassword.to_owned(),
60 firstname: reg.firstname.to_owned(),
61 patronym: reg.patronym.to_owned(),
62 surname: reg.surname.to_owned(),
63 })
64 .returning(UserTable::as_returning())
65 .get_result(con)
66 .unwrap();
67
68 user_change::new(
69 &NewUserChange {
70 user_id: user.id,
71 action: ChangeAction::New,
72 },
73 con,
74 )
75 .unwrap();
76
77 Ok(user.to_msg())
78}
79
80pub fn del(sq: &Query, con: &mut Con) -> Res<()> {
85 let id = sq.get("id");
86 let username = sq.get("username");
87 let mut q = schema::appuser::table.into_boxed();
88 if id.is_some() {
89 let val = serde_json::from_value::<Id>(id.unwrap().clone()).unwrap();
90 q = q.filter(schema::appuser::id.eq(val));
91 }
92 if username.is_some() {
93 let username =
94 serde_json::from_value::<String>(username.unwrap().clone())
95 .unwrap();
96 if username.starts_with("archive::") {
97 return err::res_msg("cannot accept archived usernames");
98 }
99 q = q.filter(schema::appuser::username.eq(username));
100 }
101
102 let username = q
103 .select(schema::appuser::username)
104 .get_result::<String>(con)
105 .unwrap();
106 let archived_username = "archived::".to_string() + username.as_str();
107
108 let id = diesel::update(schema::appuser::table)
109 .filter(schema::appuser::username.eq(username))
110 .set(schema::appuser::username.eq(archived_username))
111 .returning(schema::appuser::id)
112 .get_result::<Id>(con)
113 .unwrap();
114
115 user_change::new(
116 &NewUserChange {
117 user_id: id,
118 action: ChangeAction::Del,
119 },
120 con,
121 )
122 .unwrap();
123
124 Ok(())
125}
126
127pub fn get_by_id(id: i32, con: &mut Con) -> Res<User> {
128 Ok(schema::appuser::table
129 .filter(schema::appuser::id.eq(id))
130 .filter(schema::appuser::username.not_like("archived::%"))
131 .select(UserTable::as_select())
132 .first(con)
133 .unwrap()
134 .to_msg())
135}
136
137pub fn get_by_username(
138 username: &String,
139 con: &mut Con,
140) -> Res<(User, String)> {
141 if username.starts_with("archive::") {
142 return err::res_msg("cannot accept archived usernames");
143 }
144 let user: UserTable = schema::appuser::table
145 .filter(schema::appuser::username.eq(username))
146 .select(UserTable::as_select())
147 .first(con)
148 .unwrap();
149 Ok((user.to_msg(), user.hpassword))
150}
151
152pub fn get_by_rt(rt: &String, con: &mut Con) -> Res<(User, String)> {
153 let user: UserTable = schema::appuser::table
154 .filter(schema::appuser::rt.eq(rt))
155 .filter(schema::appuser::username.not_like("archived::%"))
156 .select(UserTable::as_select())
157 .first(con)
158 .unwrap();
159 Ok((user.to_msg(), user.hpassword))
160}
161
162pub fn del_rt(rt: &String, con: &mut Con) -> Res<()> {
163 diesel::update(schema::appuser::table.filter(schema::appuser::rt.eq(rt)))
165 .set(schema::appuser::rt.eq::<Option<String>>(None))
166 .execute(con)
167 .unwrap();
168 Ok(())
169}
170
171pub fn set_rt_for_username(
172 username: &String,
173 rt: &String,
174 con: &mut Con,
175) -> Res<()> {
176 if username.starts_with("archive::") {
177 return err::res_msg("cannot accept archived usernames");
178 }
179 diesel::update(
180 schema::appuser::table.filter(schema::appuser::username.eq(username)),
181 )
182 .set(schema::appuser::rt.eq::<Option<String>>(Some(rt.to_owned())))
183 .execute(con)
184 .unwrap();
185 Ok(())
186}
187
188pub fn get_many_as_ids(con: &mut Con) -> Res<Vec<Id>> {
189 let ids = schema::appuser::table
190 .filter(schema::appuser::username.not_like("archived::%"))
191 .select(schema::appuser::id)
192 .get_results::<Id>(con)
193 .unwrap();
194 Ok(ids)
195}