1
1
use actix_web:: { dev:: ConnectionInfo , post, web, Responder } ;
2
2
use serde:: Deserialize ;
3
- use sqlx:: { types:: ipnetwork:: IpNetwork , Acquire } ;
3
+ use sqlx:: { types:: ipnetwork:: IpNetwork , Acquire , PgConnection } ;
4
4
use uuid:: Uuid ;
5
5
6
6
use crate :: {
@@ -17,6 +17,26 @@ struct PollParams {
17
17
uuid : String ,
18
18
}
19
19
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
+
20
40
#[ post( "v1/login/github" ) ]
21
41
pub async fn start_github_login (
22
42
data : web:: Data < AppData > ,
@@ -138,17 +158,6 @@ pub async fn poll_github_login(
138
158
log:: error!( "{}" , e) ;
139
159
return Err ( ApiError :: InternalError ) ;
140
160
} ;
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
- } ;
152
161
153
162
// Create a new transaction after this point, because we need to commit the removal of the login attempt
154
163
@@ -157,71 +166,62 @@ pub async fn poll_github_login(
157
166
. await
158
167
. or ( Err ( ApiError :: TransactionError ) ) ?;
159
168
169
+ let user = client. get_user ( & token) . await . map_err ( |_| ApiError :: InternalError ) ?;
160
170
let mut transaction = pool. begin ( ) . await . or ( Err ( ApiError :: TransactionError ) ) ?;
161
171
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,
197
174
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
+ ) ?
204
183
}
205
- Ok ( i) => i,
206
184
} ;
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
+
208
211
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
+ ) ?
215
220
}
216
- Ok ( t) => t,
217
221
} ;
218
- transaction
219
- . commit ( )
220
- . await
221
- . or ( Err ( ApiError :: TransactionError ) ) ?;
222
222
223
223
Ok ( web:: Json ( ApiResponse {
224
224
error : "" . to_string ( ) ,
225
- payload : token. to_string ( ) ,
225
+ payload : token. to_string ( )
226
226
} ) )
227
227
}
0 commit comments