]> Untitled Git - lemmy.git/blob - crates/db_schema/src/impls/person.rs
Making public key required. Fixes #1934
[lemmy.git] / crates / db_schema / src / impls / person.rs
1 use crate::{
2   naive_now,
3   newtypes::{DbUrl, PersonId},
4   schema::person::dsl::*,
5   source::person::{Person, PersonForm},
6   traits::Crud,
7 };
8 use diesel::{dsl::*, result::Error, ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl};
9 use url::Url;
10
11 mod safe_type {
12   use crate::{schema::person::columns::*, source::person::Person, traits::ToSafe};
13
14   type Columns = (
15     id,
16     name,
17     display_name,
18     avatar,
19     banned,
20     published,
21     updated,
22     actor_id,
23     bio,
24     local,
25     banner,
26     deleted,
27     inbox_url,
28     shared_inbox_url,
29     matrix_user_id,
30     admin,
31     bot_account,
32   );
33
34   impl ToSafe for Person {
35     type SafeColumns = Columns;
36     fn safe_columns_tuple() -> Self::SafeColumns {
37       (
38         id,
39         name,
40         display_name,
41         avatar,
42         banned,
43         published,
44         updated,
45         actor_id,
46         bio,
47         local,
48         banner,
49         deleted,
50         inbox_url,
51         shared_inbox_url,
52         matrix_user_id,
53         admin,
54         bot_account,
55       )
56     }
57   }
58 }
59
60 mod safe_type_alias_1 {
61   use crate::{schema::person_alias_1::columns::*, source::person::PersonAlias1, traits::ToSafe};
62
63   type Columns = (
64     id,
65     name,
66     display_name,
67     avatar,
68     banned,
69     published,
70     updated,
71     actor_id,
72     bio,
73     local,
74     banner,
75     deleted,
76     inbox_url,
77     shared_inbox_url,
78     matrix_user_id,
79     admin,
80     bot_account,
81   );
82
83   impl ToSafe for PersonAlias1 {
84     type SafeColumns = Columns;
85     fn safe_columns_tuple() -> Self::SafeColumns {
86       (
87         id,
88         name,
89         display_name,
90         avatar,
91         banned,
92         published,
93         updated,
94         actor_id,
95         bio,
96         local,
97         banner,
98         deleted,
99         inbox_url,
100         shared_inbox_url,
101         matrix_user_id,
102         admin,
103         bot_account,
104       )
105     }
106   }
107 }
108
109 mod safe_type_alias_2 {
110   use crate::{schema::person_alias_2::columns::*, source::person::PersonAlias2, traits::ToSafe};
111
112   type Columns = (
113     id,
114     name,
115     display_name,
116     avatar,
117     banned,
118     published,
119     updated,
120     actor_id,
121     bio,
122     local,
123     banner,
124     deleted,
125     inbox_url,
126     shared_inbox_url,
127     matrix_user_id,
128     admin,
129     bot_account,
130   );
131
132   impl ToSafe for PersonAlias2 {
133     type SafeColumns = Columns;
134     fn safe_columns_tuple() -> Self::SafeColumns {
135       (
136         id,
137         name,
138         display_name,
139         avatar,
140         banned,
141         published,
142         updated,
143         actor_id,
144         bio,
145         local,
146         banner,
147         deleted,
148         inbox_url,
149         shared_inbox_url,
150         matrix_user_id,
151         admin,
152         bot_account,
153       )
154     }
155   }
156 }
157
158 impl Crud for Person {
159   type Form = PersonForm;
160   type IdType = PersonId;
161   fn read(conn: &PgConnection, person_id: PersonId) -> Result<Self, Error> {
162     person
163       .filter(deleted.eq(false))
164       .find(person_id)
165       .first::<Self>(conn)
166   }
167   fn delete(conn: &PgConnection, person_id: PersonId) -> Result<usize, Error> {
168     diesel::delete(person.find(person_id)).execute(conn)
169   }
170   fn create(conn: &PgConnection, form: &PersonForm) -> Result<Self, Error> {
171     insert_into(person).values(form).get_result::<Self>(conn)
172   }
173   fn update(conn: &PgConnection, person_id: PersonId, form: &PersonForm) -> Result<Self, Error> {
174     diesel::update(person.find(person_id))
175       .set(form)
176       .get_result::<Self>(conn)
177   }
178 }
179
180 impl Person {
181   pub fn ban_person(conn: &PgConnection, person_id: PersonId, ban: bool) -> Result<Self, Error> {
182     diesel::update(person.find(person_id))
183       .set(banned.eq(ban))
184       .get_result::<Self>(conn)
185   }
186
187   pub fn add_admin(conn: &PgConnection, person_id: PersonId, added: bool) -> Result<Self, Error> {
188     diesel::update(person.find(person_id))
189       .set(admin.eq(added))
190       .get_result::<Self>(conn)
191   }
192
193   pub fn find_by_name(conn: &PgConnection, from_name: &str) -> Result<Person, Error> {
194     person
195       .filter(deleted.eq(false))
196       .filter(local.eq(true))
197       .filter(name.eq(from_name))
198       .first::<Person>(conn)
199   }
200
201   pub fn mark_as_updated(conn: &PgConnection, person_id: PersonId) -> Result<Person, Error> {
202     diesel::update(person.find(person_id))
203       .set((last_refreshed_at.eq(naive_now()),))
204       .get_result::<Self>(conn)
205   }
206
207   pub fn delete_account(conn: &PgConnection, person_id: PersonId) -> Result<Person, Error> {
208     use crate::schema::local_user;
209
210     // Set the local user info to none
211     diesel::update(local_user::table.filter(local_user::person_id.eq(person_id)))
212       .set((
213         local_user::email.eq::<Option<String>>(None),
214         local_user::validator_time.eq(naive_now()),
215       ))
216       .execute(conn)?;
217
218     diesel::update(person.find(person_id))
219       .set((
220         display_name.eq::<Option<String>>(None),
221         bio.eq::<Option<String>>(None),
222         matrix_user_id.eq::<Option<String>>(None),
223         deleted.eq(true),
224         updated.eq(naive_now()),
225       ))
226       .get_result::<Self>(conn)
227   }
228
229   pub fn upsert(conn: &PgConnection, person_form: &PersonForm) -> Result<Person, Error> {
230     insert_into(person)
231       .values(person_form)
232       .on_conflict(actor_id)
233       .do_update()
234       .set(person_form)
235       .get_result::<Self>(conn)
236   }
237
238   pub fn read_from_apub_id(conn: &PgConnection, object_id: Url) -> Result<Option<Self>, Error> {
239     use crate::schema::person::dsl::*;
240     let object_id: DbUrl = object_id.into();
241     Ok(
242       person
243         .filter(deleted.eq(false))
244         .filter(actor_id.eq(object_id))
245         .first::<Person>(conn)
246         .ok()
247         .map(Into::into),
248     )
249   }
250
251   pub fn update_deleted(
252     conn: &PgConnection,
253     person_id: PersonId,
254     new_deleted: bool,
255   ) -> Result<Person, Error> {
256     use crate::schema::person::dsl::*;
257     diesel::update(person.find(person_id))
258       .set(deleted.eq(new_deleted))
259       .get_result::<Self>(conn)
260   }
261 }
262
263 #[cfg(test)]
264 mod tests {
265   use crate::{establish_unpooled_connection, source::person::*, traits::Crud};
266
267   #[test]
268   fn test_crud() {
269     let conn = establish_unpooled_connection();
270
271     let new_person = PersonForm {
272       name: "holly".into(),
273       public_key: "nada".to_owned(),
274       ..PersonForm::default()
275     };
276
277     let inserted_person = Person::create(&conn, &new_person).unwrap();
278
279     let expected_person = Person {
280       id: inserted_person.id,
281       name: "holly".into(),
282       display_name: None,
283       avatar: None,
284       banner: None,
285       banned: false,
286       deleted: false,
287       published: inserted_person.published,
288       updated: None,
289       actor_id: inserted_person.actor_id.to_owned(),
290       bio: None,
291       local: true,
292       bot_account: false,
293       admin: false,
294       private_key: None,
295       public_key: "nada".to_owned(),
296       last_refreshed_at: inserted_person.published,
297       inbox_url: inserted_person.inbox_url.to_owned(),
298       shared_inbox_url: None,
299       matrix_user_id: None,
300     };
301
302     let read_person = Person::read(&conn, inserted_person.id).unwrap();
303     let updated_person = Person::update(&conn, inserted_person.id, &new_person).unwrap();
304     let num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
305
306     assert_eq!(expected_person, read_person);
307     assert_eq!(expected_person, inserted_person);
308     assert_eq!(expected_person, updated_person);
309     assert_eq!(1, num_deleted);
310   }
311 }