Skip to content

Commit

Permalink
implement limiter.Limit entity storage
Browse files Browse the repository at this point in the history
  • Loading branch information
petrenko-alex committed Nov 1, 2023
1 parent 217ddf4 commit 74942fa
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 0 deletions.
5 changes: 5 additions & 0 deletions internal/limiter/base.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package limiter

type ILimitStorage interface {
GetLimits() (*Limits, error)
}
17 changes: 17 additions & 0 deletions internal/limiter/limit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package limiter

type LimitType string

const (
LoginLimit LimitType = "login"
PasswordLimit LimitType = "password"
IPLimit LimitType = "ip"
)

type Limits []Limit

type Limit struct {
limitType LimitType
value string
description string
}
86 changes: 86 additions & 0 deletions internal/limiter/limit_storage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package limiter

import (
"context"
"database/sql"
"errors"
"fmt"
)

var ErrConnectFailed = errors.New("error connecting to db")

const DSN = "postgresql:https://main:main@localhost:5432/rate_limiter?sslmode=disable"

type LimitStorage struct {
db *sql.DB
ctx context.Context
}

func NewLimitStorage() *LimitStorage {
return &LimitStorage{}
}

func (s *LimitStorage) GetLimits() (*Limits, error) {
limits := make(Limits, 0)

rows, err := s.db.QueryContext(s.ctx, "select type, value, description from rate_limit;")
if err != nil {
return nil, err
}
defer rows.Close()

for rows.Next() {
limit, scanErr := s.scanRow(rows)
if scanErr != nil {
return nil, err
}

limits = append(limits, *limit)
}

return &limits, nil
}

func (s *LimitStorage) Connect(ctx context.Context) error {
db, openErr := sql.Open("postgres", DSN)
if openErr != nil {
return fmt.Errorf(ErrConnectFailed.Error()+":%w", openErr)
}

pingErr := db.PingContext(ctx)
if pingErr != nil {
return fmt.Errorf(ErrConnectFailed.Error()+":%w", pingErr)
}

s.db = db
s.ctx = ctx

return nil
}

func (s *LimitStorage) Close(_ context.Context) error {
closeErr := s.db.Close()
if closeErr != nil {
return closeErr
}

s.ctx = nil

return nil
}

func (s *LimitStorage) scanRow(rows *sql.Rows) (*Limit, error) {
limit := Limit{}
nullableDescription := sql.NullString{}

err := rows.Scan(&limit.limitType, &limit.value, &nullableDescription)
if err != nil {
return nil, err
}

if nullableDescription.Valid {
limit.description = nullableDescription.String
}

return &limit, nil
}
34 changes: 34 additions & 0 deletions migrations/20231101165517_add_limit_table.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package migrations

import (
"context"
"database/sql"

"github.com/pressly/goose/v3"
)

func init() {
goose.AddMigrationContext(upAddLimitTable, downAddLimitTable)
}

func upAddLimitTable(ctx context.Context, tx *sql.Tx) error {
query := `create table rate_limit(
type varchar(50) primary key,
value int not null,
description varchar(255) null
);`

if _, err := tx.ExecContext(ctx, query); err != nil {
return err
}

return nil
}

func downAddLimitTable(ctx context.Context, tx *sql.Tx) error {
if _, err := tx.ExecContext(ctx, "DROP TABLE IF EXISTS rate_limit;"); err != nil {
return err
}

return nil
}
35 changes: 35 additions & 0 deletions migrations/20231101201204_fill_limit_table.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package migrations

import (
"context"
"database/sql"

"api-rate-limiter/internal/limiter"
"github.com/pressly/goose/v3"
)

func init() {
goose.AddMigrationContext(upFillLimitTable, downFillLimitTable)
}

func upFillLimitTable(ctx context.Context, tx *sql.Tx) error {
query := `insert into rate_limit(type, value, description)
values ($1, 10, 'Ограничение для логина'),
($2, 100, 'Ограничение для пароля'),
($3, 1000, null)
;`

if _, err := tx.ExecContext(ctx, query, limiter.LoginLimit, limiter.PasswordLimit, limiter.IPLimit); err != nil {
return err
}

return nil
}

func downFillLimitTable(ctx context.Context, tx *sql.Tx) error {
if _, err := tx.ExecContext(ctx, `truncate table rate_limit;`); err != nil {
return err
}

return nil
}

0 comments on commit 74942fa

Please sign in to comment.