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::{UserAgent, UserEmailAuthentication, UserRegistration};
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<UserAgent>,
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 /// Complete a [`UserRegistration`]
142 ///
143 /// Returns the updated [`UserRegistration`]
144 ///
145 /// # Parameters
146 ///
147 /// * `clock`: The clock used to generate timestamps
148 /// * `user_registration`: The [`UserRegistration`] to complete
149 ///
150 /// # Errors
151 ///
152 /// Returns [`Self::Error`] if the underlying repository fails or if the
153 /// registration is already completed
154 async fn complete(
155 &mut self,
156 clock: &dyn Clock,
157 user_registration: UserRegistration,
158 ) -> Result<UserRegistration, Self::Error>;
159}
160
161repository_impl!(UserRegistrationRepository:
162 async fn lookup(&mut self, id: Ulid) -> Result<Option<UserRegistration>, Self::Error>;
163 async fn add(
164 &mut self,
165 rng: &mut (dyn RngCore + Send),
166 clock: &dyn Clock,
167 username: String,
168 ip_address: Option<IpAddr>,
169 user_agent: Option<UserAgent>,
170 post_auth_action: Option<serde_json::Value>,
171 ) -> Result<UserRegistration, Self::Error>;
172 async fn set_display_name(
173 &mut self,
174 user_registration: UserRegistration,
175 display_name: String,
176 ) -> Result<UserRegistration, Self::Error>;
177 async fn set_terms_url(
178 &mut self,
179 user_registration: UserRegistration,
180 terms_url: Url,
181 ) -> Result<UserRegistration, Self::Error>;
182 async fn set_email_authentication(
183 &mut self,
184 user_registration: UserRegistration,
185 email_authentication: &UserEmailAuthentication,
186 ) -> Result<UserRegistration, Self::Error>;
187 async fn set_password(
188 &mut self,
189 user_registration: UserRegistration,
190 hashed_password: String,
191 version: u16,
192 ) -> Result<UserRegistration, Self::Error>;
193 async fn complete(
194 &mut self,
195 clock: &dyn Clock,
196 user_registration: UserRegistration,
197 ) -> Result<UserRegistration, Self::Error>;
198);