mas_storage/user/registration.rs
1// Copyright 2025 New Vector Ltd.
2//
3// SPDX-License-Identifier: AGPL-3.0-only
4// Please see LICENSE in the repository root for full details.
5
6use std::net::IpAddr;
7
8use async_trait::async_trait;
9use mas_data_model::{UserEmailAuthentication, UserRegistration, UserRegistrationToken};
10use rand_core::RngCore;
11use ulid::Ulid;
12use url::Url;
13
14use crate::{Clock, repository_impl};
15
16/// A [`UserRegistrationRepository`] helps interacting with [`UserRegistration`]
17/// saved in the storage backend
18#[async_trait]
19pub trait UserRegistrationRepository: Send + Sync {
20 /// The error type returned by the repository
21 type Error;
22
23 /// Lookup a [`UserRegistration`] by its ID
24 ///
25 /// Returns `None` if no [`UserRegistration`] was found
26 ///
27 /// # Parameters
28 ///
29 /// * `id`: The ID of the [`UserRegistration`] to lookup
30 ///
31 /// # Errors
32 ///
33 /// Returns [`Self::Error`] if the underlying repository fails
34 async fn lookup(&mut self, id: Ulid) -> Result<Option<UserRegistration>, Self::Error>;
35
36 /// Create a new [`UserRegistration`] session
37 ///
38 /// Returns the newly created [`UserRegistration`]
39 ///
40 /// # Parameters
41 ///
42 /// * `rng`: The random number generator to use
43 /// * `clock`: The clock used to generate timestamps
44 /// * `username`: The username of the user
45 /// * `ip_address`: The IP address of the user agent, if any
46 /// * `user_agent`: The user agent of the user agent, if any
47 /// * `post_auth_action`: The post auth action to execute after the
48 /// registration, if any
49 ///
50 /// # Errors
51 ///
52 /// Returns [`Self::Error`] if the underlying repository fails
53 async fn add(
54 &mut self,
55 rng: &mut (dyn RngCore + Send),
56 clock: &dyn Clock,
57 username: String,
58 ip_address: Option<IpAddr>,
59 user_agent: Option<String>,
60 post_auth_action: Option<serde_json::Value>,
61 ) -> Result<UserRegistration, Self::Error>;
62
63 /// Set the display name of a [`UserRegistration`]
64 ///
65 /// Returns the updated [`UserRegistration`]
66 ///
67 /// # Parameters
68 ///
69 /// * `user_registration`: The [`UserRegistration`] to update
70 /// * `display_name`: The display name to set
71 ///
72 /// # Errors
73 ///
74 /// Returns [`Self::Error`] if the underlying repository fails or if the
75 /// registration is already completed
76 async fn set_display_name(
77 &mut self,
78 user_registration: UserRegistration,
79 display_name: String,
80 ) -> Result<UserRegistration, Self::Error>;
81
82 /// Set the terms URL of a [`UserRegistration`]
83 ///
84 /// Returns the updated [`UserRegistration`]
85 ///
86 /// # Parameters
87 ///
88 /// * `user_registration`: The [`UserRegistration`] to update
89 /// * `terms_url`: The terms URL to set
90 ///
91 /// # Errors
92 ///
93 /// Returns [`Self::Error`] if the underlying repository fails or if the
94 /// registration is already completed
95 async fn set_terms_url(
96 &mut self,
97 user_registration: UserRegistration,
98 terms_url: Url,
99 ) -> Result<UserRegistration, Self::Error>;
100
101 /// Set the email authentication code of a [`UserRegistration`]
102 ///
103 /// Returns the updated [`UserRegistration`]
104 ///
105 /// # Parameters
106 ///
107 /// * `user_registration`: The [`UserRegistration`] to update
108 /// * `email_authentication`: The [`UserEmailAuthentication`] to set
109 ///
110 /// # Errors
111 ///
112 /// Returns [`Self::Error`] if the underlying repository fails or if the
113 /// registration is already completed
114 async fn set_email_authentication(
115 &mut self,
116 user_registration: UserRegistration,
117 email_authentication: &UserEmailAuthentication,
118 ) -> Result<UserRegistration, Self::Error>;
119
120 /// Set the password of a [`UserRegistration`]
121 ///
122 /// Returns the updated [`UserRegistration`]
123 ///
124 /// # Parameters
125 ///
126 /// * `user_registration`: The [`UserRegistration`] to update
127 /// * `hashed_password`: The hashed password to set
128 /// * `version`: The version of the hashing scheme
129 ///
130 /// # Errors
131 ///
132 /// Returns [`Self::Error`] if the underlying repository fails or if the
133 /// registration is already completed
134 async fn set_password(
135 &mut self,
136 user_registration: UserRegistration,
137 hashed_password: String,
138 version: u16,
139 ) -> Result<UserRegistration, Self::Error>;
140
141 /// Set the registration token of a [`UserRegistration`]
142 ///
143 /// Returns the updated [`UserRegistration`]
144 ///
145 /// # Parameters
146 ///
147 /// * `user_registration`: The [`UserRegistration`] to update
148 /// * `user_registration_token`: The [`UserRegistrationToken`] to set
149 ///
150 /// # Errors
151 ///
152 /// Returns [`Self::Error`] if the underlying repository fails or if the
153 /// registration is already completed
154 async fn set_registration_token(
155 &mut self,
156 user_registration: UserRegistration,
157 user_registration_token: &UserRegistrationToken,
158 ) -> Result<UserRegistration, Self::Error>;
159
160 /// Complete a [`UserRegistration`]
161 ///
162 /// Returns the updated [`UserRegistration`]
163 ///
164 /// # Parameters
165 ///
166 /// * `clock`: The clock used to generate timestamps
167 /// * `user_registration`: The [`UserRegistration`] to complete
168 ///
169 /// # Errors
170 ///
171 /// Returns [`Self::Error`] if the underlying repository fails or if the
172 /// registration is already completed
173 async fn complete(
174 &mut self,
175 clock: &dyn Clock,
176 user_registration: UserRegistration,
177 ) -> Result<UserRegistration, Self::Error>;
178}
179
180repository_impl!(UserRegistrationRepository:
181 async fn lookup(&mut self, id: Ulid) -> Result<Option<UserRegistration>, Self::Error>;
182 async fn add(
183 &mut self,
184 rng: &mut (dyn RngCore + Send),
185 clock: &dyn Clock,
186 username: String,
187 ip_address: Option<IpAddr>,
188 user_agent: Option<String>,
189 post_auth_action: Option<serde_json::Value>,
190 ) -> Result<UserRegistration, Self::Error>;
191 async fn set_display_name(
192 &mut self,
193 user_registration: UserRegistration,
194 display_name: String,
195 ) -> Result<UserRegistration, Self::Error>;
196 async fn set_terms_url(
197 &mut self,
198 user_registration: UserRegistration,
199 terms_url: Url,
200 ) -> Result<UserRegistration, Self::Error>;
201 async fn set_email_authentication(
202 &mut self,
203 user_registration: UserRegistration,
204 email_authentication: &UserEmailAuthentication,
205 ) -> Result<UserRegistration, Self::Error>;
206 async fn set_password(
207 &mut self,
208 user_registration: UserRegistration,
209 hashed_password: String,
210 version: u16,
211 ) -> Result<UserRegistration, Self::Error>;
212 async fn set_registration_token(
213 &mut self,
214 user_registration: UserRegistration,
215 user_registration_token: &UserRegistrationToken,
216 ) -> Result<UserRegistration, Self::Error>;
217 async fn complete(
218 &mut self,
219 clock: &dyn Clock,
220 user_registration: UserRegistration,
221 ) -> Result<UserRegistration, Self::Error>;
222);