1+ use std:: path:: { Path , PathBuf } ;
2+
13use serde:: { Deserialize , Serialize } ;
24use sqlx:: Row as _;
35use tracing:: * ;
@@ -12,6 +14,7 @@ pub trait UserStore: Send + Sync {
1214#[ derive( Debug , Clone ) ]
1315pub enum UserStoreKind {
1416 Static ( StaticUserStore ) ,
17+ File ( FileUserStore ) ,
1518 SQL ( SQLUserStore ) ,
1619}
1720
@@ -20,6 +23,7 @@ impl UserStore for UserStoreKind {
2023 async fn from_email ( & mut self , email : & str ) -> Option < User > {
2124 match self {
2225 UserStoreKind :: Static ( store) => store. from_email ( email) . await ,
26+ UserStoreKind :: File ( store) => store. from_email ( email) . await ,
2327 UserStoreKind :: SQL ( store) => store. from_email ( email) . await ,
2428 }
2529 }
@@ -30,7 +34,7 @@ pub struct StaticUserStore(Vec<User>);
3034
3135impl StaticUserStore {
3236 pub fn new ( users : Vec < User > ) -> Self {
33- StaticUserStore ( users)
37+ Self ( users)
3438 }
3539}
3640
@@ -41,6 +45,36 @@ impl UserStore for StaticUserStore {
4145 }
4246}
4347
48+ #[ derive( Debug , Clone , Serialize , Deserialize ) ]
49+ pub struct FileUserStore ( String ) ;
50+
51+ impl FileUserStore {
52+ pub fn new ( path : String ) -> Self {
53+ Self ( path)
54+ }
55+ }
56+
57+ #[ async_trait:: async_trait]
58+ impl UserStore for FileUserStore {
59+ async fn from_email ( & mut self , email : & str ) -> Option < User > {
60+ let users_contents = match std:: fs:: read_to_string ( self . 0 . clone ( ) ) {
61+ Ok ( contents) => contents,
62+ Err ( e) => {
63+ error ! ( "Failed to read users file: {}" , e) ;
64+ return None ;
65+ }
66+ } ;
67+ let users = match serde_yaml:: from_str :: < Vec < User > > ( & users_contents) {
68+ Ok ( users) => users,
69+ Err ( e) => {
70+ error ! ( "Failed to parse users file: {}" , e) ;
71+ return None ;
72+ }
73+ } ;
74+ users. iter ( ) . find ( |user| user. email == email) . cloned ( )
75+ }
76+ }
77+
4478#[ derive( Debug , Clone ) ]
4579pub struct SQLUserStore {
4680 conn : sqlx:: AnyPool ,
0 commit comments