Skip to main content

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