all repos

onasty @ 218bb4ee98d3f43980d398736a213688240b9336

a one-time notes service
13 files changed, 49 insertions(+), 100 deletions(-)
refactor: remove `username` (#112)

* chore: migrations

* refactor: remove all mentions of username

* e2e: refactor username out

* test(models): fix test

* fix(usersrv): validate user's password correctly
Author: Smirnov Oleksandr ss2316544@gmail.com
Committed by: GitHub noreply@github.com
Committed at: 2025-05-21 00:35:22 +0300
Parent: 35d2b54
M e2e/apiv1_auth_test.go
···
        8
        8
         )

      
        9
        9
         

      
        10
        10
         type apiv1AuthSignUpRequest struct {

      
        11
        
        -	Username string `json:"username"`

      
        12
        11
         	Email    string `json:"email"`

      
        13
        12
         	Password string `json:"password"`

      
        14
        13
         }

      
        15
        14
         

      
        16
        15
         func (e *AppTestSuite) TestAuthV1_SignUP() {

      
        17
        
        -	username := "test" + e.uuid()

      
        18
        16
         	email := e.uuid() + "test@test.com"

      
        19
        17
         	password := "password"

      
        20
        18
         

      ···
        22
        20
         		http.MethodPost,

      
        23
        21
         		"/api/v1/auth/signup",

      
        24
        22
         		e.jsonify(apiv1AuthSignUpRequest{

      
        25
        
        -			Username: username,

      
        26
        23
         			Email:    email,

      
        27
        24
         			Password: password,

      
        28
        25
         		}),

      
        29
        26
         	)

      
        30
        27
         

      
        31
        
        -	dbUser := e.getUserByUsername(username)

      
        
        28
        +	dbUser := e.getUserByEmail(email)

      
        32
        29
         	hashedPasswd, err := e.hasher.Hash(password)

      
        33
        30
         	e.require.NoError(err)

      
        34
        31
         

      ···
        40
        37
         func (e *AppTestSuite) TestAuthV1_SignUP_badrequest() {

      
        41
        38
         	tests := []struct {

      
        42
        39
         		name     string

      
        43
        
        -		username string

      
        44
        40
         		email    string

      
        45
        41
         		password string

      
        46
        42
         	}{

      
        47
        
        -		{name: "all fields empty", email: "", password: "", username: ""},

      
        48
        
        -		{

      
        49
        
        -			name:     "non valid email",

      
        50
        
        -			username: "testing",

      
        51
        
        -			email:    "email",

      
        52
        
        -			password: "password",

      
        53
        
        -		},

      
        54
        
        -		{

      
        55
        
        -			name:     "non valid password",

      
        56
        
        -			email:    "test@test.com",

      
        57
        
        -			password: "12345",

      
        58
        
        -			username: "test",

      
        59
        
        -		},

      
        
        43
        +		{name: "all fields empty", email: "", password: ""},

      
        
        44
        +		{name: "non valid email", email: "email", password: "password"},

      
        
        45
        +		{name: "non valid password", email: "test@test.com", password: "12345"},

      
        60
        46
         	}

      
        61
        47
         	for _, t := range tests {

      
        62
        48
         		httpResp := e.httpRequest(

      
        63
        49
         			http.MethodPost,

      
        64
        50
         			"/api/v1/auth/signup",

      
        65
        51
         			e.jsonify(apiv1AuthSignUpRequest{

      
        66
        
        -				Username: t.username,

      
        67
        52
         				Email:    t.email,

      
        68
        53
         				Password: t.password,

      
        69
        54
         			}),

      ···
        92
        77
         		http.MethodPost,

      
        93
        78
         		"/api/v1/auth/signup",

      
        94
        79
         		e.jsonify(apiv1AuthSignUpRequest{

      
        95
        
        -			Username: e.uuid(),

      
        96
        80
         			Email:    email,

      
        97
        81
         			Password: password,

      
        98
        82
         		}),

      ···
        119
        103
         		http.MethodPost,

      
        120
        104
         		"/api/v1/auth/signup",

      
        121
        105
         		e.jsonify(apiv1AuthSignUpRequest{

      
        122
        
        -			Username: e.uuid(),

      
        123
        106
         			Email:    email,

      
        124
        107
         			Password: password,

      
        125
        108
         		}),

      ···
        143
        126
         

      
        144
        127
         func (e *AppTestSuite) TestAuthV1_ResendVerificationEmail_wrong() {

      
        145
        128
         	email, password := e.uuid()+"@"+e.uuid()+".com", "password"

      
        146
        
        -	e.insertUser(e.uuid(), email, password, true)

      
        
        129
        +	e.insertUser(email, password, true)

      
        147
        130
         

      
        148
        131
         	tests := []struct {

      
        149
        132
         		name         string

      ···
        182
        165
         func (e *AppTestSuite) TestAuthV1_SignIn() {

      
        183
        166
         	email := e.uuid() + "email@email.com"

      
        184
        167
         	password := "qwerty"

      
        185
        
        -

      
        186
        
        -	uid := e.insertUser("test", email, password, true)

      
        
        168
        +	uid := e.insertUser(email, password, true)

      
        187
        169
         

      
        188
        170
         	httpResp := e.httpRequest(

      
        189
        171
         		http.MethodPost,

      ···
        208
        190
         func (e *AppTestSuite) TestAuthV1_SignIn_wrong() {

      
        209
        191
         	password := "password"

      
        210
        192
         	email := e.uuid() + "@test.com"

      
        211
        
        -	e.insertUser(e.uuid(), email, "password", true)

      
        
        193
        +	e.insertUser(email, "password", true)

      
        212
        194
         

      
        213
        195
         	unactivatedEmail := e.uuid() + "@test.com"

      
        214
        
        -	e.insertUser(e.uuid(), unactivatedEmail, password, false)

      
        
        196
        +	e.insertUser(unactivatedEmail, password, false)

      
        215
        197
         

      
        216
        198
         	//exhaustruct:ignore

      
        217
        199
         	tests := []struct {

      ···
        271
        253
         }

      
        272
        254
         

      
        273
        255
         func (e *AppTestSuite) TestAuthV1_RefreshTokens() {

      
        274
        
        -	uid, toks := e.createAndSingIn(e.uuid()+"@test.com", e.uuid(), "password")

      
        
        256
        +	uid, toks := e.createAndSingIn(e.uuid()+"@test.com", "password")

      
        275
        257
         	httpResp := e.httpRequest(

      
        276
        258
         		http.MethodPost,

      
        277
        259
         		"/api/v1/auth/refresh-tokens",

      ···
        306
        288
         }

      
        307
        289
         

      
        308
        290
         func (e *AppTestSuite) TestAuthV1_Logout() {

      
        309
        
        -	uid, toks := e.createAndSingIn(e.uuid()+"@test.com", e.uuid(), "password")

      
        
        291
        +	uid, toks := e.createAndSingIn(e.uuid()+"@test.com", "password")

      
        310
        292
         

      
        311
        293
         	sessionDB := e.getLastSessionByUserID(uid)

      
        312
        294
         	e.NotEmpty(sessionDB.RefreshToken)

      ···
        326
        308
         func (e *AppTestSuite) TestAuthV1_ChangePassword() {

      
        327
        309
         	password := e.uuid()

      
        328
        310
         	newPassword := e.uuid()

      
        329
        
        -	username := e.uuid()

      
        330
        
        -	_, toks := e.createAndSingIn(e.uuid()+"@test.com", username, password)

      
        
        311
        +	email := e.uuid() + "@test.com"

      
        
        312
        +	_, toks := e.createAndSingIn(email, password)

      
        331
        313
         

      
        332
        314
         	httpResp := e.httpRequest(

      
        333
        315
         		http.MethodPost,

      ···
        341
        323
         

      
        342
        324
         	e.Equal(httpResp.Code, http.StatusOK)

      
        343
        325
         

      
        344
        
        -	userDB := e.getUserByUsername(username)

      
        345
        
        -	e.Equal(userDB.Username, username)

      
        
        326
        +	userDB := e.getUserByEmail(email)

      
        346
        327
         	e.NoError(e.hasher.Compare(userDB.Password, newPassword))

      
        347
        328
         }

      
        348
        329
         

      ···
        357
        338
         

      
        358
        339
         func (e *AppTestSuite) TestAuthV1_ResetPassword() {

      
        359
        340
         	email := e.uuid() + "@test.com"

      
        360
        
        -	uname := e.uuid()

      
        361
        
        -	uid, _ := e.createAndSingIn(email, uname, "password")

      
        
        341
        +	uid, _ := e.createAndSingIn(email, "password")

      
        362
        342
         

      
        363
        343
         	httpResp := e.httpRequest(

      
        364
        344
         		http.MethodPost,

      ···
        384
        364
         		}),

      
        385
        365
         	)

      
        386
        366
         

      
        387
        
        -	dbUser := e.getUserByUsername(uname)

      
        
        367
        +	dbUser := e.getUserByEmail(email)

      
        388
        368
         	e.Equal(httpResp.Code, http.StatusOK)

      
        389
        369
         	e.NoError(e.hasher.Compare(dbUser.Password, password))

      
        390
        370
         

      ···
        393
        373
         }

      
        394
        374
         

      
        395
        375
         func (e *AppTestSuite) TestAuthV1_ResetPassword_nonExistentUser() {

      
        396
        
        -	_, _ = e.createAndSingIn(e.uuid()+"@test.comd", e.uuid(), "password")

      
        
        376
        +	_, _ = e.createAndSingIn(e.uuid()+"@test.com", "password")

      
        397
        377
         	httpResp := e.httpRequest(

      
        398
        378
         		http.MethodPost,

      
        399
        379
         		"/api/v1/auth/reset-password",

      ···
        405
        385
         	e.Equal(httpResp.Code, http.StatusBadRequest)

      
        406
        386
         }

      
        407
        387
         

      
        408
        
        -// createAndSingIn creates an activated username, logs them in,

      
        
        388
        +// createAndSingIn creates an activated user, logs them in,

      
        409
        389
         // and returns their userID along with access and refresh tokens.

      
        410
        390
         func (e *AppTestSuite) createAndSingIn(

      
        411
        
        -	email, username, password string,

      
        
        391
        +	email, password string,

      
        412
        392
         ) (uuid.UUID, apiv1AuthSignInResponse) {

      
        413
        
        -	uid := e.insertUser(username, email, password, true)

      
        
        393
        +	uid := e.insertUser(email, password, true)

      
        414
        394
         	httpResp := e.httpRequest(

      
        415
        395
         		http.MethodPost,

      
        416
        396
         		"/api/v1/auth/signin",

      
M e2e/apiv1_notes_authorized_test.go
···
        3
        3
         import "net/http"

      
        4
        4
         

      
        5
        5
         func (e *AppTestSuite) TestNoteV1_Create_authorized() {

      
        6
        
        -	uid, toks := e.createAndSingIn(e.uuid()+"@test.com", e.uuid(), "password")

      
        
        6
        +	uid, toks := e.createAndSingIn(e.uuid()+"@test.com", "password")

      
        7
        7
         	httpResp := e.httpRequest(

      
        8
        8
         		http.MethodPost,

      
        9
        9
         		"/api/v1/note",

      
M e2e/e2e_utils_db_test.go
···
        10
        10
         	"github.com/olexsmir/onasty/internal/models"

      
        11
        11
         )

      
        12
        12
         

      
        13
        
        -// getUserByUsername queries user from db by it's username

      
        14
        
        -func (e *AppTestSuite) getUserByUsername(username string) models.User {

      
        
        13
        +// getUserByEmail queries user from db by it's email

      
        
        14
        +func (e *AppTestSuite) getUserByEmail(email string) models.User {

      
        15
        15
         	query, args, err := pgq.

      
        16
        
        -		Select("id", "username", "email", "password", "created_at", "last_login_at").

      
        
        16
        +		Select("id", "email", "password", "created_at", "last_login_at").

      
        17
        17
         		From("users").

      
        18
        
        -		Where(pgq.Eq{"username": username}).

      
        
        18
        +		Where(pgq.Eq{"email": email}).

      
        19
        19
         		SQL()

      
        20
        20
         	e.require.NoError(err)

      
        21
        21
         

      
        22
        22
         	var user models.User

      
        23
        23
         	err = e.postgresDB.QueryRow(e.ctx, query, args...).

      
        24
        
        -		Scan(&user.ID, &user.Username, &user.Email, &user.Password, &user.CreatedAt, &user.LastLoginAt)

      
        
        24
        +		Scan(&user.ID, &user.Email, &user.Password, &user.CreatedAt, &user.LastLoginAt)

      
        25
        25
         	e.require.NoError(err)

      
        26
        26
         

      
        27
        27
         	return user

      
        28
        28
         }

      
        29
        29
         

      
        30
        30
         // insertUser inserts user into db

      
        31
        
        -func (e *AppTestSuite) insertUser(uname, email, passwd string, activated ...bool) uuid.UUID {

      
        
        31
        +func (e *AppTestSuite) insertUser(email, passwd string, activated ...bool) uuid.UUID {

      
        32
        32
         	p, err := e.hasher.Hash(passwd)

      
        33
        33
         	e.require.NoError(err)

      
        34
        34
         

      ···
        39
        39
         

      
        40
        40
         	query, args, err := pgq.

      
        41
        41
         		Insert("users").

      
        42
        
        -		Columns("username", "email", "password", "activated", "created_at", "last_login_at").

      
        43
        
        -		Values(uname, email, p, a, time.Now(), time.Now()).

      
        
        42
        +		Columns("email", "password", "activated", "created_at", "last_login_at").

      
        
        43
        +		Values(email, p, a, time.Now(), time.Now()).

      
        44
        44
         		Returning("id").

      
        45
        45
         		SQL()

      
        46
        46
         	e.require.NoError(err)

      ···
        77
        77
         // getLastUserByEmail gets last inserted [models.User] by user's email

      
        78
        78
         func (e *AppTestSuite) getLastUserByEmail(em string) models.User {

      
        79
        79
         	query, args, err := pgq.

      
        80
        
        -		Select("id", "username", "activated", "email", "password", "created_at", "last_login_at").

      
        
        80
        +		Select("id", "activated", "email", "password", "created_at", "last_login_at").

      
        81
        81
         		From("users").

      
        82
        82
         		Where(pgq.Eq{"email": em}).

      
        83
        83
         		OrderBy("created_at DESC").

      ···
        87
        87
         

      
        88
        88
         	var u models.User

      
        89
        89
         	err = e.postgresDB.QueryRow(e.ctx, query, args...).

      
        90
        
        -		Scan(&u.ID, &u.Username, &u.Activated, &u.Email, &u.Password, &u.CreatedAt, &u.LastLoginAt)

      
        
        90
        +		Scan(&u.ID, &u.Activated, &u.Email, &u.Password, &u.CreatedAt, &u.LastLoginAt)

      
        91
        91
         	if errors.Is(err, pgx.ErrNoRows) {

      
        92
        92
         		return models.User{} //nolint:exhaustruct

      
        93
        93
         	}

      
M internal/dtos/user.go
···
        5
        5
         )

      
        6
        6
         

      
        7
        7
         type SignUp struct {

      
        8
        
        -	Username    string

      
        9
        8
         	Email       string

      
        10
        9
         	Password    string

      
        11
        10
         	CreatedAt   time.Time

      
M internal/models/user.go
···
        10
        10
         

      
        11
        11
         var (

      
        12
        12
         	ErrUserEmailIsAlreadyInUse = errors.New("user: email is already in use")

      
        13
        
        -	ErrUsernameIsAlreadyInUse  = errors.New("user: username is already in use")

      
        14
        13
         	ErrUserIsAlreadyVerified   = errors.New("user: user is already verified")

      
        15
        14
         

      
        16
        15
         	ErrResetPasswordTokenAlreadyUsed = errors.New("reset password token is already used")

      ···
        22
        21
         

      
        23
        22
         	ErrUserInvalidEmail    = errors.New("user: invalid email")

      
        24
        23
         	ErrUserInvalidPassword = errors.New("user: password too short, minimum 6 chars")

      
        25
        
        -	ErrUserInvalidUsername = errors.New("user: username is required")

      
        26
        24
         )

      
        27
        25
         

      
        28
        26
         type User struct {

      
        29
        27
         	ID          uuid.UUID

      
        30
        
        -	Username    string

      
        31
        28
         	Email       string

      
        32
        29
         	Activated   bool

      
        33
        30
         	Password    string

      ···
        39
        36
         	_, err := mail.ParseAddress(u.Email)

      
        40
        37
         	if err != nil {

      
        41
        38
         		return ErrUserInvalidEmail

      
        42
        
        -	}

      
        43
        
        -

      
        44
        
        -	if len(u.Username) == 0 {

      
        45
        
        -		return ErrUserInvalidUsername

      
        46
        39
         	}

      
        47
        40
         

      
        48
        41
         	return u.ValidatePassword()

      
M internal/models/user_test.go
···
        11
        11
         		name string

      
        12
        12
         		fail bool

      
        13
        13
         

      
        14
        
        -		username string

      
        15
        14
         		email    string

      
        16
        15
         		password string

      
        17
        16
         	}{

      ···
        19
        18
         			name:     "valid",

      
        20
        19
         			fail:     false,

      
        21
        20
         			email:    "test@example.org",

      
        22
        
        -			username: "iuserarchbtw",

      
        23
        21
         			password: "superhardasspassword",

      
        24
        22
         		},

      
        25
        23
         		{

      
        26
        24
         			name:     "all fields empty",

      
        27
        25
         			fail:     true,

      
        28
        26
         			email:    "",

      
        29
        
        -			username: "",

      
        30
        27
         			password: "",

      
        31
        28
         		},

      
        32
        29
         		{

      
        33
        30
         			name:     "invalid email",

      
        34
        31
         			fail:     true,

      
        35
        32
         			email:    "test",

      
        36
        
        -			username: "iuserarchbtw",

      
        37
        33
         			password: "superhardasspassword",

      
        38
        34
         		},

      
        39
        35
         		{

      
        40
        36
         			name:     "invalid password",

      
        41
        37
         			fail:     true,

      
        42
        38
         			email:    "test@example.org",

      
        43
        
        -			username: "iuserarchbtw",

      
        44
        39
         			password: "12345",

      
        45
        40
         		},

      
        46
        
        -		{

      
        47
        
        -			name:     "invalid username",

      
        48
        
        -			fail:     true,

      
        49
        
        -			email:    "test@example.org",

      
        50
        
        -			username: "",

      
        51
        
        -			password: "superhardasspassword",

      
        52
        
        -		},

      
        53
        41
         	}

      
        54
        42
         

      
        55
        43
         	for _, tt := range tests {

      
        56
        44
         		t.Run(tt.name, func(t *testing.T) {

      
        57
        45
         			err := User{ //nolint:exhaustruct

      
        58
        
        -				Username: tt.username,

      
        59
        46
         				Email:    tt.email,

      
        60
        47
         				Password: tt.password,

      
        61
        48
         			}.Validate()

      
M internal/service/usersrv/oauth.go
···
        4
        4
         	"context"

      
        5
        5
         	"errors"

      
        6
        6
         	"log/slog"

      
        7
        
        -	"strings"

      
        8
        7
         	"time"

      
        9
        8
         

      
        10
        9
         	"github.com/gofrs/uuid/v5"

      ···
        74
        73
         	return userInfo, err

      
        75
        74
         }

      
        76
        75
         

      
        77
        
        -func getUsernameFromEmail(email string) string {

      
        78
        
        -	p := strings.Split(email, "@")

      
        79
        
        -	return p[0]

      
        80
        
        -}

      
        81
        
        -

      
        82
        76
         func (u *UserSrv) getUserByOAuthIDOrCreateOne(

      
        83
        77
         	ctx context.Context,

      
        84
        78
         	info oauth.UserInfo,

      ···
        88
        82
         		if errors.Is(err, models.ErrUserNotFound) {

      
        89
        83
         			uid, cerr := u.userstore.Create(ctx, models.User{

      
        90
        84
         				ID:          uuid.Nil,

      
        91
        
        -				Username:    getUsernameFromEmail(info.Email),

      
        92
        85
         				Email:       info.Email,

      
        93
        86
         				Activated:   true,

      
        94
        87
         				Password:    "",

      
M internal/service/usersrv/usersrv.go
···
        93
        93
         }

      
        94
        94
         

      
        95
        95
         func (u *UserSrv) SignUp(ctx context.Context, inp dtos.SignUp) (uuid.UUID, error) {

      
        96
        
        -	hashedPassword, err := u.hasher.Hash(inp.Password)

      
        97
        
        -	if err != nil {

      
        98
        
        -		return uuid.UUID{}, err

      
        99
        
        -	}

      
        100
        
        -

      
        101
        96
         	user := models.User{

      
        102
        97
         		ID:          uuid.Nil, // nil, because it does not get used here

      
        103
        
        -		Username:    inp.Username,

      
        104
        98
         		Email:       inp.Email,

      
        105
        99
         		Activated:   false,

      
        106
        
        -		Password:    hashedPassword,

      
        
        100
        +		Password:    inp.Password,

      
        107
        101
         		CreatedAt:   inp.CreatedAt,

      
        108
        102
         		LastLoginAt: inp.LastLoginAt,

      
        109
        103
         	}

      
        110
        
        -	if err = user.Validate(); err != nil {

      
        
        104
        +	if err := user.Validate(); err != nil {

      
        111
        105
         		return uuid.Nil, err

      
        112
        106
         	}

      
        
        107
        +

      
        
        108
        +	hashedPassword, err := u.hasher.Hash(inp.Password)

      
        
        109
        +	if err != nil {

      
        
        110
        +		return uuid.UUID{}, err

      
        
        111
        +	}

      
        
        112
        +

      
        
        113
        +	user.Password = hashedPassword

      
        113
        114
         

      
        114
        115
         	userID, err := u.userstore.Create(ctx, user)

      
        115
        116
         	if err != nil {

      
M internal/store/psql/userepo/userepo.go
···
        51
        51
         func (r *UserRepo) Create(ctx context.Context, inp models.User) (uuid.UUID, error) {

      
        52
        52
         	query, args, err := pgq.

      
        53
        53
         		Insert("users").

      
        54
        
        -		Columns("username", "email", "password", "activated", "created_at", "last_login_at").

      
        55
        
        -		Values(inp.Username, inp.Email, inp.Password, inp.Activated, inp.CreatedAt, inp.LastLoginAt).

      
        
        54
        +		Columns("email", "password", "activated", "created_at", "last_login_at").

      
        
        55
        +		Values(inp.Email, inp.Password, inp.Activated, inp.CreatedAt, inp.LastLoginAt).

      
        56
        56
         		Returning("id").

      
        57
        57
         		SQL()

      
        58
        58
         	if err != nil {

      ···
        63
        63
         	err = r.db.QueryRow(ctx, query, args...).Scan(&id)

      
        64
        64
         

      
        65
        65
         	// FIXME: somehow this does return errors but i can't errors.Is them in api layer

      
        66
        
        -	if psqlutil.IsDuplicateErr(err, "users_username_key") {

      
        67
        
        -		return uuid.UUID{}, models.ErrUsernameIsAlreadyInUse

      
        68
        
        -	}

      
        69
        
        -

      
        70
        66
         	if psqlutil.IsDuplicateErr(err, "users_email_key") {

      
        71
        67
         		return uuid.UUID{}, models.ErrUserEmailIsAlreadyInUse

      
        72
        68
         	}

      ···
        79
        75
         	email string,

      
        80
        76
         ) (models.User, error) {

      
        81
        77
         	query, args, err := pgq.

      
        82
        
        -		Select("id", "username", "email", "password", "activated", "created_at", "last_login_at").

      
        
        78
        +		Select("id", "email", "password", "activated", "created_at", "last_login_at").

      
        83
        79
         		From("users").

      
        84
        80
         		Where(pgq.Eq{"email": email}).

      
        85
        81
         		SQL()

      ···
        89
        85
         

      
        90
        86
         	var user models.User

      
        91
        87
         	err = r.db.QueryRow(ctx, query, args...).

      
        92
        
        -		Scan(&user.ID, &user.Username, &user.Email, &user.Password, &user.Activated, &user.CreatedAt, &user.LastLoginAt)

      
        
        88
        +		Scan(&user.ID, &user.Email, &user.Password, &user.Activated, &user.CreatedAt, &user.LastLoginAt)

      
        93
        89
         	if errors.Is(err, pgx.ErrNoRows) {

      
        94
        90
         		return models.User{}, models.ErrUserNotFound

      
        95
        91
         	}

      ···
        121
        117
         	provider, providerID string,

      
        122
        118
         ) (models.User, error) {

      
        123
        119
         	query := `--sql

      
        124
        
        -	select u.id, u.username, u.email, u.password, u.activated, u.created_at, u.last_login_at

      
        
        120
        +	select u.id, u.email, u.password, u.activated, u.created_at, u.last_login_at

      
        125
        121
         	from users u

      
        126
        122
         	join oauth_identities oi on u.id = oi.user_id

      
        127
        123
         	where oi.provider = $1

      ···
        130
        126
         

      
        131
        127
         	var user models.User

      
        132
        128
         	err := r.db.QueryRow(ctx, query, provider, providerID).

      
        133
        
        -		Scan(&user.ID, &user.Username, &user.Email, &user.Password, &user.Activated, &user.CreatedAt, &user.LastLoginAt)

      
        
        129
        +		Scan(&user.ID, &user.Email, &user.Password, &user.Activated, &user.CreatedAt, &user.LastLoginAt)

      
        134
        130
         	if errors.Is(err, pgx.ErrNoRows) {

      
        135
        131
         		return models.User{}, models.ErrUserNotFound

      
        136
        132
         	}

      
M internal/transport/http/apiv1/auth.go
···
        9
        9
         )

      
        10
        10
         

      
        11
        11
         type signUpRequest struct {

      
        12
        
        -	Username string `json:"username"`

      
        13
        12
         	Email    string `json:"email"`

      
        14
        13
         	Password string `json:"password"`

      
        15
        14
         }

      ···
        22
        21
         	}

      
        23
        22
         

      
        24
        23
         	if _, err := a.usersrv.SignUp(c.Request.Context(), dtos.SignUp{

      
        25
        
        -		Username:    req.Username,

      
        26
        24
         		Email:       req.Email,

      
        27
        25
         		Password:    req.Password,

      
        28
        26
         		CreatedAt:   time.Now(),

      
M internal/transport/http/apiv1/response.go
···
        21
        21
         		errors.Is(err, models.ErrResetPasswordTokenAlreadyUsed) ||

      
        22
        22
         		errors.Is(err, models.ErrResetPasswordTokenExpired) ||

      
        23
        23
         		errors.Is(err, models.ErrUserEmailIsAlreadyInUse) ||

      
        24
        
        -		errors.Is(err, models.ErrUsernameIsAlreadyInUse) ||

      
        25
        24
         		errors.Is(err, models.ErrUserIsAlreadyVerified) ||

      
        26
        25
         		errors.Is(err, models.ErrUserIsNotActivated) ||

      
        27
        26
         		errors.Is(err, models.ErrUserInvalidEmail) ||

      
        28
        27
         		errors.Is(err, models.ErrUserInvalidPassword) ||

      
        29
        
        -		errors.Is(err, models.ErrUserInvalidUsername) ||

      
        30
        28
         		// notes

      
        31
        29
         		errors.Is(err, models.ErrNoteContentIsEmpty) ||

      
        32
        30
         		errors.Is(err, models.ErrNoteSlugIsAlreadyInUse) {

      
A migrations/20250520211029_remove_username.down.sql
···
        
        1
        +ALTER TABLE users

      
        
        2
        +     add column username varchar(255) NOT NULL UNIQUE;

      
A migrations/20250520211029_remove_username.up.sql
···
        
        1
        +ALTER TABLE users

      
        
        2
        +    DROP COLUMN username;