Skip to main content

rustauth_core/db/adapter/
traits.rs

1use std::future::Future;
2use std::pin::Pin;
3use std::sync::Arc;
4
5use crate::db::schema::DbSchema;
6use crate::error::RustAuthError;
7use crate::plugin::PluginMigration;
8
9use super::capabilities::{AdapterCapabilities, SchemaCreation};
10use super::query::{Count, Create, Delete, DeleteMany, FindMany, FindOne, Update, UpdateMany};
11use super::value::DbRecord;
12
13pub type AdapterResult<T> = Result<T, RustAuthError>;
14
15/// Boxed async result returned by database adapter methods.
16pub type AdapterFuture<'a, T> = Pin<Box<dyn Future<Output = AdapterResult<T>> + Send + 'a>>;
17
18/// Adapter handle passed to transaction callbacks.
19pub type TransactionAdapter<'tx> = Box<dyn DbAdapter + 'tx>;
20
21/// Callback executed inside an adapter transaction.
22pub type TransactionCallback<'a> =
23    Box<dyn for<'tx> FnOnce(TransactionAdapter<'tx>) -> AdapterFuture<'tx, ()> + Send + 'a>;
24
25/// Execute a transaction callback directly when native transactions are unavailable.
26pub fn run_transaction_without_native_support<'a, A>(
27    adapter: &'a A,
28    callback: TransactionCallback<'a>,
29) -> AdapterFuture<'a, ()>
30where
31    A: DbAdapter,
32{
33    callback(Box::new(adapter))
34}
35
36/// Async database adapter contract used by core authentication behavior.
37///
38/// Concrete database integrations should live outside `rustauth-core` and
39/// implement this trait without forcing their driver or ORM dependencies into
40/// the core crate.
41pub trait DbAdapter: Send + Sync {
42    fn id(&self) -> &str;
43
44    fn capabilities(&self) -> AdapterCapabilities {
45        AdapterCapabilities::new(self.id())
46    }
47
48    fn create<'a>(&'a self, query: Create) -> AdapterFuture<'a, DbRecord>;
49
50    fn find_one<'a>(&'a self, query: FindOne) -> AdapterFuture<'a, Option<DbRecord>>;
51
52    fn find_many<'a>(&'a self, query: FindMany) -> AdapterFuture<'a, Vec<DbRecord>>;
53
54    fn count<'a>(&'a self, query: Count) -> AdapterFuture<'a, u64>;
55
56    fn update<'a>(&'a self, query: Update) -> AdapterFuture<'a, Option<DbRecord>>;
57
58    fn update_many<'a>(&'a self, query: UpdateMany) -> AdapterFuture<'a, u64>;
59
60    fn delete<'a>(&'a self, query: Delete) -> AdapterFuture<'a, ()>;
61
62    fn delete_many<'a>(&'a self, query: DeleteMany) -> AdapterFuture<'a, u64>;
63
64    fn transaction<'a>(&'a self, callback: TransactionCallback<'a>) -> AdapterFuture<'a, ()>;
65
66    fn create_schema<'a>(
67        &'a self,
68        _schema: &'a DbSchema,
69        _file: Option<&'a str>,
70    ) -> AdapterFuture<'a, Option<SchemaCreation>> {
71        Box::pin(async { Ok(None) })
72    }
73
74    fn run_migrations<'a>(&'a self, _schema: &'a DbSchema) -> AdapterFuture<'a, ()> {
75        Box::pin(async {
76            Err(RustAuthError::InvalidConfig(
77                "adapter does not support explicit migrations".to_owned(),
78            ))
79        })
80    }
81
82    fn run_plugin_migrations<'a>(
83        &'a self,
84        _migrations: &'a [PluginMigration],
85    ) -> AdapterFuture<'a, ()> {
86        Box::pin(async { Ok(()) })
87    }
88}
89
90impl<A> DbAdapter for &A
91where
92    A: DbAdapter + ?Sized,
93{
94    fn id(&self) -> &str {
95        (**self).id()
96    }
97
98    fn capabilities(&self) -> AdapterCapabilities {
99        (**self).capabilities()
100    }
101
102    fn create<'a>(&'a self, query: Create) -> AdapterFuture<'a, DbRecord> {
103        (**self).create(query)
104    }
105
106    fn find_one<'a>(&'a self, query: FindOne) -> AdapterFuture<'a, Option<DbRecord>> {
107        (**self).find_one(query)
108    }
109
110    fn find_many<'a>(&'a self, query: FindMany) -> AdapterFuture<'a, Vec<DbRecord>> {
111        (**self).find_many(query)
112    }
113
114    fn count<'a>(&'a self, query: Count) -> AdapterFuture<'a, u64> {
115        (**self).count(query)
116    }
117
118    fn update<'a>(&'a self, query: Update) -> AdapterFuture<'a, Option<DbRecord>> {
119        (**self).update(query)
120    }
121
122    fn update_many<'a>(&'a self, query: UpdateMany) -> AdapterFuture<'a, u64> {
123        (**self).update_many(query)
124    }
125
126    fn delete<'a>(&'a self, query: Delete) -> AdapterFuture<'a, ()> {
127        (**self).delete(query)
128    }
129
130    fn delete_many<'a>(&'a self, query: DeleteMany) -> AdapterFuture<'a, u64> {
131        (**self).delete_many(query)
132    }
133
134    fn transaction<'a>(&'a self, callback: TransactionCallback<'a>) -> AdapterFuture<'a, ()> {
135        (**self).transaction(callback)
136    }
137
138    fn create_schema<'a>(
139        &'a self,
140        schema: &'a DbSchema,
141        file: Option<&'a str>,
142    ) -> AdapterFuture<'a, Option<SchemaCreation>> {
143        (**self).create_schema(schema, file)
144    }
145
146    fn run_migrations<'a>(&'a self, schema: &'a DbSchema) -> AdapterFuture<'a, ()> {
147        (**self).run_migrations(schema)
148    }
149
150    fn run_plugin_migrations<'a>(
151        &'a self,
152        migrations: &'a [PluginMigration],
153    ) -> AdapterFuture<'a, ()> {
154        (**self).run_plugin_migrations(migrations)
155    }
156}
157
158impl<A> DbAdapter for Box<A>
159where
160    A: DbAdapter + ?Sized,
161{
162    fn id(&self) -> &str {
163        (**self).id()
164    }
165
166    fn capabilities(&self) -> AdapterCapabilities {
167        (**self).capabilities()
168    }
169
170    fn create<'a>(&'a self, query: Create) -> AdapterFuture<'a, DbRecord> {
171        (**self).create(query)
172    }
173
174    fn find_one<'a>(&'a self, query: FindOne) -> AdapterFuture<'a, Option<DbRecord>> {
175        (**self).find_one(query)
176    }
177
178    fn find_many<'a>(&'a self, query: FindMany) -> AdapterFuture<'a, Vec<DbRecord>> {
179        (**self).find_many(query)
180    }
181
182    fn count<'a>(&'a self, query: Count) -> AdapterFuture<'a, u64> {
183        (**self).count(query)
184    }
185
186    fn update<'a>(&'a self, query: Update) -> AdapterFuture<'a, Option<DbRecord>> {
187        (**self).update(query)
188    }
189
190    fn update_many<'a>(&'a self, query: UpdateMany) -> AdapterFuture<'a, u64> {
191        (**self).update_many(query)
192    }
193
194    fn delete<'a>(&'a self, query: Delete) -> AdapterFuture<'a, ()> {
195        (**self).delete(query)
196    }
197
198    fn delete_many<'a>(&'a self, query: DeleteMany) -> AdapterFuture<'a, u64> {
199        (**self).delete_many(query)
200    }
201
202    fn transaction<'a>(&'a self, callback: TransactionCallback<'a>) -> AdapterFuture<'a, ()> {
203        (**self).transaction(callback)
204    }
205
206    fn create_schema<'a>(
207        &'a self,
208        schema: &'a DbSchema,
209        file: Option<&'a str>,
210    ) -> AdapterFuture<'a, Option<SchemaCreation>> {
211        (**self).create_schema(schema, file)
212    }
213
214    fn run_migrations<'a>(&'a self, schema: &'a DbSchema) -> AdapterFuture<'a, ()> {
215        (**self).run_migrations(schema)
216    }
217
218    fn run_plugin_migrations<'a>(
219        &'a self,
220        migrations: &'a [PluginMigration],
221    ) -> AdapterFuture<'a, ()> {
222        (**self).run_plugin_migrations(migrations)
223    }
224}
225
226impl<A> DbAdapter for Arc<A>
227where
228    A: DbAdapter + ?Sized,
229{
230    fn id(&self) -> &str {
231        (**self).id()
232    }
233
234    fn capabilities(&self) -> AdapterCapabilities {
235        (**self).capabilities()
236    }
237
238    fn create<'a>(&'a self, query: Create) -> AdapterFuture<'a, DbRecord> {
239        (**self).create(query)
240    }
241
242    fn find_one<'a>(&'a self, query: FindOne) -> AdapterFuture<'a, Option<DbRecord>> {
243        (**self).find_one(query)
244    }
245
246    fn find_many<'a>(&'a self, query: FindMany) -> AdapterFuture<'a, Vec<DbRecord>> {
247        (**self).find_many(query)
248    }
249
250    fn count<'a>(&'a self, query: Count) -> AdapterFuture<'a, u64> {
251        (**self).count(query)
252    }
253
254    fn update<'a>(&'a self, query: Update) -> AdapterFuture<'a, Option<DbRecord>> {
255        (**self).update(query)
256    }
257
258    fn update_many<'a>(&'a self, query: UpdateMany) -> AdapterFuture<'a, u64> {
259        (**self).update_many(query)
260    }
261
262    fn delete<'a>(&'a self, query: Delete) -> AdapterFuture<'a, ()> {
263        (**self).delete(query)
264    }
265
266    fn delete_many<'a>(&'a self, query: DeleteMany) -> AdapterFuture<'a, u64> {
267        (**self).delete_many(query)
268    }
269
270    fn transaction<'a>(&'a self, callback: TransactionCallback<'a>) -> AdapterFuture<'a, ()> {
271        (**self).transaction(callback)
272    }
273
274    fn create_schema<'a>(
275        &'a self,
276        schema: &'a DbSchema,
277        file: Option<&'a str>,
278    ) -> AdapterFuture<'a, Option<SchemaCreation>> {
279        (**self).create_schema(schema, file)
280    }
281
282    fn run_migrations<'a>(&'a self, schema: &'a DbSchema) -> AdapterFuture<'a, ()> {
283        (**self).run_migrations(schema)
284    }
285
286    fn run_plugin_migrations<'a>(
287        &'a self,
288        migrations: &'a [PluginMigration],
289    ) -> AdapterFuture<'a, ()> {
290        (**self).run_plugin_migrations(migrations)
291    }
292}