mas_storage/user/
registration.rs

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