add ban by login attempts and fix sql
This commit is contained in:
parent
a27c8669fc
commit
00b8636b5a
@ -123,6 +123,7 @@ func (a *App) Run(p RunParams) {
|
||||
eventRepo = repos.NewEventRepo(kafka)
|
||||
|
||||
userCache = cache.NewCacheInmemSharded[models.UserDTO](cache.ShardingTypeInteger)
|
||||
loginAttemptsCache = cache.NewCacheInmem[string, int]()
|
||||
jwtCache = cache.NewCacheInmemSharded[string](cache.ShardingTypeJWT)
|
||||
linksCache = cache.NewCacheInmem[string, string]()
|
||||
)
|
||||
@ -140,6 +141,7 @@ func (a *App) Run(p RunParams) {
|
||||
userCache.CheckExpired()
|
||||
jwtCache.CheckExpired()
|
||||
linksCache.CheckExpired()
|
||||
loginAttemptsCache.CheckExpired()
|
||||
}
|
||||
}
|
||||
}()
|
||||
@ -150,6 +152,7 @@ func (a *App) Run(p RunParams) {
|
||||
Password: passwordUtil,
|
||||
UserRepo: userRepo,
|
||||
UserCache: userCache,
|
||||
LoginAttemptsCache: loginAttemptsCache,
|
||||
JwtCache: jwtCache,
|
||||
EventRepo: *eventRepo,
|
||||
ActionTokenRepo: actionTokenRepo,
|
||||
|
||||
@ -26,7 +26,7 @@ type actionTokenRepo struct {
|
||||
func (a *actionTokenRepo) CreateActionToken(ctx context.Context, dto models.ActionTokenDTO) (*models.ActionTokenDTO, error) {
|
||||
query := `
|
||||
insert into
|
||||
action_tokens (user_id, value, target, expiration)
|
||||
action_tokens (user_id, value, target, expires_at)
|
||||
values ($1, $2, $3, $4)
|
||||
returning id;`
|
||||
row := a.db.QueryRowContext(ctx, query, dto.UserId, dto.Value, dto.Target, dto.Expiration)
|
||||
@ -51,7 +51,7 @@ func (a *actionTokenRepo) GetActionToken(ctx context.Context, value string, targ
|
||||
select id, user_id from action_tokens
|
||||
where
|
||||
value=$1 and target=$2
|
||||
and CURRENT_TIMESTAMP < expiration;`
|
||||
and CURRENT_TIMESTAMP < expires_at;`
|
||||
row := a.db.QueryRowContext(ctx, query, value, target)
|
||||
|
||||
err := row.Scan(&dto.Id, &dto.UserId)
|
||||
|
||||
@ -93,7 +93,7 @@ func (u *userRepo) GetUserById(ctx context.Context, id string) (*models.UserDTO,
|
||||
|
||||
query := `
|
||||
select id, email, secret, full_name, email_verified
|
||||
from users where id = $1 and activated;`
|
||||
from users where id = $1 and active;`
|
||||
row := u.db.QueryRowContext(ctx, query, id)
|
||||
|
||||
dto := &models.UserDTO{}
|
||||
@ -113,7 +113,7 @@ func (u *userRepo) GetUserByEmail(ctx context.Context, login string) (*models.Us
|
||||
defer span.End()
|
||||
|
||||
query := `select id, email, secret, full_name, email_verified
|
||||
from users where email = $1 and activated;`
|
||||
from users where email = $1 and active;`
|
||||
row := u.db.QueryRowContext(ctx, query, login)
|
||||
|
||||
dto := &models.UserDTO{}
|
||||
|
||||
@ -54,6 +54,7 @@ type UserServiceDeps struct {
|
||||
UserRepo repos.UserRepo
|
||||
UserCache cache.Cache[string, models.UserDTO]
|
||||
JwtCache cache.Cache[string, string]
|
||||
LoginAttemptsCache cache.Cache[string, int]
|
||||
EventRepo repos.EventRepo
|
||||
ActionTokenRepo repos.ActionTokenRepo
|
||||
Logger logger.Logger
|
||||
@ -108,6 +109,22 @@ func (u *userService) CreateUser(ctx context.Context, params UserCreateParams) (
|
||||
}
|
||||
|
||||
func (u *userService) AuthenticateUser(ctx context.Context, email, password string) (string, error) {
|
||||
attempts, ok := u.deps.LoginAttemptsCache.Get(email)
|
||||
if ok && attempts >= 4 {
|
||||
return "", fmt.Errorf("too many bad login attempts")
|
||||
}
|
||||
|
||||
token, err := u.authenticateUser(ctx, email, password)
|
||||
if err != nil {
|
||||
u.deps.LoginAttemptsCache.Set(email, attempts+1, cache.Expiration{Ttl: 30 * time.Second})
|
||||
return "", err
|
||||
}
|
||||
|
||||
u.deps.LoginAttemptsCache.Del(email)
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func (u *userService) authenticateUser(ctx context.Context, email, password string) (string, error) {
|
||||
user, err := u.deps.UserRepo.GetUserByEmail(ctx, email)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
||||
@ -4,11 +4,13 @@ create table if not exists users (
|
||||
secret varchar(256) not null,
|
||||
full_name varchar(256) not null,
|
||||
email_verified boolean not null default false,
|
||||
active boolean,
|
||||
active boolean default true,
|
||||
created_at timestamp,
|
||||
updated_at timestamp
|
||||
);
|
||||
|
||||
alter table users alter column active set default true;
|
||||
|
||||
create index if not exists idx_users_email on users(email);
|
||||
|
||||
create or replace trigger trg_user_created
|
||||
|
||||
@ -4,14 +4,15 @@ create table if not exists shortlinks (
|
||||
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
|
||||
for each row
|
||||
when (new is distinct from old)
|
||||
execute function trg_proc_row_updated();
|
||||
@ -1,26 +1,25 @@
|
||||
create table if not exists action_tokens (
|
||||
id int primary key generated always as identity,
|
||||
id int generated always as identity,
|
||||
user_id int references users(id),
|
||||
value text not null,
|
||||
target text not null,
|
||||
expires_at timestamp not null,
|
||||
created_at timestamp,
|
||||
updated_at timestamp
|
||||
updated_at timestamp,
|
||||
|
||||
constraint pk_action_tokens_id primary key(id),
|
||||
constraint check chk_action_tokens_target target in ('verify', 'restore')
|
||||
constraint chk_action_tokens_target check(target in ('verify', 'restore'))
|
||||
);
|
||||
|
||||
create index if not exists idx_action_tokens_value on actions_tokens(value);
|
||||
create index if not exists idx_action_tokens_value on action_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
|
||||
when (new is distinct from old)
|
||||
execute function trg_proc_row_updated();
|
||||
Loading…
x
Reference in New Issue
Block a user