· 7 years ago · May 30, 2018, 02:06 PM
1import axios from 'axios'
2import JWTDecode from 'jwt-decode'
3
4import { jsonToFormData } from '../utils'
5import config from '../config'
6import localStorage from '../lib/LocalStorage'
7import ServiceDebugger from '../lib/ServiceDebugger'
8import { Notification } from './Notifications'
9import { Paciente } from '.';
10
11export class OAuthTokenService {
12
13 constructor() {
14
15 this._auth_axios = axios.create({
16 url: '/oauth/token',
17 baseURL: config.api.hostname,
18 headers: {
19 Authorization: 'Basic ZmFtaWx5ZG9jX21vYmlsZTojc2VjdHJldEZAbWlseURvY1BAY2kmbnQmc0BwcGxpY2F0aW9uJSY=',
20 },
21 })
22
23 this.debugger = new ServiceDebugger(this, this._auth_axios, __DEV__)
24 }
25
26 __debug(caller) {
27 if (name) this.debugger._caller = caller
28 }
29
30 async checkToken(token){
31 console.debug('Verificando token...')
32 token = token || await this.getAccessToken()
33
34 if (this.isTokenExpired(token)) {
35 console.debug('O token expirou!')
36 token = await this.getNewAccessToken()
37 return this.checkToken(token.access_token)
38 }
39
40 console.debug('O token está válido!')
41 return token
42 }
43
44 async jwtPayload(){
45 const token = await this.getAccessToken()
46 return token ? JWTDecode(token) : null
47 }
48
49 async processTokens(res) {
50 console.debug('Extraindo tokens...')
51
52 const { access_token, refresh_token } = res.data
53
54 const token = {
55 access_token,
56 refresh_token,
57 }
58
59 await this.setToken(token)
60
61 const payload = JWTDecode(access_token)
62
63 return { token, payload }
64 }
65
66 login (username, password) {
67 console.debug('Fazendo login...')
68
69 return this._auth_axios({
70 method: 'POST',
71 url: '/oauth/token',
72 data: jsonToFormData({
73 grant_type: 'password',
74 username,
75 password,
76 })
77 })
78 .then(res =>
79 Notification.getDeviceToken().then(async token => {
80 const p = await this.processTokens(res)
81 await Paciente.setFCMToken(p.payload.pessoa_id, token)
82
83 return p
84 })
85 )
86 }
87
88 async getNewAccessToken(access_token) {
89 console.debug('Obtendo um novo token de acesso...')
90
91 const { refresh_token } = await this.getToken()
92
93 return this._auth_axios({
94 method: 'POST',
95 url: '/oauth/token',
96 data: jsonToFormData({
97 grant_type: 'refresh_token',
98 refresh_token,
99 })
100 })
101 .then(res => this.processTokens(res))
102 .catch(async e => {
103 await this.deleteToken()
104 return Promise.reject(e)
105 })
106 }
107
108 getToken() {
109 return localStorage.get('token').then(r => r || ({}))
110 }
111
112 setToken(token) {
113 console.debug('Armazenando tokens...')
114 return localStorage.set('token', token)
115 }
116
117 async deleteToken(){
118 console.debug('Apagando tokens da memória...')
119 await localStorage.delete('token')
120 return true
121 }
122
123 async getAccessToken() {
124 const { access_token } = await this.getToken()
125 return access_token
126 }
127
128 async getRefreshToken() {
129 const token = await this.getToken()
130 return token && token.refresh_token
131 }
132
133 async isLogged() {
134 console.debug('Verificando se há uma sessão ativa...')
135 const token = await this.getToken()
136 if (!token.access_token) return false
137 const payload = JWTDecode(token.access_token)
138 return { token, payload }
139 }
140
141 async isAccessTokenValid() {
142 console.debug('Verificando se o token de acesso é válido...')
143 const token = await this.getAccessToken()
144 return token && this.isTokenExpired(token)
145 }
146
147 async tokenExpirationTime() {
148 console.debug('Verificando data de expiração do token de acesso...')
149
150 const token = await this.getAccessToken()
151
152 if (!token) return 0
153 const decodedToken = JWTDecode(token)
154
155 return decodedToken.exp - Date.now() / 1000
156 }
157
158 isTokenExpired(jwtToken) {
159 console.debug('Verificando se o token de acesso expirou...')
160 const token = JWTDecode(jwtToken)
161 return token.exp < Date.now() / 1000
162 }
163
164 async hasRole(permission) {
165 console.debug('Verificando permissões do token de acesso...')
166
167 const payload = await this.jwtPayload()
168 return payload && payload.authorities.includes(permission)
169 }
170
171 logout() {
172 console.debug('Encerrando sessão...')
173 return this.deleteToken()
174 }
175
176 async checkAuth () {
177 const token = await this.getAccessToken()
178
179 if (!token) return Promise.reject()
180
181 return this.checkToken(token)
182 }
183}
184
185export const Auth = new OAuthTokenService()