@@ -3,9 +3,7 @@ package auth
33import (
44 "context"
55 "crypto/rand"
6- "crypto/sha256"
76 "crypto/subtle"
8- "encoding/hex"
97 "fmt"
108 "time"
119
@@ -41,7 +39,7 @@ type Service struct {
4139
4240 users * repository
4341 codesCache * cache.Cache [string ]
44- usersCache * cache. Cache [models. User ]
42+ usersCache * usersCache
4543
4644 devicesSvc * devices.Service
4745 onlineSvc online.Service
@@ -52,7 +50,8 @@ type Service struct {
5250}
5351
5452func New (params Params ) * Service {
55- idgen , _ := nanoid .Standard (21 )
53+ const idLen = 21
54+ idgen , _ := nanoid .Standard (idLen )
5655
5756 return & Service {
5857 config : params .Config ,
@@ -62,24 +61,26 @@ func New(params Params) *Service {
6261 logger : params .Logger ,
6362 idgen : idgen ,
6463
65- codesCache : cache.New [string ](cache.Config {}),
66- usersCache : cache. New [models. User ](cache. Config { TTL : 1 * time . Hour } ),
64+ codesCache : cache.New [string ](cache.Config {TTL : codeTTL }),
65+ usersCache : newUsersCache ( ),
6766 }
6867}
6968
70- // GenerateUserCode generates a unique one-time user authorization code
71- func (s * Service ) GenerateUserCode (userID string ) (AuthCode , error ) {
69+ // GenerateUserCode generates a unique one-time user authorization code.
70+ func (s * Service ) GenerateUserCode (userID string ) (OneTimeCode , error ) {
7271 var code string
7372 var err error
7473
75- b := make ([]byte , 3 )
74+ const bytesLen = 3
75+ const maxCode = 1000000
76+ b := make ([]byte , bytesLen )
7677 validUntil := time .Now ().Add (codeTTL )
7778 for range 3 {
7879 if _ , err = rand .Read (b ); err != nil {
7980 continue
8081 }
81- num := (int (b [0 ]) << 16 ) | (int (b [1 ]) << 8 ) | int (b [2 ])
82- code = fmt .Sprintf ("%06d" , num % 1000000 )
82+ num := (int (b [0 ]) << 16 ) | (int (b [1 ]) << 8 ) | int (b [2 ]) //nolint:mnd //bitshift
83+ code = fmt .Sprintf ("%06d" , num % maxCode )
8384
8485 if err = s .codesCache .SetOrFail (code , userID , cache .WithValidUntil (validUntil )); err != nil {
8586 continue
@@ -89,36 +90,34 @@ func (s *Service) GenerateUserCode(userID string) (AuthCode, error) {
8990 }
9091
9192 if err != nil {
92- return AuthCode {}, fmt .Errorf ("can't generate code: %w" , err )
93+ return OneTimeCode {}, fmt .Errorf ("failed to generate code: %w" , err )
9394 }
9495
95- return AuthCode {Code : code , ValidUntil : validUntil }, nil
96+ return OneTimeCode {Code : code , ValidUntil : validUntil }, nil
9697}
9798
98- func (s * Service ) RegisterUser (login , password string ) (models.User , error ) {
99- user := models.User {
100- ID : login ,
101- }
102-
103- var err error
104- if user .PasswordHash , err = crypto .MakeBCryptHash (password ); err != nil {
105- return user , fmt .Errorf ("can't hash password: %w" , err )
99+ func (s * Service ) RegisterUser (login , password string ) (* models.User , error ) {
100+ passwordHash , err := crypto .MakeBCryptHash (password )
101+ if err != nil {
102+ return nil , fmt .Errorf ("failed to hash password: %w" , err )
106103 }
107104
108- if err = s .users .Insert (& user ); err != nil {
109- return user , fmt .Errorf ("can't create user" )
105+ user := models .NewUser (login , passwordHash )
106+ if err = s .users .Insert (user ); err != nil {
107+ return user , fmt .Errorf ("failed to create user: %w" , err )
110108 }
111109
112110 return user , nil
113111}
114112
115- func (s * Service ) RegisterDevice (user models.User , name , pushToken * string ) (models.Device , error ) {
116- device := models.Device {
117- Name : name ,
118- PushToken : pushToken ,
113+ func (s * Service ) RegisterDevice (user * models.User , name , pushToken * string ) (* models.Device , error ) {
114+ device := models .NewDevice (name , pushToken )
115+
116+ if err := s .devicesSvc .Insert (user .ID , device ); err != nil {
117+ return device , fmt .Errorf ("failed to create device: %w" , err )
119118 }
120119
121- return device , s . devicesSvc . Insert ( user . ID , & device )
120+ return device , nil
122121}
123122
124123func (s * Service ) IsPublic () bool {
@@ -134,17 +133,18 @@ func (s *Service) AuthorizeRegistration(token string) error {
134133 return nil
135134 }
136135
137- return fmt . Errorf ( "invalid token" )
136+ return ErrAuthorizationFailed
138137}
139138
140139func (s * Service ) AuthorizeDevice (token string ) (models.Device , error ) {
141140 device , err := s .devicesSvc .GetByToken (token )
142141 if err != nil {
143- return device , err
142+ return device , fmt . Errorf ( "%w: %w" , ErrAuthorizationFailed , err )
144143 }
145144
146145 go func (id string ) {
147- ctx , cancel := context .WithTimeout (context .Background (), 5 * time .Second )
146+ const timeout = 5 * time .Second
147+ ctx , cancel := context .WithTimeout (context .Background (), timeout )
148148 defer cancel ()
149149 s .onlineSvc .SetOnline (ctx , id )
150150 }(device .ID )
@@ -154,41 +154,37 @@ func (s *Service) AuthorizeDevice(token string) (models.Device, error) {
154154 return device , nil
155155}
156156
157- func (s * Service ) AuthorizeUser (username , password string ) (models.User , error ) {
158- hash := sha256 .Sum256 ([]byte (username + password ))
159- cacheKey := hex .EncodeToString (hash [:])
160-
161- user , err := s .usersCache .Get (cacheKey )
162- if err == nil {
163- return user , nil
157+ func (s * Service ) AuthorizeUser (username , password string ) (* models.User , error ) {
158+ if user , err := s .usersCache .Get (username , password ); err == nil {
159+ return & user , nil
164160 }
165161
166- user , err = s .users .GetByLogin (username )
162+ user , err : = s .users .GetByLogin (username )
167163 if err != nil {
168164 return user , err
169165 }
170166
171- if err := crypto .CompareBCryptHash (user .PasswordHash , password ); err != nil {
172- return models. User {}, err
167+ if cmpErr := crypto .CompareBCryptHash (user .PasswordHash , password ); cmpErr != nil {
168+ return nil , fmt . Errorf ( "password is incorrect: %w" , cmpErr )
173169 }
174170
175- if err := s .usersCache .Set (cacheKey , user ); err != nil {
176- s .logger .Error ("can't cache user" , zap .Error (err ))
171+ if setErr := s .usersCache .Set (username , password , * user ); setErr != nil {
172+ s .logger .Error ("failed to cache user" , zap .Error (setErr ))
177173 }
178174
179175 return user , nil
180176}
181177
182178// AuthorizeUserByCode authorizes a user by one-time code.
183- func (s * Service ) AuthorizeUserByCode (code string ) (models.User , error ) {
179+ func (s * Service ) AuthorizeUserByCode (code string ) (* models.User , error ) {
184180 userID , err := s .codesCache .GetAndDelete (code )
185181 if err != nil {
186- return models. User {} , err
182+ return nil , fmt . Errorf ( "failed to get user by code: %w" , err )
187183 }
188184
189185 user , err := s .users .GetByID (userID )
190186 if err != nil {
191- return models. User {} , err
187+ return nil , err
192188 }
193189
194190 return user , nil
@@ -200,24 +196,22 @@ func (s *Service) ChangePassword(userID string, currentPassword string, newPassw
200196 return fmt .Errorf ("failed to get user: %w" , err )
201197 }
202198
203- if err := crypto .CompareBCryptHash (user .PasswordHash , currentPassword ); err != nil {
204- return fmt .Errorf ("current password is incorrect: %w" , err )
199+ if hashErr := crypto .CompareBCryptHash (user .PasswordHash , currentPassword ); hashErr != nil {
200+ return fmt .Errorf ("current password is incorrect: %w" , hashErr )
205201 }
206202
207203 newHash , err := crypto .MakeBCryptHash (newPassword )
208204 if err != nil {
209205 return fmt .Errorf ("failed to hash new password: %w" , err )
210206 }
211207
212- if err := s .users .UpdatePassword (userID , newHash ); err != nil {
213- return fmt .Errorf ("failed to update password: %w" , err )
208+ if updErr := s .users .UpdatePassword (userID , newHash ); updErr != nil {
209+ return fmt .Errorf ("failed to update password: %w" , updErr )
214210 }
215211
216212 // Invalidate cache
217- hash := sha256 .Sum256 ([]byte (userID + currentPassword ))
218- cacheKey := hex .EncodeToString (hash [:])
219- if err := s .usersCache .Delete (cacheKey ); err != nil {
220- s .logger .Error ("can't invalidate user cache" , zap .Error (err ))
213+ if delErr := s .usersCache .Delete (userID , currentPassword ); delErr != nil {
214+ s .logger .Error ("failed to invalidate user cache" , zap .Error (delErr ))
221215 }
222216
223217 return nil
0 commit comments