1+ import axios from 'axios'
2+ import quidException from "./exceptions"
3+
4+ export default class QuidRequests {
5+ refreshToken = null ;
6+ #accessToken = null ;
7+
8+ constructor ( { namespace, axiosConfig, timeouts = {
9+ accessToken : "20m" ,
10+ refreshToken : "24h"
11+ } ,
12+ accessTokenUri = null ,
13+ verbose = false } ) {
14+ if ( typeof namespace !== 'string' ) {
15+ throw quidException ( { error : 'Parameter namespace has to be set' } ) ;
16+ }
17+ if ( typeof axiosConfig !== 'object' ) {
18+ throw quidException ( { error : 'Parameter axiosConfig has to be set' } ) ;
19+ }
20+ this . namespace = namespace
21+ this . axiosConfig = axiosConfig ;
22+ this . axios = axios . create ( this . axiosConfig ) ;
23+ this . timeouts = timeouts
24+ this . verbose = verbose
25+ this . accessTokenUri = accessTokenUri
26+ }
27+
28+ async get ( uri ) {
29+ return await this . _requestWithRetry ( uri , "get" )
30+ }
31+
32+ async post ( uri , payload ) {
33+ return await this . _requestWithRetry ( uri , "post" , payload )
34+ }
35+
36+ async adminLogin ( username , password ) {
37+ let uri = "/admin_login" ;
38+ let payload = {
39+ namespace : "quid" ,
40+ username : username ,
41+ password : password ,
42+ }
43+ try {
44+ let response = await axios . post ( uri , payload , this . axiosConfig ) ;
45+ this . refreshToken = response . data . token ;
46+ } catch ( e ) {
47+ if ( e . response ) {
48+ if ( e . response . status === 401 ) {
49+ throw quidException ( { error : null , unauthorized : true } ) ;
50+ }
51+ }
52+ throw quidException ( { error : e } ) ;
53+ }
54+ }
55+
56+ async _requestWithRetry ( uri , method , payload , retry = 0 ) {
57+ if ( this . verbose ) {
58+ console . log ( method + " request to " + uri )
59+ }
60+ await this . checkTokens ( ) ;
61+ try {
62+ if ( method === "get" ) {
63+ return await this . axios . get ( uri , this . axiosConfig ) ;
64+ } else {
65+ return await axios . post ( uri , payload , this . axiosConfig ) ;
66+ }
67+ } catch ( e ) {
68+ if ( e . response ) {
69+ if ( e . response . status === 401 ) {
70+ if ( this . verbose ) {
71+ console . log ( "Access token has expired" )
72+ }
73+ this . #accessToken = null ;
74+ await this . checkTokens ( ) ;
75+ if ( retry > 2 ) {
76+ throw quidException ( { error : "too many retries" } ) ;
77+ }
78+ retry ++
79+ if ( this . verbose ) {
80+ console . log ( "Retrying" , method , "request to" , uri , ", retry" , retry )
81+ }
82+ return await this . _requestWithRetry ( uri , method , payload , retry )
83+ } else {
84+ throw quidException ( { error : e } ) ;
85+ }
86+ } else {
87+ throw quidException ( { error : e } ) ;
88+ }
89+ }
90+ }
91+
92+ async checkTokens ( ) {
93+ if ( this . refreshToken === null ) {
94+ if ( this . verbose ) {
95+ console . log ( "Tokens check: no refresh token" )
96+ }
97+ throw quidException ( { error : 'No refresh token found' , hasToLogin : true } ) ;
98+ }
99+ if ( this . #accessToken === null ) {
100+ if ( this . verbose ) {
101+ console . log ( "Tokens check: no access token" )
102+ }
103+ let { token, error, statusCode } = await this . _getAccessToken ( ) ;
104+ if ( error !== null ) {
105+ if ( statusCode === 401 ) {
106+ if ( this . verbose ) {
107+ console . log ( "The refresh token has expired" )
108+ }
109+ throw quidException ( { error : 'The refresh token has expired' , hasToLogin : true } ) ;
110+ } else {
111+ throw quidException ( { error : error } ) ;
112+ }
113+ }
114+ this . #accessToken = token ;
115+ this . axiosConfig . headers . Authorization = "Bearer " + this . #accessToken
116+ this . axios = axios . create ( this . axiosConfig ) ;
117+ }
118+ }
119+
120+ async _getAccessToken ( ) {
121+ try {
122+ let payload = {
123+ namespace : this . namespace ,
124+ refresh_token : this . refreshToken ,
125+ }
126+ let url = "/token/access/" + this . timeouts . accessToken
127+ if ( this . accessTokenUri !== null ) {
128+ url = this . accessTokenUri
129+ }
130+ if ( this . verbose ) {
131+ console . log ( "Getting an access token from" , url , payload )
132+ }
133+ let response = await axios . post ( url , payload , this . axiosConfig ) ;
134+ return { token : response . data . token , error : null , statusCode : response . status } ;
135+ } catch ( e ) {
136+ if ( e . response !== undefined ) {
137+ return { token : null , error : e . response . data . error , statusCode : e . response . status } ;
138+ }
139+ return { token : null , error : e , statusCode : null }
140+ }
141+ }
142+ }
0 commit comments