]> git.immae.eu Git - perso/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front.git/blob - api/api.go
Error flags.
[perso/Immae/Projets/Cryptomonnaies/Cryptoportfolio/Front.git] / api / api.go
1 package api
2
3 import (
4 "net/http"
5 "unicode"
6
7 "github.com/gin-gonic/gin"
8 "github.com/jloup/utils"
9 )
10
11 var CONFIG Config
12 var MAIL_CONFIG MailConfig
13
14 type MailConfig struct {
15 IsEnabled bool
16 SmtpAddress string `toml:"smtp_address"`
17 AddressFrom string `toml:"address_from"`
18 Login string `toml:"login"`
19 Password string `toml:"password"`
20 }
21
22 type Config struct {
23 Domain string `toml:"domain"`
24 JwtSecret string `toml:"jwt_secret"`
25 PasswordResetSecret string `toml:"password_reset_secret"`
26 FreeSMSUser string `toml:"free_sms_user"`
27 FreeSMSPass string `toml:"free_sms_pass"`
28 }
29
30 func SetConfig(config Config) {
31 CONFIG = config
32
33 JWT_SECRET = []byte(config.JwtSecret)
34 PASSWORD_RESET_SECRET = []byte(config.PasswordResetSecret)
35 }
36
37 func SetMailConfig(config MailConfig) {
38 MAIL_CONFIG = config
39
40 if config.Login != "" && config.AddressFrom != "" && config.Password != "" && config.SmtpAddress != "" {
41 MAIL_CONFIG.IsEnabled = true
42 ConfigureMailTemplateEngine()
43 }
44 }
45
46 type Error struct {
47 Code utils.Flag
48 UserMessage string
49 err error
50 }
51
52 func (e Error) FlagString() string {
53 return e.Code.String()
54 }
55
56 func (e Error) Flag() utils.Flag {
57 return e.Code
58 }
59
60 func (e Error) Msg() string {
61 return e.UserMessage
62 }
63
64 func (e Error) ErrorWithCode(f utils.Flag) utils.ErrorFlagged {
65 if utils.Intersect(e.Code, f) {
66 return e
67 }
68
69 return nil
70 }
71 func (e Error) Err() error {
72 if e.err != nil {
73 return e
74 }
75
76 return nil
77 }
78
79 func (e Error) Error() string {
80 if e.err != nil {
81 return e.err.Error()
82 }
83
84 return ""
85 }
86
87 func ErrorIs(err error, code utils.Flag) bool {
88 if err == nil {
89 return false
90 }
91
92 if apiError, ok := err.(*Error); !ok {
93 return false
94 } else {
95 return utils.Intersect(apiError.Code, code) && apiError.Code.String() == code.String()
96 }
97 }
98
99 func NewInternalError(err error) *Error {
100 if apiError, ok := err.(*Error); ok {
101 return apiError
102 }
103 return &Error{InternalError, "internal error", err}
104 }
105
106 func ToSnake(in string) string {
107 runes := []rune(in)
108 length := len(runes)
109
110 var out []rune
111 for i := 0; i < length; i++ {
112 if i > 0 && unicode.IsUpper(runes[i]) && ((i+1 < length && unicode.IsLower(runes[i+1])) || unicode.IsLower(runes[i-1])) {
113 out = append(out, '_')
114 }
115 out = append(out, unicode.ToLower(runes[i]))
116 }
117
118 return string(out)
119 }
120
121 type Response struct {
122 StatusCode Status `json:"-"`
123 ErrorCode utils.Flag `json:"-"`
124
125 Status string `json:"status"`
126 Code string `json:"code,omitempty"`
127 Response interface{} `json:"response,omitempty"`
128 Message string `json:"message,omitempty"`
129 }
130
131 func (r Response) populateStatus() Response {
132 r.Status = ToSnake(r.StatusCode.String())
133 r.Code = ToSnake(r.ErrorCode.String())
134
135 return r
136 }
137
138 func ErrorResponse(code utils.Flag, message string) Response {
139 return Response{
140 StatusCode: NOK,
141 ErrorCode: code,
142 Message: message,
143 }
144 }
145
146 func SuccessResponse(data interface{}) Response {
147 return Response{
148 StatusCode: OK,
149 Response: data,
150 }
151 }
152
153 func WriteJsonResponse(response Response, c *gin.Context) {
154 response = response.populateStatus()
155
156 c.JSON(StatusToHttpCode(response.StatusCode, response.ErrorCode), response)
157 }
158
159 func WriteBinary(contentType string, b []byte, c *gin.Context) {
160 c.Data(http.StatusOK, contentType, b)
161 }
162
163 type Middleware func(*gin.Context) *Error
164
165 func M(handler Middleware) gin.HandlerFunc {
166 return func(c *gin.Context) {
167 err := handler(c)
168
169 if err != nil {
170 WriteJsonResponse(ErrorResponse(err.Flag(), err.UserMessage), c)
171 c.Error(err)
172 c.Abort()
173 } else {
174 c.Next()
175 }
176 }
177 }
178
179 type Query interface {
180 ValidateParams() *Error
181 Run() (interface{}, *Error)
182 }
183
184 func RunQuery(query Query, c *gin.Context) {
185 if err := query.ValidateParams(); err != nil {
186 WriteJsonResponse(ErrorResponse(err.Flag(), err.UserMessage), c)
187 c.Error(err)
188 return
189 }
190
191 if out, err := query.Run(); err != nil {
192 WriteJsonResponse(ErrorResponse(err.Flag(), err.UserMessage), c)
193 c.Error(err)
194 } else {
195 WriteJsonResponse(SuccessResponse(out), c)
196 }
197 }