subgraph/graphql/schema/create_auth_service/update_user/
mod.rs

1use crate::{
2    configuration::subgraph::data_sources::sql::DialectEnum,
3    data_sources::{sql::PoolEnum, DataSource},
4    graphql::schema::ServiceSchema,
5};
6use bson::{doc, Regex};
7use log::debug;
8use mongodb::options::FindOneAndUpdateOptions;
9
10use super::ServiceUser;
11
12pub struct UpdateUserInput {
13    pub identifier: String,
14    pub registration_state: Option<String>,
15    pub passkey: Option<String>,
16    pub authentication_state: Option<String>,
17}
18
19impl ServiceSchema {
20    fn create_set_options(update_user_input: UpdateUserInput) -> String {
21        let mut set_options = String::new();
22        if let Some(registration_state) = update_user_input.registration_state {
23            set_options.push_str(&format!("registration_state = '{}'", registration_state));
24        }
25        if let Some(passkey) = update_user_input.passkey {
26            if !set_options.is_empty() {
27                set_options.push_str(", ");
28            }
29            set_options.push_str(&format!("passkey = '{}'", passkey));
30        }
31        if let Some(authentication_state) = update_user_input.authentication_state {
32            if !set_options.is_empty() {
33                set_options.push_str(", ");
34            }
35            set_options.push_str(&format!(
36                "authentication_state = '{}'",
37                authentication_state
38            ));
39        }
40
41        set_options
42    }
43
44    pub async fn update_user(
45        data_source: &DataSource,
46        service_user: ServiceUser,
47    ) -> Result<(), async_graphql::Error> {
48        debug!("Updating user: {:?}", &service_user);
49
50        let updated: Result<(), async_graphql::Error> = match &data_source {
51            DataSource::Mongo(mongo_ds) => {
52                let identifer_regex = Regex {
53                    pattern: service_user.identifier.to_string(),
54                    options: "i".to_string(),
55                };
56                let filter = doc! {
57                    "identifier": identifer_regex
58                };
59                let mut update = doc! {
60                    "$set": {
61                        "registration_state": serde_json::to_string(&service_user.registration_state).unwrap(),
62                        "passkey": serde_json::to_string(&service_user.passkey).unwrap(),
63                    }
64                };
65                if let Some(authentication_state) = service_user.authentication_state {
66                    update.insert(
67                        "$set",
68                        doc! {
69                            "authentication_state": serde_json::to_string(&authentication_state).unwrap(),
70                        },
71                    );
72                }
73                let options = FindOneAndUpdateOptions::builder().upsert(true).build();
74                let user = mongo_ds
75                    .db
76                    .collection::<ServiceUser>("subgraph_user")
77                    .find_one_and_update(filter, update, options)
78                    .await;
79
80                match user {
81                    Ok(user) => {
82                        if let Some(_user) = user {
83                            Ok(())
84                        } else {
85                            Err(async_graphql::Error::new(format!("Could not find user.")))
86                        }
87                    }
88                    Err(e) => Err(async_graphql::Error::new(format!(
89                        "Something went wrong when finding the user: {:?}",
90                        e
91                    ))),
92                }
93            }
94            DataSource::SQL(sql_ds) => match sql_ds.config.dialect {
95                DialectEnum::MYSQL => {
96                    let set_query = ServiceSchema::create_set_options(UpdateUserInput {
97                        identifier: service_user.identifier.clone(),
98                        registration_state: Some(
99                            serde_json::to_string(&service_user.registration_state)
100                                .unwrap_or("".to_string())
101                                .to_string(),
102                        ),
103                        passkey: Some(
104                            serde_json::to_string(&service_user.passkey)
105                                .unwrap_or("".to_string())
106                                .to_string(),
107                        ),
108                        authentication_state: Some(
109                            serde_json::to_string(&service_user.authentication_state)
110                                .unwrap_or("".to_string())
111                                .to_string(),
112                        ),
113                    });
114                    let query_string = format!(
115                        "UPDATE subgraph_user SET {} WHERE LOWER(identifier) = (?);",
116                        set_query
117                    );
118                    let query = sqlx::query(&query_string).bind(service_user.identifier.clone());
119                    let result = match sql_ds.pool.clone() {
120                        PoolEnum::MySql(pool) => query.execute(&pool).await,
121                        _ => panic!("Pool not supported."),
122                    };
123
124                    match result {
125                        Ok(res) => {
126                            if res.rows_affected() > 0 {
127                                Ok(())
128                            } else {
129                                Err(async_graphql::Error::new(format!("Could not find user.")))
130                            }
131                        }
132                        Err(error) => Err(async_graphql::Error::new(format!(
133                            "Could not update user: {:?}",
134                            error
135                        ))),
136                    }
137                }
138                DialectEnum::POSTGRES => {
139                    let set_query = ServiceSchema::create_set_options(UpdateUserInput {
140                        identifier: service_user.identifier.clone(),
141                        registration_state: Some(
142                            serde_json::to_string(&service_user.registration_state)
143                                .unwrap_or("".to_string())
144                                .to_string(),
145                        ),
146                        passkey: Some(
147                            serde_json::to_string(&service_user.passkey)
148                                .unwrap_or("".to_string())
149                                .to_string(),
150                        ),
151                        authentication_state: Some(
152                            serde_json::to_string(&service_user.authentication_state)
153                                .unwrap_or("".to_string())
154                                .to_string(),
155                        ),
156                    });
157                    let query_string = format!(
158                        "UPDATE subgraph_user SET {} WHERE LOWER(identifier) = LOWER($1) RETURNING *;",
159                        set_query
160                    );
161                    let query = sqlx::query(&query_string).bind(service_user.identifier.clone());
162                    let result = match sql_ds.pool.clone() {
163                        PoolEnum::Postgres(pool) => query.fetch_one(&pool).await,
164                        _ => panic!("Pool not supported."),
165                    };
166
167                    match result {
168                        Ok(_) => Ok(()),
169                        Err(error) => Err(async_graphql::Error::new(format!(
170                            "Could not update user: {:?}",
171                            error
172                        ))),
173                    }
174                }
175                DialectEnum::SQLITE => {
176                    let set_query = ServiceSchema::create_set_options(UpdateUserInput {
177                        identifier: service_user.identifier.clone(),
178                        registration_state: Some(
179                            serde_json::to_string(&service_user.registration_state)
180                                .unwrap_or("".to_string())
181                                .to_string(),
182                        ),
183                        passkey: Some(
184                            serde_json::to_string(&service_user.passkey)
185                                .unwrap_or("".to_string())
186                                .to_string(),
187                        ),
188                        authentication_state: Some(
189                            serde_json::to_string(&service_user.authentication_state)
190                                .unwrap_or("".to_string())
191                                .to_string(),
192                        ),
193                    });
194                    let query_string = format!(
195                        "UPDATE subgraph_user SET {} WHERE LOWER(identifier) = LOWER(?);",
196                        set_query
197                    );
198                    let query = sqlx::query(&query_string).bind(service_user.identifier.clone());
199                    let result = match sql_ds.pool.clone() {
200                        PoolEnum::SqLite(pool) => query.execute(&pool).await,
201                        _ => panic!("Pool not supported."),
202                    };
203
204                    match result {
205                        Ok(res) => {
206                            if res.rows_affected() > 0 {
207                                Ok(())
208                            } else {
209                                Err(async_graphql::Error::new(format!("Could not find user.")))
210                            }
211                        }
212                        Err(error) => Err(async_graphql::Error::new(format!(
213                            "Could not update user: {:?}",
214                            error
215                        ))),
216                    }
217                }
218            },
219            _ => Err(async_graphql::Error::new(format!("Failed to find user."))),
220        };
221
222        debug!("Updated user");
223
224        updated
225    }
226}