Skip to content

Commit 675db47

Browse files
Shield: Add name and email addresses to user
1 parent d098cd7 commit 675db47

6 files changed

Lines changed: 288 additions & 50 deletions

File tree

packages/core/shield/src/user.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
11
use std::fmt::Debug;
22

3+
use async_trait::async_trait;
34
use chrono::{DateTime, Utc};
45
use serde::{Deserialize, Serialize};
56

7+
use crate::error::StorageError;
8+
9+
#[async_trait]
610
pub trait User: Debug + Send + Sync {
711
fn id(&self) -> String;
12+
13+
fn name(&self) -> Option<String>;
14+
15+
async fn email_addresses(&self) -> Result<Vec<EmailAddress>, StorageError>;
816
}
917

1018
#[derive(Clone, Debug)]
@@ -52,18 +60,31 @@ pub struct UpdateEmailAddress {
5260

5361
#[cfg(test)]
5462
pub(crate) mod tests {
63+
use async_trait::async_trait;
5564
use serde::{Deserialize, Serialize};
5665

57-
use super::User;
66+
use crate::StorageError;
67+
68+
use super::{EmailAddress, User};
5869

5970
#[derive(Clone, Debug, Deserialize, Serialize)]
6071
pub struct TestUser {
6172
id: String,
73+
name: Option<String>,
6274
}
6375

76+
#[async_trait]
6477
impl User for TestUser {
6578
fn id(&self) -> String {
6679
self.id.clone()
6780
}
81+
82+
fn name(&self) -> Option<String> {
83+
self.name.clone()
84+
}
85+
86+
async fn email_addresses(&self) -> Result<Vec<EmailAddress>, StorageError> {
87+
Ok(vec![])
88+
}
6889
}
6990
}
Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
use async_trait::async_trait;
12
use serde::{Deserialize, Serialize};
2-
use shield::EmailAddress;
3+
use shield::{EmailAddress, StorageError};
34

45
#[derive(Clone, Debug, Deserialize, Serialize)]
56
pub struct User {
@@ -8,8 +9,17 @@ pub struct User {
89
pub(crate) email_addresses: Vec<EmailAddress>,
910
}
1011

12+
#[async_trait]
1113
impl shield::User for User {
1214
fn id(&self) -> String {
1315
self.id.clone()
1416
}
17+
18+
fn name(&self) -> Option<String> {
19+
self.name.clone()
20+
}
21+
22+
async fn email_addresses(&self) -> Result<Vec<EmailAddress>, StorageError> {
23+
Ok(self.email_addresses.clone())
24+
}
1525
}

packages/storage/shield-sea-orm/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,7 @@ pub mod entities;
33
pub mod migrations;
44
mod providers;
55
mod storage;
6+
mod user;
67

78
pub use storage::*;
9+
pub use user::*;

packages/storage/shield-sea-orm/src/providers/oidc.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ use shield_oidc::{
77
};
88

99
use crate::{
10-
entities::{oidc_provider, oidc_provider_connection, user},
10+
entities::{oidc_provider, oidc_provider_connection},
1111
storage::SeaOrmStorage,
12+
user::User,
1213
};
1314

1415
#[async_trait]
15-
impl OidcStorage<user::Model> for SeaOrmStorage {
16+
impl OidcStorage<User> for SeaOrmStorage {
1617
async fn oidc_subproviders(&self) -> Result<Vec<OidcSubprovider>, StorageError> {
1718
oidc_provider::Entity::find()
1819
.all(&self.database)

packages/storage/shield-sea-orm/src/storage.rs

Lines changed: 134 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,13 @@ use shield::{CreateEmailAddress, CreateUser, Storage, StorageError, UpdateUser};
77

88
#[cfg(feature = "entity")]
99
use crate::entities::entity;
10-
use crate::entities::{email_address, prelude::User, user};
10+
use crate::{
11+
entities::{email_address, user},
12+
user::User,
13+
};
1114

1215
pub const SEA_ORM_STORAGE_ID: &str = "sea-orm";
1316

14-
impl shield::User for user::Model {
15-
fn id(&self) -> String {
16-
self.id.to_string()
17-
}
18-
}
19-
2017
#[derive(Clone, Debug)]
2118
pub struct SeaOrmStorage {
2219
pub(crate) database: DatabaseConnection,
@@ -33,49 +30,94 @@ impl SeaOrmStorage {
3330
}
3431

3532
#[async_trait]
36-
impl Storage<user::Model> for SeaOrmStorage {
33+
impl Storage<User> for SeaOrmStorage {
3734
fn id(&self) -> String {
3835
SEA_ORM_STORAGE_ID.to_owned()
3936
}
4037

41-
async fn user_by_id(&self, user_id: &str) -> Result<Option<user::Model>, StorageError> {
42-
User::find_by_id(Self::parse_uuid(user_id)?)
43-
.one(&self.database)
44-
.await
45-
.map_err(|err| StorageError::Engine(err.to_string()))
38+
async fn user_by_id(&self, user_id: &str) -> Result<Option<User>, StorageError> {
39+
#[cfg(feature = "entity")]
40+
{
41+
let user_and_entity = user::Entity::find_by_id(Self::parse_uuid(user_id)?)
42+
.find_also_related(entity::Entity)
43+
.one(&self.database)
44+
.await
45+
.map_err(|err| StorageError::Engine(err.to_string()))?;
46+
47+
match user_and_entity {
48+
Some((user, Some(entity))) => {
49+
Ok(Some(User::new(self.database.clone(), user, entity)))
50+
}
51+
Some((user, None)) => Err(StorageError::NotFound(
52+
"Entity".to_owned(),
53+
user.entity_id.to_string(),
54+
)),
55+
None => Ok(None),
56+
}
57+
}
58+
59+
#[cfg(not(feature = "entity"))]
60+
{
61+
user::Entity::find_by_id(Self::parse_uuid(user_id)?)
62+
.one(&self.database)
63+
.await
64+
.map_err(|err| StorageError::Engine(err.to_string()))
65+
.map(|user| user.map(|user| User::new(self.database.clone(), user)))
66+
}
4667
}
4768

48-
async fn user_by_email(&self, email: &str) -> Result<Option<user::Model>, StorageError> {
69+
async fn user_by_email(&self, email: &str) -> Result<Option<User>, StorageError> {
4970
#[cfg(feature = "entity")]
5071
{
5172
use sea_orm::{JoinType, QuerySelect, RelationTrait};
5273

53-
User::find()
74+
let user_and_entity = user::Entity::find()
75+
.find_also_related(entity::Entity)
5476
.join(JoinType::LeftJoin, user::Relation::Entity.def())
5577
.join(JoinType::LeftJoin, entity::Relation::EmailAddress.def())
5678
.filter(email_address::Column::Email.eq(email))
5779
.one(&self.database)
5880
.await
59-
.map_err(|err| StorageError::Engine(err.to_string()))
81+
.map_err(|err| StorageError::Engine(err.to_string()))?;
82+
83+
match user_and_entity {
84+
Some((user, Some(entity))) => {
85+
Ok(Some(User::new(self.database.clone(), user, entity)))
86+
}
87+
Some((user, None)) => Err(StorageError::NotFound(
88+
"Entity".to_owned(),
89+
user.entity_id.to_string(),
90+
)),
91+
None => Ok(None),
92+
}
6093
}
94+
6195
#[cfg(not(feature = "entity"))]
6296
{
63-
User::find()
97+
user::Entity::find()
6498
.left_join(email_address::Entity)
6599
.filter(email_address::Column::Email.eq(email))
66100
.one(&self.database)
67101
.await
68102
.map_err(|err| StorageError::Engine(err.to_string()))
103+
.map(|user| user.map(|user| User::new(self.database.clone(), user)))
69104
}
70105
}
71106

72107
async fn create_user(
73108
&self,
74109
user: CreateUser,
75110
email_address: CreateEmailAddress,
76-
) -> Result<user::Model, StorageError> {
77-
self.database
78-
.transaction::<_, user::Model, StorageError>(|database_transaction| {
111+
) -> Result<User, StorageError> {
112+
#[cfg(feature = "entity")]
113+
type UserAndEntity = (user::Model, entity::Model);
114+
115+
#[cfg(not(feature = "entity"))]
116+
type UserAndEntity = user::Model;
117+
118+
let user_and_entity = self
119+
.database
120+
.transaction::<_, UserAndEntity, StorageError>(|database_transaction| {
79121
Box::pin(async move {
80122
#[cfg(feature = "entity")]
81123
{
@@ -117,7 +159,7 @@ impl Storage<user::Model> for SeaOrmStorage {
117159
.await
118160
.map_err(|err| StorageError::Engine(err.to_string()))?;
119161

120-
Ok(user)
162+
Ok((user, entity))
121163
}
122164

123165
#[cfg(not(feature = "entity"))]
@@ -158,26 +200,45 @@ impl Storage<user::Model> for SeaOrmStorage {
158200
.map_err(|err| match err {
159201
TransactionError::Connection(err) => StorageError::Engine(err.to_string()),
160202
TransactionError::Transaction(err) => err,
161-
})
203+
})?;
204+
205+
#[cfg(feature = "entity")]
206+
{
207+
let (user, entity) = user_and_entity;
208+
Ok(User::new(self.database.clone(), user, entity))
209+
}
210+
211+
#[cfg(not(feature = "entity"))]
212+
{
213+
let user = user_and_entity;
214+
Ok(User::new(self.database.clone(), user))
215+
}
162216
}
163217

164-
async fn update_user(&self, user: UpdateUser) -> Result<user::Model, StorageError> {
165-
self.database
166-
.transaction::<_, user::Model, StorageError>(|database_transaction| {
167-
Box::pin(async move {
168-
let user_entity = user::Entity::find()
169-
.filter(user::Column::Id.eq(Self::parse_uuid(&user.id)?))
170-
.one(database_transaction)
171-
.await
172-
.map_err(|err| StorageError::Engine(err.to_string()))?
173-
.ok_or_else(|| {
174-
StorageError::NotFound("User".to_owned(), user.id.clone())
175-
})?;
218+
async fn update_user(&self, user: UpdateUser) -> Result<User, StorageError> {
219+
#[cfg(feature = "entity")]
220+
type UserAndEntity = (user::Model, entity::Model);
176221

222+
#[cfg(not(feature = "entity"))]
223+
type UserAndEntity = user::Model;
224+
225+
let user_and_entity = self
226+
.database
227+
.transaction::<_, UserAndEntity, StorageError>(|database_transaction| {
228+
Box::pin(async move {
177229
#[cfg(feature = "entity")]
178230
{
179231
use sea_orm::ModelTrait;
180232

233+
let user_entity = user::Entity::find()
234+
.filter(user::Column::Id.eq(Self::parse_uuid(&user.id)?))
235+
.one(database_transaction)
236+
.await
237+
.map_err(|err| StorageError::Engine(err.to_string()))?
238+
.ok_or_else(|| {
239+
StorageError::NotFound("User".to_owned(), user.id.clone())
240+
})?;
241+
181242
let mut entity_active_model: entity::ActiveModel = user_entity
182243
.find_related(entity::Entity)
183244
.one(database_transaction)
@@ -195,31 +256,58 @@ impl Storage<user::Model> for SeaOrmStorage {
195256
entity_active_model.name = ActiveValue::Set(name);
196257
}
197258

198-
entity_active_model
259+
let entity = entity_active_model
199260
.update(database_transaction)
200261
.await
201262
.map_err(|err| StorageError::Engine(err.to_string()))?;
202-
}
203263

204-
#[allow(unused_mut)]
205-
let mut user_active_model: user::ActiveModel = user_entity.into();
264+
Ok((user_entity, entity))
265+
}
206266

207267
#[cfg(not(feature = "entity"))]
208-
if let Some(Some(name)) = user.name {
209-
user_active_model.name = ActiveValue::Set(name);
210-
}
268+
{
269+
let user_entity = user::Entity::find()
270+
.filter(user::Column::Id.eq(Self::parse_uuid(&user.id)?))
271+
.one(database_transaction)
272+
.await
273+
.map_err(|err| StorageError::Engine(err.to_string()))?
274+
.ok_or_else(|| {
275+
StorageError::NotFound("User".to_owned(), user.id.clone())
276+
})?;
277+
278+
let mut user_active_model: user::ActiveModel = user_entity.into();
211279

212-
user_active_model
213-
.update(database_transaction)
214-
.await
215-
.map_err(|err| StorageError::Engine(err.to_string()))
280+
#[cfg(not(feature = "entity"))]
281+
if let Some(Some(name)) = user.name {
282+
user_active_model.name = ActiveValue::Set(name);
283+
}
284+
285+
let user = user_active_model
286+
.update(database_transaction)
287+
.await
288+
.map_err(|err| StorageError::Engine(err.to_string()))?;
289+
290+
Ok(user)
291+
}
216292
})
217293
})
218294
.await
219295
.map_err(|err| match err {
220296
TransactionError::Connection(err) => StorageError::Engine(err.to_string()),
221297
TransactionError::Transaction(err) => err,
222-
})
298+
})?;
299+
300+
#[cfg(feature = "entity")]
301+
{
302+
let (user, entity) = user_and_entity;
303+
Ok(User::new(self.database.clone(), user, entity))
304+
}
305+
306+
#[cfg(not(feature = "entity"))]
307+
{
308+
let user = user_and_entity;
309+
Ok(User::new(self.database.clone(), user))
310+
}
223311
}
224312

225313
async fn delete_user(&self, user_id: &str) -> Result<(), StorageError> {

0 commit comments

Comments
 (0)