11use actix_web:: { dev:: ConnectionInfo , post, web, Responder } ;
22use serde:: Deserialize ;
3- use sqlx:: { types:: ipnetwork:: IpNetwork , Acquire } ;
3+ use sqlx:: { types:: ipnetwork:: IpNetwork , Acquire , PgConnection } ;
44use uuid:: Uuid ;
55
66use crate :: {
@@ -17,6 +17,26 @@ struct PollParams {
1717 uuid : String ,
1818}
1919
20+ #[ derive( Deserialize ) ]
21+ struct TokenLoginParams {
22+ token : String ,
23+ }
24+
25+ async fn developer_from_token (
26+ pool : & mut PgConnection ,
27+ user : serde_json:: Value
28+ ) -> Result < Uuid , Option < ApiError > > {
29+ let id = user. get ( "id" ) . ok_or ( None ) ?. as_i64 ( ) . unwrap ( ) ;
30+ let username = user. get ( "login" ) . ok_or ( None ) ?;
31+
32+ let dev_id = match Developer :: get_by_github_id ( id, pool) . await ? {
33+ Some ( x) => x. id ,
34+ None => Developer :: create ( id, username. to_string ( ) , pool) . await ?
35+ } ;
36+
37+ create_token_for_developer ( dev_id, pool) . await . map_err ( Some )
38+ }
39+
2040#[ post( "v1/login/github" ) ]
2141pub async fn start_github_login (
2242 data : web:: Data < AppData > ,
@@ -138,17 +158,6 @@ pub async fn poll_github_login(
138158 log:: error!( "{}" , e) ;
139159 return Err ( ApiError :: InternalError ) ;
140160 } ;
141- let user = match client. get_user ( token) . await {
142- Err ( e) => {
143- transaction
144- . rollback ( )
145- . await
146- . or ( Err ( ApiError :: TransactionError ) ) ?;
147- log:: error!( "{}" , e) ;
148- return Err ( ApiError :: InternalError ) ;
149- }
150- Ok ( u) => u,
151- } ;
152161
153162 // Create a new transaction after this point, because we need to commit the removal of the login attempt
154163
@@ -157,71 +166,62 @@ pub async fn poll_github_login(
157166 . await
158167 . or ( Err ( ApiError :: TransactionError ) ) ?;
159168
169+ let user = client. get_user ( & token) . await . map_err ( |_| ApiError :: InternalError ) ?;
160170 let mut transaction = pool. begin ( ) . await . or ( Err ( ApiError :: TransactionError ) ) ?;
161171
162- let id = match user. get ( "id" ) {
163- None => return Err ( ApiError :: InternalError ) ,
164- Some ( id) => id. as_i64 ( ) . unwrap ( ) ,
165- } ;
166- if let Some ( x) = Developer :: get_by_github_id ( id, & mut transaction) . await ? {
167- let token = match create_token_for_developer ( x. id , & mut transaction) . await {
168- Err ( _) => {
169- transaction
170- . rollback ( )
171- . await
172- . or ( Err ( ApiError :: TransactionError ) ) ?;
173- return Err ( ApiError :: InternalError ) ;
174- }
175- Ok ( t) => t,
176- } ;
177- transaction
178- . commit ( )
179- . await
180- . or ( Err ( ApiError :: TransactionError ) ) ?;
181- return Ok ( web:: Json ( ApiResponse {
182- error : "" . to_string ( ) ,
183- payload : token. to_string ( ) ,
184- } ) ) ;
185- }
186- let username = match user. get ( "login" ) {
187- None => {
188- transaction
189- . rollback ( )
190- . await
191- . or ( Err ( ApiError :: TransactionError ) ) ?;
192- return Err ( ApiError :: InternalError ) ;
193- }
194- Some ( user) => user. to_string ( ) ,
195- } ;
196- let id = match Developer :: create ( id, username, & mut transaction) . await {
172+ let token = match developer_from_token ( & mut transaction, user) . await {
173+ Ok ( t) => t,
197174 Err ( e) => {
198- transaction
199- . rollback ( )
200- . await
201- . or ( Err ( ApiError :: TransactionError ) ) ?;
202- log:: error!( "{}" , e) ;
203- return Err ( ApiError :: InternalError ) ;
175+ if let Some ( e) = e {
176+ log:: error!( "{}" , e) ;
177+ }
178+
179+ transaction. rollback ( ) . await . map_or_else (
180+ |_| Err ( ApiError :: TransactionError ) ,
181+ |_| Err ( ApiError :: InternalError )
182+ ) ?
204183 }
205- Ok ( i) => i,
206184 } ;
207- let token = match create_token_for_developer ( id, & mut transaction) . await {
185+
186+ Ok ( web:: Json ( ApiResponse {
187+ error : "" . to_string ( ) ,
188+ payload : token. to_string ( ) ,
189+ } ) )
190+ }
191+
192+ #[ post( "v1/login/github/token" ) ]
193+ pub async fn github_token_login (
194+ json : web:: Json < TokenLoginParams > ,
195+ data : web:: Data < AppData > ,
196+ ) -> Result < impl Responder , ApiError > {
197+ let client = github:: GithubClient :: new (
198+ data. github_client_id . to_string ( ) ,
199+ data. github_client_secret . to_string ( ) ,
200+ ) ;
201+
202+ let user = client. get_user ( & json. token ) . await
203+ . map_err ( |_| ApiError :: BadRequest ( format ! ( "Invalid access token: {}" , json. token) ) ) ?;
204+
205+ let mut pool = data. db . acquire ( ) . await . or ( Err ( ApiError :: DbAcquireError ) ) ?;
206+ let mut transaction = pool. begin ( ) . await . or ( Err ( ApiError :: TransactionError ) ) ?;
207+
208+ let token = match developer_from_token ( & mut transaction, user) . await {
209+ Ok ( t) => t,
210+
208211 Err ( e) => {
209- transaction
210- . rollback ( )
211- . await
212- . or ( Err ( ApiError :: TransactionError ) ) ?;
213- log:: error!( "{}" , e) ;
214- return Err ( ApiError :: InternalError ) ;
212+ if let Some ( e) = e {
213+ log:: error!( "{}" , e) ;
214+ }
215+
216+ transaction. rollback ( ) . await . map_or_else (
217+ |_| Err ( ApiError :: TransactionError ) ,
218+ |_| Err ( ApiError :: InternalError )
219+ ) ?
215220 }
216- Ok ( t) => t,
217221 } ;
218- transaction
219- . commit ( )
220- . await
221- . or ( Err ( ApiError :: TransactionError ) ) ?;
222222
223223 Ok ( web:: Json ( ApiResponse {
224224 error : "" . to_string ( ) ,
225- payload : token. to_string ( ) ,
225+ payload : token. to_string ( )
226226 } ) )
227227}
0 commit comments