-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtoken.go
More file actions
150 lines (135 loc) · 4.42 KB
/
Copy pathtoken.go
File metadata and controls
150 lines (135 loc) · 4.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
Срок действия access токена составляет 15 минут.
Ограничим 12 минут
TODO нужно ли запустить метод обновления токена в отдельном потоке с таймером?
*/
package finam
import (
"context"
"fmt"
"net/http"
"time"
)
const jwtTokenTtl = 12 // Время жизни токена JWT в минутах
// Запрос авторизации
type AuthRequest struct {
// API токен (secret key)
Secret string `json:"secret,omitempty"`
}
// Информация об авторизации
type AuthResponse struct {
// Полученный JWT-токен
Token string `json:"token,omitempty"`
}
// Запрос информации о токене
type TokenDetailsRequest struct {
// JWT-токен
Token string `json:"token,omitempty"`
}
// Информация о доступе к рыночным данным
type MDPermission struct {
// Уровень котировок
QuoteLevel string `json:"quote_level,omitempty"`
// Задержка в минутах
DelayMinutes int32 `json:"delay_minutes,omitempty"`
}
// Информация о токене
type TokenDetailsResponse struct {
// Дата и время создания
CreatedAt string `json:"created_at,omitempty"`
// Дата и время экспирации
ExpiresAt string `json:"expires_at,omitempty"`
// Информация о доступе к рыночным данным
//MdPermissions []*MDPermission `json:"mdPermissions,omitempty"`
// Идентификаторы аккаунтов
AccountIds []string `json:"account_ids,omitempty"`
}
// WithAuthToken добавим в запрос токен авторизации
//
// При необходимости, предварительно получим токен (GetJWT)
// и запишем его в параметры клиента (c.accessToken)
func (c *Client) WithAuthToken(req *Request) error {
// проверим наличие токена
err := c.UpdateJWT()
if err != nil {
return err
}
// запишем его в запрос
if req != nil {
req.SetHeader("Authorization", c.accessToken)
}
return nil
}
// UpdateJWT
// если токен пустой или вышло его время => получим JWT и запишем его в параметры клиента
func (c *Client) UpdateJWT() error {
if c.refreshToken == "" {
c.accessToken = ""
return fmt.Errorf("UpdateJWT: token пустой")
}
// если токен пустой или вышло его время
if c.accessToken == "" || c.ttlJWT.Before(time.Now()) {
log.Debug("UpdateJWT. токен пустой или вышло его время = получим новый токен")
// получим новый токен
token, err := c.GetJWT()
if err != nil {
return err
}
// запишем время окончания токена
c.ttlJWT = time.Now().Add(jwtTokenTtl * time.Minute)
c.accessToken = token
}
log.Debug("UpdateJWT. токен живой")
return nil
}
// GetJWT получим accessToken
//
// v1/sessions
func (c *Client) GetJWT() (string, error) {
//const op = "GetJWT"
var err error
var result AuthResponse
if c.refreshToken == "" {
c.accessToken = ""
return c.accessToken, err
}
req := NewRequest(http.MethodPost, apiURL).URLJoin("v1/sessions")
reqAuth := &AuthRequest{
Secret: c.refreshToken,
}
req.SetJSONBody(reqAuth) // запишем в тело запроса структуру
req.authorization = false
log.Debug("GetJWT start refresh")
t := time.Now()
err = c.GetJson(req, &result)
if err != nil {
return "", err
}
log.Debug("GetJWT end refresh", "duration", time.Since(t))
return result.Token, nil
}
// GetTokenDetails Получение информации о токене сессии
//
// v1/sessions/details/
func (c *Client) GetTokenDetails(ctx context.Context) (TokenDetailsResponse, error) {
var err error
var result TokenDetailsResponse
req := NewRequest(http.MethodPost, apiURL).URLJoin("v1/sessions/details/")
reqToken := &TokenDetailsRequest{
Token: c.accessToken,
}
req.SetJSONBody(reqToken)
resp, err := c.SendRequest(req)
if err != nil {
return result, err
}
err = resp.DecodeJSON(&result)
if err != nil {
return result, err
}
return result, nil
}
// WithAuthToken добавим в запрос токен авторизации
// func (c *Client) WithAuthToken(req *Request) error {
// return c.SetJWT(req)
// }