@@ -3,7 +3,7 @@ use libsql::{Row, params, Database};
33use serde:: { Deserialize , Serialize } ;
44use tokio:: sync:: Mutex ;
55use crate :: dross:: { DrossError , DrossHolder , DrossResult } ;
6- use crate :: repository:: { Repository , RepositoryError , RepositoryResult } ;
6+ use crate :: repository:: { Repository , RepositoryError , RepositoryItem , RepositoryResult } ;
77
88#[ derive( Clone ) ]
99pub struct FaeryRepository {
@@ -16,14 +16,59 @@ impl FaeryRepository {
1616 db,
1717 }
1818 }
19+
20+ // TODO: Secure this method
21+ pub async fn update_auth_token ( & self , id : i64 , auth_token : String ) -> RepositoryResult < ( ) > {
22+ let db = self . db . lock ( ) . await . connect ( ) . unwrap ( ) ;
23+ let result = db. execute ( "UPDATE faeries SET auth_token = ?1 WHERE id = ?2" , params ! [ auth_token, id] ) . await ;
24+ match result {
25+ Ok ( _) => Ok ( ( ) ) ,
26+ Err ( _) => Err ( RepositoryError :: Other ) ,
27+ }
28+ }
29+ }
30+
31+ impl RepositoryItem for Faery {
32+ fn masked_columns ( is_admin : bool ) -> Vec < String > {
33+ let mut columns = vec ! [ "auth_token" . to_string( ) ] ;
34+ if !is_admin {
35+ columns. push ( "email" . to_string ( ) ) ;
36+ }
37+ columns
38+ }
39+
40+ fn saved_columns ( ) -> Vec < String > {
41+ // get all columns
42+ let columns = Faery :: all_columns ( ) ;
43+ // filter out masked columns, assuming is_admin is true
44+ let masked_columns = Faery :: masked_columns ( true ) ;
45+ columns. into_iter ( ) . filter ( |c| !masked_columns. contains ( c) ) . collect ( )
46+ }
47+
48+ fn all_columns ( ) -> Vec < String > {
49+ vec ! [
50+ "id" . to_string( ) ,
51+ "name" . to_string( ) ,
52+ "is_admin" . to_string( ) ,
53+ "email" . to_string( ) ,
54+ "auth_token" . to_string( ) ,
55+ "dross" . to_string( ) ,
56+ ]
57+ }
58+
59+ fn table_name ( ) -> String {
60+ "faeries" . to_string ( )
61+ }
62+
1963}
2064
2165#[ shuttle_runtime:: async_trait]
2266// Mark: Repository
2367impl Repository for FaeryRepository {
2468 type Item = Faery ;
69+ type RowIdentifier = i64 ;
2570
26- async fn create ( & self , faery : Option < Faery > ) -> RepositoryResult < ( ) > {
71+ async fn create ( & self , faery : Option < Faery > ) -> RepositoryResult < i64 > {
2772 match faery {
2873 Some ( faery) => {
2974 self . save ( faery) . await
@@ -32,7 +77,7 @@ impl Repository for FaeryRepository {
3277 }
3378 }
3479
35- async fn save ( & self , faery : Faery ) -> RepositoryResult < ( ) > {
80+ async fn save ( & self , faery : Faery ) -> RepositoryResult < i64 > {
3681 let db = self . db . lock ( ) . await . connect ( ) . unwrap ( ) ;
3782 let result = match faery. id {
3883 Some ( id) => {
@@ -45,38 +90,13 @@ impl Repository for FaeryRepository {
4590 } ,
4691 } ;
4792 match result {
48- Ok ( _) => Ok ( ( ) ) ,
49- Err ( _) => Err ( RepositoryError :: Other ) ,
50- }
51- }
52-
53- async fn create_table ( & self ) -> RepositoryResult < ( ) > {
54- let db = self . db . lock ( ) . await . connect ( ) . unwrap ( ) ;
55- let result = db. execute (
56- r#"CREATE TABLE IF NOT EXISTS faeries (
57- id INTEGER PRIMARY KEY,
58- name VARCHAR(255) NOT NULL,
59- is_admin BOOLEAN NOT NULL,
60- email VARCHAR(255) NOT NULL,
61- dross INTEGER
62- )"# , ( ) ) . await ;
63- match result {
64- Ok ( _) => Ok ( ( ) ) ,
65- Err ( _) => Err ( RepositoryError :: Other ) ,
66- }
67- }
68-
69- async fn drop_table ( & self ) -> RepositoryResult < ( ) > {
70- let db = self . db . lock ( ) . await . connect ( ) . unwrap ( ) ;
71- let result = db. execute ( "DROP TABLE IF EXISTS faeries" , ( ) ) . await ;
72- match result {
73- Ok ( _) => Ok ( ( ) ) ,
93+ Ok ( _) => Ok ( db. last_insert_rowid ( ) ) ,
7494 Err ( _) => Err ( RepositoryError :: Other ) ,
7595 }
7696 }
7797
7898 // Mark: Faery
79- async fn get ( & self , id : u32 ) -> RepositoryResult < Faery > {
99+ async fn get ( & self , id : i64 ) -> RepositoryResult < Faery > {
80100 let db = self . db . lock ( ) . await . connect ( ) . unwrap ( ) ;
81101 let mut stmt = db
82102 . prepare ( "SELECT * FROM faeries WHERE id = ?1" )
@@ -102,6 +122,7 @@ impl Repository for FaeryRepository {
102122 return Err ( RepositoryError :: Other )
103123 } ,
104124 } ;
125+
105126 let mut faeries: Vec < Faery > = Vec :: new ( ) ;
106127 while let Ok ( result_row) = res. next ( ) . await {
107128 match result_row {
@@ -114,7 +135,7 @@ impl Repository for FaeryRepository {
114135 Ok ( faeries)
115136 }
116137
117- async fn delete ( & self , id : u32 ) -> RepositoryResult < ( ) > {
138+ async fn delete ( & self , id : i64 ) -> RepositoryResult < ( ) > {
118139 let db = self . db . lock ( ) . await . connect ( ) . unwrap ( ) ;
119140 let result = db. execute ( "DELETE FROM faeries WHERE id = ?1" , [ id] ) . await ;
120141 match result {
@@ -123,20 +144,40 @@ impl Repository for FaeryRepository {
123144 }
124145 }
125146
126- fn table_name ( ) -> String {
127- "faeries" . to_string ( )
147+ async fn create_table ( & self ) -> RepositoryResult < ( ) > {
148+ let db = self . db . lock ( ) . await . connect ( ) . unwrap ( ) ;
149+ let result = db. execute (
150+ r#"CREATE TABLE IF NOT EXISTS faeries (
151+ id INTEGER PRIMARY KEY,
152+ name VARCHAR(255) NOT NULL,
153+ is_admin BOOLEAN NOT NULL,
154+ email VARCHAR(255) NOT NULL,
155+ dross INTEGER
156+ )"# , ( ) ) . await ;
157+ match result {
158+ Ok ( _) => Ok ( ( ) ) ,
159+ Err ( _) => Err ( RepositoryError :: Other ) ,
160+ }
161+ }
162+
163+ async fn drop_table ( & self ) -> RepositoryResult < ( ) > {
164+ let db = self . db . lock ( ) . await . connect ( ) . unwrap ( ) ;
165+ let result = db. execute ( "DROP TABLE IF EXISTS faeries" , ( ) ) . await ;
166+ match result {
167+ Ok ( _) => Ok ( ( ) ) ,
168+ Err ( _) => Err ( RepositoryError :: Other ) ,
169+ }
128170 }
129171}
130172
131173// Faery represents the user of the application.
132174// It has the name of the user, their email, an authentication token, and a count of their dross.
133175#[ derive( Debug , Deserialize , Serialize ) ]
134176pub struct Faery {
135- pub ( crate ) id : Option < u32 > ,
177+ pub ( crate ) id : Option < i64 > ,
136178 pub name : String ,
137179 pub email : String ,
138180 pub is_admin : bool ,
139- #[ serde( skip_serializing) ]
140181 pub auth_token : Option < String > ,
141182 pub dross : u32 ,
142183}
@@ -145,12 +186,13 @@ pub struct Faery {
145186impl Faery {
146187 // This is a method that creates a new Faery.
147188 // It takes a name and an email and returns a Faery.
148- pub fn new ( name : String , email : String , is_admin : bool , dross : u32 , id : Option < u32 > ) -> Faery {
189+ pub fn new ( name : String , email : String , is_admin : bool , dross : u32 , id : Option < i64 > ) -> Faery {
149190 Faery {
150191 id,
151192 name,
152193 email,
153194 is_admin,
195+ // TODO: Implement static method for inflating from auth_token claims
154196 auth_token : None ,
155197 dross,
156198 }
@@ -246,3 +288,16 @@ impl DrossHolder for Faery {
246288 Ok ( self . dross )
247289 }
248290}
291+
292+
293+ #[ derive( Deserialize , Debug ) ]
294+ pub struct CreateFaeryRequest {
295+ pub name : String ,
296+ pub email : String ,
297+ }
298+
299+ impl From < CreateFaeryRequest > for Faery {
300+ fn from ( req : CreateFaeryRequest ) -> Self {
301+ Faery :: new ( req. name , req. email , false , 0 , None )
302+ }
303+ }
0 commit comments