5 files changed,
72 insertions(+),
8 deletions(-)
Author:
Smirnov Oleksandr
ss2316544@gmail.com
Committed by:
GitHub
noreply@github.com
Committed at:
2025-06-07 17:47:56 +0300
Parent:
51d3b53
M
e2e/apiv1_auth_test.go
··· 286 286 e.Equal(httpResp.Code, http.StatusBadRequest) 287 287 } 288 288 289 +type apiV1AuthLogoutRequest struct { 290 + RefreshToken string `json:"refresh_token"` 291 +} 292 + 289 293 func (e *AppTestSuite) TestAuthV1_Logout() { 290 294 uid, toks := e.createAndSingIn(e.uuid()+"@test.com", "password") 291 295 292 296 sessionDB := e.getLastSessionByUserID(uid) 293 297 e.NotEmpty(sessionDB.RefreshToken) 294 298 295 - httpResp := e.httpRequest(http.MethodPost, "/api/v1/auth/logout", nil, toks.AccessToken) 299 + httpResp := e.httpRequest( 300 + http.MethodPost, 301 + "/api/v1/auth/logout", 302 + e.jsonify(apiV1AuthLogoutRequest{ 303 + RefreshToken: toks.RefreshToken, 304 + }), 305 + toks.AccessToken, 306 + ) 296 307 e.Equal(httpResp.Code, http.StatusNoContent) 297 308 298 309 sessionDB = e.getLastSessionByUserID(uid) 299 310 e.Empty(sessionDB.RefreshToken) 311 +} 312 + 313 +func (e *AppTestSuite) TestAuthV1_LogoutAll() { 314 + uid, toks := e.createAndSingIn(e.uuid()+"@test.com", "password") 315 + 316 + var res int 317 + query := "select count(*) from sessions where user_id = $1" 318 + 319 + err := e.postgresDB.QueryRow(e.ctx, query, uid).Scan(&res) 320 + e.require.NoError(err) 321 + e.NotZero(res) 322 + 323 + httpResp := e.httpRequest(http.MethodPost, "/api/v1/auth/logout/all", nil, toks.AccessToken) 324 + e.Equal(httpResp.Code, http.StatusNoContent) 325 + 326 + err = e.postgresDB.QueryRow(e.ctx, query, uid).Scan(&res) 327 + e.require.NoError(err) 328 + e.Zero(res) 300 329 } 301 330 302 331 type apiv1AuthChangePasswordRequest struct {
M
internal/service/usersrv/usersrv.go
··· 24 24 SignUp(ctx context.Context, inp dtos.SignUp) (uuid.UUID, error) 25 25 SignIn(ctx context.Context, inp dtos.SignIn) (dtos.Tokens, error) 26 26 RefreshTokens(ctx context.Context, refreshToken string) (dtos.Tokens, error) 27 - Logout(ctx context.Context, userID uuid.UUID) error 27 + Logout(ctx context.Context, userID uuid.UUID, refreshToken string) error 28 + LogoutAll(ctx context.Context, userID uuid.UUID) error 28 29 29 30 ChangePassword(ctx context.Context, userID uuid.UUID, inp dtos.ChangeUserPassword) error 30 31 RequestPasswordReset(ctx context.Context, inp dtos.RequestResetPassword) error ··· 158 159 return tokens, err 159 160 } 160 161 161 -func (u *UserSrv) Logout(ctx context.Context, userID uuid.UUID) error { 162 - return u.sessionstore.Delete(ctx, userID) 162 +func (u *UserSrv) Logout(ctx context.Context, userID uuid.UUID, refreshToken string) error { 163 + return u.sessionstore.Delete(ctx, userID, refreshToken) 164 +} 165 + 166 +func (u *UserSrv) LogoutAll(ctx context.Context, userID uuid.UUID) error { 167 + return u.sessionstore.DeleteAllByUserID(ctx, userID) 163 168 } 164 169 165 170 func (u *UserSrv) RefreshTokens(ctx context.Context, rtoken string) (dtos.Tokens, error) {
M
internal/store/psql/sessionrepo/sessionrepo.go
··· 16 16 Set(ctx context.Context, usedID uuid.UUID, refreshToken string, expiresAt time.Time) error 17 17 GetUserIDByRefreshToken(ctx context.Context, refreshToken string) (uuid.UUID, error) 18 18 Update(ctx context.Context, userID uuid.UUID, refreshToken string, newRefreshToken string) error 19 - Delete(ctx context.Context, userID uuid.UUID) error 19 + Delete(ctx context.Context, userID uuid.UUID, refreshToken string) error 20 + DeleteAllByUserID(ctx context.Context, userID uuid.UUID) error 20 21 } 21 22 22 23 var _ SessionStorer = (*SessionRepo)(nil) ··· 95 96 return userID, err 96 97 } 97 98 98 -func (s *SessionRepo) Delete(ctx context.Context, userID uuid.UUID) error { 99 +func (s *SessionRepo) Delete(ctx context.Context, userID uuid.UUID, refreshToken string) error { 99 100 query := `--sql 100 101 DELETE FROM sessions 101 102 WHERE user_id = $1 102 -` 103 + AND refresh_token = $2` 104 + 105 + _, err := s.db.Exec(ctx, query, userID, refreshToken) 106 + return err 107 +} 108 + 109 +func (s *SessionRepo) DeleteAllByUserID(ctx context.Context, userID uuid.UUID) error { 110 + query := `--sql 111 +delete from sessions 112 +where user_id = $1` 103 113 104 114 _, err := s.db.Exec(ctx, query, userID) 105 115 return err
M
internal/transport/http/apiv1/apiv1.go
··· 49 49 authorized := auth.Group("/", a.authorizedMiddleware) 50 50 { 51 51 authorized.POST("/logout", a.logOutHandler) 52 + authorized.POST("/logout/all", a.logOutAllHandler) 52 53 authorized.POST("/change-password", a.changePasswordHandler) 53 54 } 54 55 }
M
internal/transport/http/apiv1/auth.go
··· 163 163 c.Status(http.StatusOK) 164 164 } 165 165 166 +type logoutRequest struct { 167 + RefreshToken string `json:"refresh_token"` 168 +} 169 + 166 170 func (a *APIV1) logOutHandler(c *gin.Context) { 167 - if err := a.usersrv.Logout(c.Request.Context(), a.getUserID(c)); err != nil { 171 + var req logoutRequest 172 + if err := c.ShouldBindJSON(&req); err != nil { 173 + newError(c, http.StatusBadRequest, "invalid request") 174 + return 175 + } 176 + 177 + if err := a.usersrv.Logout(c.Request.Context(), a.getUserID(c), req.RefreshToken); err != nil { 178 + errorResponse(c, err) 179 + return 180 + } 181 + 182 + c.Status(http.StatusNoContent) 183 +} 184 + 185 +func (a *APIV1) logOutAllHandler(c *gin.Context) { 186 + if err := a.usersrv.LogoutAll(c.Request.Context(), a.getUserID(c)); err != nil { 168 187 errorResponse(c, err) 169 188 return 170 189 }