improve sql queries and tables
This commit is contained in:
parent
162e7e2f50
commit
3d1fe25dcb
@ -2,13 +2,11 @@ package models
|
|||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
type ActionTokenTarget int
|
type ActionTokenTarget string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
_ ActionTokenTarget = iota
|
ActionTokenTargetRestorePassword ActionTokenTarget = "restore"
|
||||||
ActionTokenTargetForgotPassword
|
ActionTokenTargetVerifyEmail ActionTokenTarget = "verify"
|
||||||
ActionTokenTargetLogin2FA
|
|
||||||
ActionTokenVerifyEmail
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ActionTokenDTO struct {
|
type ActionTokenDTO struct {
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import (
|
|||||||
type ShortlinkDTO struct {
|
type ShortlinkDTO struct {
|
||||||
Id string
|
Id string
|
||||||
Url string
|
Url string
|
||||||
Expiration time.Time
|
ExpiresAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
type ShortlinkRepo interface {
|
type ShortlinkRepo interface {
|
||||||
@ -35,8 +35,8 @@ func (u *shortlinkRepo) AddShortlink(ctx context.Context, dto ShortlinkDTO) erro
|
|||||||
_, span := u.tracer.Start(ctx, "postgres::AddShortlink")
|
_, span := u.tracer.Start(ctx, "postgres::AddShortlink")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
query := `insert into shortlinks (id, url, expiration) values ($1, $2, $3);`
|
query := `insert into shortlinks (url, expires_at) values ($1, $2);`
|
||||||
_, err := u.db.ExecContext(ctx, query, dto.Id, dto.Url, dto.Expiration)
|
_, err := u.db.ExecContext(ctx, query, dto.Url, dto.ExpiresAt)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,14 +44,14 @@ func (u *shortlinkRepo) GetShortlink(ctx context.Context, id string) (*Shortlink
|
|||||||
_, span := u.tracer.Start(ctx, "postgres::GetShortlink")
|
_, span := u.tracer.Start(ctx, "postgres::GetShortlink")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
query := `select url, expiration from shortlinks where id = $1;`
|
query := `select url, expires_at from shortlinks where id = $1;`
|
||||||
row := u.db.QueryRowContext(ctx, query, id)
|
row := u.db.QueryRowContext(ctx, query, id)
|
||||||
if err := row.Err(); err != nil {
|
if err := row.Err(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
dto := &ShortlinkDTO{Id: id}
|
dto := &ShortlinkDTO{Id: id}
|
||||||
err := row.Scan(&dto.Url, &dto.Expiration)
|
err := row.Scan(&dto.Url, &dto.ExpiresAt)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return dto, nil
|
return dto, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,16 +10,10 @@ import (
|
|||||||
"go.opentelemetry.io/otel/trace"
|
"go.opentelemetry.io/otel/trace"
|
||||||
)
|
)
|
||||||
|
|
||||||
// type userDAO struct {
|
|
||||||
// Id string `json:"id"`
|
|
||||||
// Login string `json:"login"`
|
|
||||||
// Secret string `json:"secret"`
|
|
||||||
// Name string `json:"name"`
|
|
||||||
// }
|
|
||||||
|
|
||||||
type UserRepo interface {
|
type UserRepo interface {
|
||||||
CreateUser(ctx context.Context, dto models.UserDTO) (*models.UserDTO, error)
|
CreateUser(ctx context.Context, dto models.UserDTO) (*models.UserDTO, error)
|
||||||
UpdateUser(ctx context.Context, userId string, dto models.UserUpdateDTO) error
|
UpdateUser(ctx context.Context, userId string, dto models.UserUpdateDTO) error
|
||||||
|
DeactivateUser(ctx context.Context, userId string) error
|
||||||
SetUserEmailVerified(ctx context.Context, userId string) error
|
SetUserEmailVerified(ctx context.Context, userId string) error
|
||||||
GetUserById(ctx context.Context, id string) (*models.UserDTO, error)
|
GetUserById(ctx context.Context, id string) (*models.UserDTO, error)
|
||||||
GetUserByEmail(ctx context.Context, login string) (*models.UserDTO, error)
|
GetUserByEmail(ctx context.Context, login string) (*models.UserDTO, error)
|
||||||
@ -67,6 +61,19 @@ func (u *userRepo) UpdateUser(ctx context.Context, userId string, dto models.Use
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *userRepo) DeactivateUser(ctx context.Context, userId string) error {
|
||||||
|
_, span := u.tracer.Start(ctx, "postgres::DeactivateUser")
|
||||||
|
defer span.End()
|
||||||
|
|
||||||
|
query := `update users set active=false where id = $1;`
|
||||||
|
_, err := u.db.ExecContext(ctx, query, userId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (u *userRepo) SetUserEmailVerified(ctx context.Context, userId string) error {
|
func (u *userRepo) SetUserEmailVerified(ctx context.Context, userId string) error {
|
||||||
_, span := u.tracer.Start(ctx, "postgres::SetUserEmailVerified")
|
_, span := u.tracer.Start(ctx, "postgres::SetUserEmailVerified")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|||||||
@ -50,7 +50,7 @@ func (s *shortlinkService) CreateShortlink(ctx context.Context, url string) (str
|
|||||||
dto := repos.ShortlinkDTO{
|
dto := repos.ShortlinkDTO{
|
||||||
Id: id,
|
Id: id,
|
||||||
Url: url,
|
Url: url,
|
||||||
Expiration: expiration,
|
ExpiresAt: expiration,
|
||||||
}
|
}
|
||||||
if err := s.repo.AddShortlink(ctx, dto); err != nil {
|
if err := s.repo.AddShortlink(ctx, dto); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@ -73,7 +73,7 @@ func (s *shortlinkService) GetShortlink(ctx context.Context, id string) (string,
|
|||||||
if link == nil {
|
if link == nil {
|
||||||
return "", ErrShortlinkNotexist
|
return "", ErrShortlinkNotexist
|
||||||
}
|
}
|
||||||
if time.Now().After(link.Expiration) {
|
if time.Now().After(link.ExpiresAt) {
|
||||||
return "", ErrShortlinkExpired
|
return "", ErrShortlinkExpired
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -133,7 +133,7 @@ func (u *userService) AuthenticateUser(ctx context.Context, email, password stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *userService) VerifyEmail(ctx context.Context, actionToken string) error {
|
func (u *userService) VerifyEmail(ctx context.Context, actionToken string) error {
|
||||||
token, err := u.deps.ActionTokenRepo.GetActionToken(ctx, actionToken, models.ActionTokenVerifyEmail)
|
token, err := u.deps.ActionTokenRepo.GetActionToken(ctx, actionToken, models.ActionTokenTargetVerifyEmail)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -162,7 +162,7 @@ func (u *userService) SendEmailForgotPassword(ctx context.Context, email string)
|
|||||||
models.ActionTokenDTO{
|
models.ActionTokenDTO{
|
||||||
UserId: user.Id,
|
UserId: user.Id,
|
||||||
Value: uuid.New().String(),
|
Value: uuid.New().String(),
|
||||||
Target: models.ActionTokenTargetForgotPassword,
|
Target: models.ActionTokenTargetRestorePassword,
|
||||||
Expiration: time.Now().Add(15 * time.Minute),
|
Expiration: time.Now().Add(15 * time.Minute),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -179,7 +179,7 @@ func (u *userService) sendEmailVerifyUser(ctx context.Context, userId, email str
|
|||||||
models.ActionTokenDTO{
|
models.ActionTokenDTO{
|
||||||
UserId: userId,
|
UserId: userId,
|
||||||
Value: uuid.New().String(),
|
Value: uuid.New().String(),
|
||||||
Target: models.ActionTokenVerifyEmail,
|
Target: models.ActionTokenTargetVerifyEmail,
|
||||||
Expiration: time.Now().Add(1 * time.Hour),
|
Expiration: time.Now().Add(1 * time.Hour),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -207,7 +207,7 @@ func (u *userService) SendEmailVerifyUser(ctx context.Context, email string) err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *userService) ChangePasswordWithToken(ctx context.Context, actionToken, newPassword string) error {
|
func (u *userService) ChangePasswordWithToken(ctx context.Context, actionToken, newPassword string) error {
|
||||||
token, err := u.deps.ActionTokenRepo.GetActionToken(ctx, actionToken, models.ActionTokenTargetForgotPassword)
|
token, err := u.deps.ActionTokenRepo.GetActionToken(ctx, actionToken, models.ActionTokenTargetRestorePassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
18
sql/00_common.sql
Normal file
18
sql/00_common.sql
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
create or replace function trg_proc_row_updated()
|
||||||
|
returns trigger as $$
|
||||||
|
begin
|
||||||
|
if new is distinct from old then
|
||||||
|
new.updated_at = now();
|
||||||
|
end if;
|
||||||
|
return new;
|
||||||
|
end;
|
||||||
|
$$ language plpgsql;
|
||||||
|
|
||||||
|
create or replace function trg_proc_row_created()
|
||||||
|
returns trigger as $$
|
||||||
|
begin
|
||||||
|
new.created_at = now();
|
||||||
|
new.updated_at = now();
|
||||||
|
return new;
|
||||||
|
end;
|
||||||
|
$$ language plpgsql;
|
||||||
@ -4,38 +4,20 @@ create table if not exists users (
|
|||||||
secret varchar(256) not null,
|
secret varchar(256) not null,
|
||||||
full_name varchar(256) not null,
|
full_name varchar(256) not null,
|
||||||
email_verified boolean not null default false,
|
email_verified boolean not null default false,
|
||||||
|
active boolean,
|
||||||
created_at timestamp,
|
created_at timestamp,
|
||||||
updated_at timestamp
|
updated_at timestamp
|
||||||
);
|
);
|
||||||
|
|
||||||
create index if not exists idx_users_email on users(email);
|
create index if not exists idx_users_email on users(email);
|
||||||
|
|
||||||
create or replace function set_created_at()
|
|
||||||
returns trigger as $$
|
|
||||||
begin
|
|
||||||
new.created_at = now();
|
|
||||||
new.updated_at = now();
|
|
||||||
return new;
|
|
||||||
end;
|
|
||||||
$$ language plpgsql;
|
|
||||||
|
|
||||||
create or replace trigger trg_user_created
|
create or replace trigger trg_user_created
|
||||||
before insert on users
|
before insert on users
|
||||||
for each row
|
for each row
|
||||||
execute function set_created_at();
|
execute function trg_proc_row_created();
|
||||||
|
|
||||||
create or replace function set_updated_at()
|
|
||||||
returns trigger as $$
|
|
||||||
begin
|
|
||||||
if new is distinct from old then
|
|
||||||
new.updated_at = now();
|
|
||||||
end if;
|
|
||||||
return new;
|
|
||||||
end;
|
|
||||||
$$ language plpgsql;
|
|
||||||
|
|
||||||
create or replace trigger trg_user_updated
|
create or replace trigger trg_user_updated
|
||||||
before update on users
|
before update on users
|
||||||
for each row
|
for each row
|
||||||
when(new is distinct from old)
|
when(new is distinct from old)
|
||||||
execute function set_updated_at();
|
execute function trg_proc_row_updated();
|
||||||
@ -1,5 +1,17 @@
|
|||||||
create table if not exists shortlinks (
|
create table if not exists shortlinks (
|
||||||
id text primary key,
|
id int generated always as identity,
|
||||||
url text,
|
url text not null,
|
||||||
expiration date
|
expires_at timestamp not null,
|
||||||
);
|
created_at timestamp,
|
||||||
|
updated_at timestamp
|
||||||
|
|
||||||
|
create or replace trigger trg_shortlink_created
|
||||||
|
before insert on shortlinks
|
||||||
|
for each row
|
||||||
|
when new is distinct from old
|
||||||
|
execute function trg_proc_row_created();
|
||||||
|
|
||||||
|
create or replace trigger trg_shortlink_updated
|
||||||
|
before update on shortlinks
|
||||||
|
for each row when new is distinct from old
|
||||||
|
execute function trg_proc_row_updated();
|
||||||
@ -1,9 +1,26 @@
|
|||||||
create table if not exists action_tokens (
|
create table if not exists action_tokens (
|
||||||
id int generated always as identity,
|
id int primary key generated always as identity,
|
||||||
user_id int,
|
user_id int references users(id),
|
||||||
value text,
|
value text not null,
|
||||||
target int,
|
target text not null,
|
||||||
expiration timestamp,
|
expires_at timestamp not null,
|
||||||
|
created_at timestamp,
|
||||||
|
updated_at timestamp
|
||||||
|
|
||||||
primary key(id)
|
constraint pk_action_tokens_id primary key(id),
|
||||||
|
constraint check chk_action_tokens_target target in ('verify', 'restore')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
create index if not exists idx_action_tokens_value on actions_tokens(value);
|
||||||
|
|
||||||
|
create or replace trigger trg_action_token_created
|
||||||
|
before insert on action_tokens
|
||||||
|
for each row
|
||||||
|
when new is distinct from old
|
||||||
|
execute function trg_proc_row_created();
|
||||||
|
|
||||||
|
create or replace trigger trg_action_token_updated
|
||||||
|
before update on action_tokens
|
||||||
|
for each row
|
||||||
|
when new is distinct from old
|
||||||
|
execute function trg_proc_row_updated();
|
||||||
Loading…
x
Reference in New Issue
Block a user