diff --git a/internal/storage/postgresql.go b/internal/storage/postgresql.go index ffe3bca..e12d4d3 100644 --- a/internal/storage/postgresql.go +++ b/internal/storage/postgresql.go @@ -40,8 +40,8 @@ const ( type User struct { Id int32 `db:"id"` - Username string `db:"username"` - HashedPassword []byte `db:"hashed_password"` + Username string `db:"username"` + HashedPassword [60]byte `db:"hashed_pwd"` Email *string `db:"email"` @@ -51,24 +51,28 @@ type User struct { Role int32 `db:"role"` } -func (hashedUser *User) IsAdmin() bool { - return lib.IsAdmin(hashedUser.Role) +func (user *User) IsAdmin() bool { + return lib.IsAdmin(user.Role) } -func (hashedUser *User) IsModerator() bool { - return lib.IsModerator(hashedUser.Role) +func (user *User) IsModerator() bool { + return lib.IsModerator(user.Role) } -func (hashedUser *User) IsParticipant() bool { - return lib.IsParticipant(hashedUser.Role) +func (user *User) IsParticipant() bool { + return lib.IsParticipant(user.Role) } -func (hashedUser *User) IsSpectator() bool { - return lib.IsSpectator(hashedUser.Role) +func (user *User) IsSpectator() bool { + return lib.IsSpectator(user.Role) } -func (hashedUser *User) ComparePassword(password string) error { - if bcrypt.CompareHashAndPassword(hashedUser.HashedPassword, []byte(password)) != nil { +func (user *User) AtLeast(role int32) bool { + return user.Role >= role +} + +func (user *User) ComparePassword(password string) error { + if bcrypt.CompareHashAndPassword(user.HashedPassword[:], []byte(password)) != nil { return lib.ErrBadHandleOrPassword } return nil @@ -123,12 +127,12 @@ func (storage *PostgresqlStorage) CreateUser( query := storage.db.Rebind(` INSERT INTO users - (username, hashed_password, email, expires_at, created_at, role) -VALUES (?, ?, ?, ?, ?, ?) + (username, hashed_pwd, email, expires_at, role) +VALUES (?, ?, ?, ?, ?) RETURNING id `) - rows, err := storage.db.QueryxContext(ctx, query, username, hashedPassword, email, expiresAt, now, role) + rows, err := storage.db.QueryxContext(ctx, query, username, hashedPassword, email, expiresAt, role) if err != nil { return nil, storage.handlePgErr(err) } @@ -227,7 +231,7 @@ func (storage *PostgresqlStorage) UpdateUser( query := storage.db.Rebind(` UPDATE users SET username = COALESCE(?, username), - hashed_password = COALESCE(?, hashed_password), + hashed_pwd = COALESCE(?, hashed_pwd), email = COALESCE(?, email), expires_at = COALESCE(?, expires_at), role = COALESCE(?, role) diff --git a/migrations/20240608163806_initial.sql b/migrations/20240608163806_initial.sql index 08fc7e1..bd150c0 100644 --- a/migrations/20240608163806_initial.sql +++ b/migrations/20240608163806_initial.sql @@ -1,20 +1,43 @@ -- +goose Up -CREATE TABLE IF NOT EXISTS users ( - id serial NOT NULL, - username VARCHAR(70) UNIQUE NOT NULL CHECK (length(username) != 0 AND username = lower(username)), - hashed_password BYTEA NOT NULL CHECK (length(hashed_password) != 0), - email VARCHAR(70) UNIQUE CHECK (length(email) != 0 AND email = lower(email)), - expires_at TIMESTAMP NOT NULL, - created_at TIMESTAMP NOT NULL, - role INT NOT NULL CHECK (role BETWEEN 0 AND 3), - PRIMARY KEY (id) +-- +goose StatementBegin +CREATE TABLE IF NOT EXISTS users +( + id serial NOT NULL, + username VARCHAR(70) UNIQUE NOT NULL, + hashed_pwd VARCHAR(60) NOT NULL, + email VARCHAR(70) UNIQUE, + role INT NOT NULL, + expires_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + + PRIMARY KEY (id), + CHECK (length(username) != 0 AND username = lower(username)), + CHECK (length(email) != 0 AND email = lower(email)), + CHECK (lower(username) != lower(email)), + CHECK (length(hashed_pwd) != 0), + CHECK (role BETWEEN 0 AND 3) ); CREATE INDEX ON users (id); - CREATE INDEX ON users (username); - CREATE INDEX ON users (email); +CREATE FUNCTION usr_upd_trg_fn() RETURNS TRIGGER + LANGUAGE plpgsql AS +$$ +BEGIN + NEW.updated_at = NOW(); + RETURN NEW; +END; +$$; + +CREATE TRIGGER usr_upd_trg + BEFORE UPDATE + ON users + FOR EACH ROW +EXECUTE PROCEDURE usr_upd_trg_fn(); +-- +goose StatementEnd + -- +goose Down DROP TABLE IF EXISTS users; \ No newline at end of file