refactor:
This commit is contained in:
parent
ad8d145986
commit
3c0f01630f
29 changed files with 360 additions and 1377 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
.env
|
||||||
|
.idea
|
||||||
|
/pkg/go/gen
|
20
Dockerfile
20
Dockerfile
|
@ -1,9 +1,15 @@
|
||||||
FROM golang:latest
|
FROM golang:1.22-alpine AS base
|
||||||
|
WORKDIR /src
|
||||||
|
RUN --mount=type=cache,target=/go/pkg/mod/ \
|
||||||
|
--mount=type=bind,source=go.sum,target=go.sum \
|
||||||
|
--mount=type=bind,source=go.mod,target=go.mod \
|
||||||
|
go mod download -x
|
||||||
|
|
||||||
WORKDIR /app
|
FROM base AS builder
|
||||||
|
RUN --mount=type=cache,target=/go/pkg/mod/ \
|
||||||
|
--mount=type=bind,target=. \
|
||||||
|
go build -o /bin/server .
|
||||||
|
|
||||||
COPY . .
|
FROM scratch AS runner
|
||||||
|
COPY --from=builder /bin/server /bin/
|
||||||
RUN go build ./main.go
|
ENTRYPOINT [ "/bin/server" ]
|
||||||
|
|
||||||
CMD ["./main"]
|
|
9
Makefile
9
Makefile
|
@ -1,4 +1,7 @@
|
||||||
all:
|
dev:
|
||||||
go build
|
@buf generate proto
|
||||||
bug generate proto
|
@go run main.go
|
||||||
|
|
||||||
|
build:
|
||||||
|
@buf generate proto
|
||||||
|
# TODO: build dockerfile
|
||||||
|
|
|
@ -1,75 +0,0 @@
|
||||||
version: '3'
|
|
||||||
|
|
||||||
networks:
|
|
||||||
local:
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
db:
|
|
||||||
|
|
||||||
services:
|
|
||||||
auth-service:
|
|
||||||
build:
|
|
||||||
dockerfile: ./Dockerfile
|
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
ports:
|
|
||||||
- "8090:8090"
|
|
||||||
depends_on:
|
|
||||||
# postgres:
|
|
||||||
# condition: service_healthy
|
|
||||||
# valkey:
|
|
||||||
# condition: service_healthy
|
|
||||||
migrate:
|
|
||||||
condition: service_completed_successfully
|
|
||||||
networks:
|
|
||||||
- local
|
|
||||||
|
|
||||||
postgres:
|
|
||||||
image: postgres:14.1-alpine
|
|
||||||
restart: always
|
|
||||||
environment:
|
|
||||||
POSTGRES_USER: postgres
|
|
||||||
POSTGRES_PASSWORD: supersecretpassword
|
|
||||||
networks:
|
|
||||||
- local
|
|
||||||
ports:
|
|
||||||
- '5432:5432'
|
|
||||||
volumes:
|
|
||||||
- db:/var/lib/postgresql/data
|
|
||||||
healthcheck:
|
|
||||||
test: pg_isready -U postgres -d postgres
|
|
||||||
interval: 10s
|
|
||||||
timeout: 3s
|
|
||||||
retries: 5
|
|
||||||
|
|
||||||
migrate:
|
|
||||||
image: ghcr.io/kukymbr/goose-docker:latest
|
|
||||||
networks:
|
|
||||||
- local
|
|
||||||
volumes:
|
|
||||||
- ./migrations:/migrations
|
|
||||||
environment:
|
|
||||||
GOOSE_DRIVER: "postgres"
|
|
||||||
GOOSE_DBSTRING: "host=postgres user=postgres password=supersecretpassword dbname=postgres port=5432 sslmode=disable"
|
|
||||||
depends_on:
|
|
||||||
postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
|
|
||||||
valkey:
|
|
||||||
container_name: valkey
|
|
||||||
hostname: valkey
|
|
||||||
image: valkey/valkey:latest
|
|
||||||
build: .
|
|
||||||
volumes:
|
|
||||||
- ./conf/valkey.conf:/usr/local/etc/valkey/valkey.conf
|
|
||||||
- ./data:/data
|
|
||||||
command: ["valkey-server", "/usr/local/etc/valkey/valkey.conf"]
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD-SHELL", "valkey-cli ping | grep PONG"]
|
|
||||||
interval: 1s
|
|
||||||
timeout: 3s
|
|
||||||
retries: 5
|
|
||||||
ports:
|
|
||||||
- 6379:6379
|
|
||||||
networks:
|
|
||||||
- local
|
|
2
go.mod
2
go.mod
|
@ -1,4 +1,4 @@
|
||||||
module ms-auth
|
module git.sch9.ru/new_gate/ms-tester
|
||||||
|
|
||||||
go 1.19
|
go 1.19
|
||||||
|
|
||||||
|
|
|
@ -6,15 +6,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Env string `env:"ENV" env-default:"prod"`
|
Env string `env:"ENV" env-default:"prod"`
|
||||||
|
Pandoc string `env:"PANDOC" required:"true"`
|
||||||
PostgresDSN string `env:"POSTGRES_DSN" required:"true"`
|
PostgresDSN string `env:"POSTGRES_DSN" required:"true"`
|
||||||
RedisDSN string `env:"REDIS_DSN" required:"true"`
|
JWTSecret string `env:"JWT_SECRET" required:"true"`
|
||||||
|
|
||||||
Email string `env:"EMAIL" required:"true"`
|
|
||||||
Password string `env:"PASSWORD" required:"true"`
|
|
||||||
|
|
||||||
JWTSecret string `env:"JWT_SECRET" required:"true"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func MustSetupConfig() *Config {
|
func MustSetupConfig() *Config {
|
||||||
|
|
|
@ -11,12 +11,5 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrBadHandleOrPassword = errors.New("bad handle or password")
|
ErrBadRole = errors.New("bad role")
|
||||||
ErrBadRole = errors.New("bad role")
|
|
||||||
ErrTooShortPassword = errors.New("too short password")
|
|
||||||
ErrTooLongPassword = errors.New("too long password")
|
|
||||||
ErrBadEmail = errors.New("bad email")
|
|
||||||
ErrBadUsername = errors.New("bad username")
|
|
||||||
ErrTooShortUsername = errors.New("too short username")
|
|
||||||
ErrTooLongUsername = errors.New("too long username")
|
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,29 +4,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
RoleSpectator int32 = 0
|
|
||||||
RoleParticipant int32 = 1
|
|
||||||
RoleModerator int32 = 2
|
|
||||||
RoleAdmin int32 = 3
|
|
||||||
)
|
|
||||||
|
|
||||||
func IsAdmin(role int32) bool {
|
|
||||||
return role == RoleAdmin
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsModerator(role int32) bool {
|
|
||||||
return role == RoleModerator
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsParticipant(role int32) bool {
|
|
||||||
return role == RoleParticipant
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsSpectator(role int32) bool {
|
|
||||||
return role == RoleSpectator
|
|
||||||
}
|
|
||||||
|
|
||||||
func AsTimeP(t time.Time) *time.Time {
|
func AsTimeP(t time.Time) *time.Time {
|
||||||
return &t
|
return &t
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
package lib
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/smtp"
|
|
||||||
)
|
|
||||||
|
|
||||||
func SendMail(cfg Config, to []string, subject, body string) error {
|
|
||||||
auth := smtp.PlainAuth("", cfg.Email, cfg.Password, "smtp.gmail.com")
|
|
||||||
|
|
||||||
msg := fmt.Sprintf("From: %s\nTo: %s\nSubject: %s\n%s", cfg.Email, "", subject, body)
|
|
||||||
|
|
||||||
err := smtp.SendMail("smtp.gmail.com:587", auth, cfg.Email, to, []byte(msg))
|
|
||||||
if err != nil {
|
|
||||||
return err // FIXME
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
package lib
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/mail"
|
|
||||||
)
|
|
||||||
|
|
||||||
func ValidPassword(str string) error {
|
|
||||||
if len(str) < 5 {
|
|
||||||
return ErrTooShortPassword
|
|
||||||
}
|
|
||||||
if len(str) > 70 {
|
|
||||||
return ErrTooLongPassword
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ValidUsername(str string) error {
|
|
||||||
if len(str) < 5 {
|
|
||||||
return ErrTooShortUsername
|
|
||||||
}
|
|
||||||
if len(str) > 70 {
|
|
||||||
return ErrTooLongUsername
|
|
||||||
}
|
|
||||||
if err := ValidEmail(str); err == nil {
|
|
||||||
return ErrBadUsername
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ValidEmail(str string) error {
|
|
||||||
emailAddress, err := mail.ParseAddress(str)
|
|
||||||
if err != nil || emailAddress.Address != str {
|
|
||||||
return ErrBadEmail
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ValidRole(role int32) error {
|
|
||||||
switch role {
|
|
||||||
case RoleSpectator, RoleParticipant, RoleModerator, RoleAdmin:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return ErrBadRole
|
|
||||||
}
|
|
8
internal/models/contest.go
Normal file
8
internal/models/contest.go
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
type Contest struct {
|
||||||
|
Id *int `db:"id"`
|
||||||
|
Name *string `db:"name"`
|
||||||
|
//CreatedAt time.Time `db:"created_at"` FIXME
|
||||||
|
//UpdatedAt time.Time `db:"updated_at"` FIXME
|
||||||
|
}
|
12
internal/models/language.go
Normal file
12
internal/models/language.go
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type Language struct {
|
||||||
|
Id *int32 `db:"id"`
|
||||||
|
Name *string `db:"name"`
|
||||||
|
BuildFileHash *string `db:"build_file_hash"`
|
||||||
|
ExecuteFileHash *string `db:"execute_file_hash"`
|
||||||
|
CreatedAt *time.Time `db:"created_at"`
|
||||||
|
UpdatedAt *time.Time `db:"updated_at"`
|
||||||
|
}
|
13
internal/models/problem.go
Normal file
13
internal/models/problem.go
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type Problem struct {
|
||||||
|
Id *int32 `db:"id"`
|
||||||
|
Name *string `db:"name"`
|
||||||
|
Description *string `db:"description"`
|
||||||
|
TimeLimit *int32 `db:"time_limit"`
|
||||||
|
MemoryLimit *int32 `db:"memory_limit"`
|
||||||
|
CreatedAt *time.Time `db:"created_at"`
|
||||||
|
UpdatedAt *time.Time `db:"updated_at"`
|
||||||
|
}
|
44
internal/models/role.go
Normal file
44
internal/models/role.go
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import "git.sch9.ru/new_gate/ms-tester/internal/lib"
|
||||||
|
|
||||||
|
type Role int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
RoleSpectator Role = 0
|
||||||
|
RoleParticipant Role = 1
|
||||||
|
RoleModerator Role = 2
|
||||||
|
RoleAdmin Role = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
func (role Role) IsAdmin() bool {
|
||||||
|
return role == RoleAdmin
|
||||||
|
}
|
||||||
|
|
||||||
|
func (role Role) IsModerator() bool {
|
||||||
|
return role == RoleModerator
|
||||||
|
}
|
||||||
|
|
||||||
|
func (role Role) IsParticipant() bool {
|
||||||
|
return role == RoleParticipant
|
||||||
|
}
|
||||||
|
|
||||||
|
func (role Role) IsSpectator() bool {
|
||||||
|
return role == RoleSpectator
|
||||||
|
}
|
||||||
|
|
||||||
|
func (role Role) AtLeast(other Role) bool {
|
||||||
|
return role >= other
|
||||||
|
}
|
||||||
|
|
||||||
|
func (role Role) AtMost(other Role) bool {
|
||||||
|
return role <= other
|
||||||
|
}
|
||||||
|
|
||||||
|
func (role Role) Valid() error {
|
||||||
|
switch role {
|
||||||
|
case RoleSpectator, RoleParticipant, RoleModerator, RoleAdmin:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return lib.ErrBadRole
|
||||||
|
}
|
14
internal/models/solution.go
Normal file
14
internal/models/solution.go
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type Solution struct {
|
||||||
|
Id *int32 `db:"id"`
|
||||||
|
ParticipantId *int32 `db:"participant_id"`
|
||||||
|
ProblemId *int32 `db:"problem_id"`
|
||||||
|
LanguageId *int32 `db:"language_id"`
|
||||||
|
ContestId *int32 `db:"contest_id"`
|
||||||
|
SolutionHash *string `db:"solution_hash"`
|
||||||
|
Result *int32 `db:"result"`
|
||||||
|
CreatedAt *time.Time `db:"created_at"`
|
||||||
|
}
|
30
internal/services/tester.go
Normal file
30
internal/services/tester.go
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"git.sch9.ru/new_gate/ms-tester/internal/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ProblemStorage interface {
|
||||||
|
CreateProblem(ctx context.Context, problem *models.Problem) (int32, error)
|
||||||
|
ReadProblem(ctx context.Context, id int32) (*models.Problem, error)
|
||||||
|
UpdateProblem(ctx context.Context, problem *models.Problem) error
|
||||||
|
DeleteProblem(ctx context.Context, id int32) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProblemService struct {
|
||||||
|
problemStorage ProblemStorage
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewProblemService(
|
||||||
|
problemStorage ProblemStorage,
|
||||||
|
) *ProblemService {
|
||||||
|
return &ProblemService{
|
||||||
|
problemStorage: problemStorage,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (service *ProblemService) CreateProblem(ctx context.Context, problem *models.Problem) (int32, error) {
|
||||||
|
userId := ctx.Value("user_id").(int32)
|
||||||
|
return service.problemStorage.CreateProblem(ctx, problem)
|
||||||
|
}
|
|
@ -3,11 +3,11 @@ package storage
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"git.sch9.ru/new_gate/ms-tester/internal/lib"
|
||||||
"github.com/jackc/pgerrcode"
|
"github.com/jackc/pgerrcode"
|
||||||
"github.com/jackc/pgx/v5/pgconn"
|
"github.com/jackc/pgx/v5/pgconn"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"golang.org/x/crypto/bcrypt"
|
"golang.org/x/crypto/bcrypt"
|
||||||
"ms-auth/internal/lib"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
|
@ -1,332 +0,0 @@
|
||||||
package storage
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"ms-auth/internal/lib"
|
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt"
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/valkey-io/valkey-go"
|
|
||||||
"github.com/valkey-io/valkey-go/valkeylock"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ValkeyStorage struct {
|
|
||||||
db valkey.Client
|
|
||||||
locker valkeylock.Locker
|
|
||||||
cfg *lib.Config
|
|
||||||
logger *zap.Logger
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewValkeyStorage(dsn string, cfg *lib.Config, logger *zap.Logger) *ValkeyStorage {
|
|
||||||
opts, err := valkey.ParseURL(dsn)
|
|
||||||
if err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
db, err := valkey.NewClient(opts)
|
|
||||||
if err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
locker, err := valkeylock.NewLocker(valkeylock.LockerOption{
|
|
||||||
ClientOption: opts,
|
|
||||||
KeyMajority: 1,
|
|
||||||
NoLoopTracking: true,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return &ValkeyStorage{
|
|
||||||
db: db,
|
|
||||||
locker: locker,
|
|
||||||
cfg: cfg,
|
|
||||||
logger: logger,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (storage *ValkeyStorage) Stop() error {
|
|
||||||
storage.db.Close()
|
|
||||||
storage.locker.Close()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
sessionLifetime = time.Minute * 40
|
|
||||||
confirmationLifetime = time.Hour * 5
|
|
||||||
)
|
|
||||||
|
|
||||||
func (storage *ValkeyStorage) CreateSession(
|
|
||||||
ctx context.Context,
|
|
||||||
user_id int32,
|
|
||||||
) error {
|
|
||||||
session := NewSession(user_id)
|
|
||||||
|
|
||||||
resp := storage.db.Do(ctx, storage.db.
|
|
||||||
B().Set().
|
|
||||||
Key(string(*session.UserId)).
|
|
||||||
Value(*session.Id).
|
|
||||||
Nx().
|
|
||||||
Exat(time.Now().Add(sessionLifetime)).
|
|
||||||
Build(),
|
|
||||||
)
|
|
||||||
|
|
||||||
if err := resp.Error(); err != nil {
|
|
||||||
storage.logger.Error(err.Error())
|
|
||||||
return lib.ErrInternal
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (storage *ValkeyStorage) ReadSessionByToken(ctx context.Context, token string) (*Session, error) {
|
|
||||||
session, err := Parse(token, storage.cfg.JWTSecret)
|
|
||||||
if err != nil {
|
|
||||||
storage.logger.Error(err.Error())
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
real_session, err := storage.ReadSessionByUserId(ctx, *session.UserId)
|
|
||||||
if err != nil {
|
|
||||||
storage.logger.Error(err.Error())
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if *session.Id != *real_session.Id {
|
|
||||||
storage.logger.Error(err.Error())
|
|
||||||
return nil, lib.ErrInternal
|
|
||||||
}
|
|
||||||
|
|
||||||
return session, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (storage *ValkeyStorage) ReadSessionByUserId(ctx context.Context, user_id int32) (*Session, error) {
|
|
||||||
resp := storage.db.Do(ctx, storage.db.B().Get().Key(string(user_id)).Build())
|
|
||||||
if err := resp.Error(); err != nil {
|
|
||||||
storage.logger.Error(err.Error())
|
|
||||||
return nil, lib.ErrInternal
|
|
||||||
}
|
|
||||||
|
|
||||||
id, err := resp.ToString()
|
|
||||||
if err != nil {
|
|
||||||
storage.logger.Error(err.Error())
|
|
||||||
return nil, lib.ErrInternal
|
|
||||||
}
|
|
||||||
|
|
||||||
return &Session{
|
|
||||||
Id: &id,
|
|
||||||
UserId: &user_id,
|
|
||||||
}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (storage *ValkeyStorage) UpdateSession(ctx context.Context, session *Session) error {
|
|
||||||
resp := storage.db.Do(ctx, storage.db.
|
|
||||||
B().Set().
|
|
||||||
Key(string(*session.UserId)).
|
|
||||||
Value(*session.Id).
|
|
||||||
Xx().
|
|
||||||
Exat(time.Now().Add(sessionLifetime)).
|
|
||||||
Build(),
|
|
||||||
)
|
|
||||||
|
|
||||||
if err := resp.Error(); err != nil {
|
|
||||||
storage.logger.Error(err.Error())
|
|
||||||
return lib.ErrInternal
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (storage *ValkeyStorage) DeleteSessionByToken(ctx context.Context, token string) error {
|
|
||||||
session, err := Parse(token, storage.cfg.JWTSecret)
|
|
||||||
if err != nil {
|
|
||||||
storage.logger.Error(err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = storage.DeleteSessionByUserId(ctx, *session.UserId)
|
|
||||||
if err != nil {
|
|
||||||
storage.logger.Error(err.Error())
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (storage *ValkeyStorage) DeleteSessionByUserId(ctx context.Context, user_id int32) error {
|
|
||||||
resp := storage.db.Do(ctx, storage.db.
|
|
||||||
B().Del().
|
|
||||||
Key(string(user_id)).
|
|
||||||
Build(),
|
|
||||||
)
|
|
||||||
|
|
||||||
if err := resp.Error(); err != nil {
|
|
||||||
storage.logger.Error(err.Error())
|
|
||||||
return lib.ErrInternal
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (storage *ValkeyStorage) CreateConfirmation(ctx context.Context, conf *Confirmation) error {
|
|
||||||
resp := storage.db.Do(ctx, storage.db.
|
|
||||||
B().Set().
|
|
||||||
Key(*conf.Id).
|
|
||||||
Value(string(conf.JSON())).
|
|
||||||
Exat(time.Now().Add(confirmationLifetime)).
|
|
||||||
Build(),
|
|
||||||
)
|
|
||||||
|
|
||||||
if err := resp.Error(); err != nil {
|
|
||||||
storage.logger.Error(err.Error())
|
|
||||||
return lib.ErrInternal
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (storage *ValkeyStorage) ReadConfirmation(ctx context.Context, conf_id string) (*Confirmation, error) {
|
|
||||||
resp := storage.db.Do(ctx, storage.db.
|
|
||||||
B().Get().
|
|
||||||
Key(conf_id).
|
|
||||||
Build(),
|
|
||||||
)
|
|
||||||
|
|
||||||
if err := resp.Error(); err != nil {
|
|
||||||
storage.logger.Error(err.Error())
|
|
||||||
return nil, lib.ErrInternal
|
|
||||||
}
|
|
||||||
|
|
||||||
b, err := resp.AsBytes()
|
|
||||||
if err != nil {
|
|
||||||
storage.logger.Error(err.Error())
|
|
||||||
return nil, lib.ErrInternal
|
|
||||||
}
|
|
||||||
|
|
||||||
var conf Confirmation
|
|
||||||
err = json.Unmarshal(b, &conf)
|
|
||||||
if err != nil {
|
|
||||||
storage.logger.Error(err.Error())
|
|
||||||
return nil, lib.ErrInternal
|
|
||||||
}
|
|
||||||
|
|
||||||
return &conf, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (storage *ValkeyStorage) DeleteConfirmation(ctx context.Context, conf_id string) error {
|
|
||||||
resp := storage.db.Do(ctx, storage.db.
|
|
||||||
B().Del().
|
|
||||||
Key(conf_id).
|
|
||||||
Build(),
|
|
||||||
)
|
|
||||||
|
|
||||||
if err := resp.Error(); err != nil {
|
|
||||||
storage.logger.Error(err.Error())
|
|
||||||
return lib.ErrInternal
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrBadSession = errors.New("bad session")
|
|
||||||
ErrBadConfirmation = errors.New("bad confirmation")
|
|
||||||
)
|
|
||||||
|
|
||||||
type Confirmation struct {
|
|
||||||
Id *string `json:"id"`
|
|
||||||
UserId *int32 `json:"user_id,omitempty"`
|
|
||||||
Email *string `json:"email"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewConfirmation(userId *int32, email string) (*Confirmation, error) {
|
|
||||||
c := &Confirmation{
|
|
||||||
Id: lib.AsStringP(uuid.NewString()),
|
|
||||||
UserId: userId,
|
|
||||||
Email: &email,
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := c.Valid(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Confirmation) Valid() error {
|
|
||||||
if c.Id == nil {
|
|
||||||
return ErrBadConfirmation
|
|
||||||
}
|
|
||||||
// FIXME
|
|
||||||
// if c.userId == nil {
|
|
||||||
// return ErrBadConfirmation
|
|
||||||
// }
|
|
||||||
if c.Email == nil {
|
|
||||||
return ErrBadConfirmation
|
|
||||||
}
|
|
||||||
if err := lib.ValidEmail(*c.Email); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Confirmation) JSON() []byte {
|
|
||||||
b, err := json.Marshal(c)
|
|
||||||
if err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
type Session struct {
|
|
||||||
Id *string
|
|
||||||
UserId *int32
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewSession(userId int32) *Session {
|
|
||||||
return &Session{
|
|
||||||
Id: lib.AsStringP(uuid.NewString()),
|
|
||||||
UserId: &userId,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Session) Valid() error {
|
|
||||||
if s.Id == nil {
|
|
||||||
return ErrBadSession
|
|
||||||
}
|
|
||||||
if s.UserId == nil {
|
|
||||||
return ErrBadSession
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s Session) Token(secret string) (string, error) {
|
|
||||||
if err := s.Valid(); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
refreshToken := jwt.NewWithClaims(jwt.SigningMethodHS256, s)
|
|
||||||
str, err := refreshToken.SignedString([]byte(secret))
|
|
||||||
if err != nil {
|
|
||||||
return "", ErrBadSession
|
|
||||||
}
|
|
||||||
return str, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Parse(tkn string, secret string) (*Session, error) {
|
|
||||||
parsedToken, err := jwt.ParseWithClaims(tkn, &Session{}, func(token *jwt.Token) (interface{}, error) {
|
|
||||||
return []byte(secret), nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, ErrBadSession
|
|
||||||
}
|
|
||||||
session := parsedToken.Claims.(*Session)
|
|
||||||
if err := session.Valid(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return session, nil
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
package transport
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"google.golang.org/protobuf/types/known/emptypb"
|
|
||||||
emailv1 "ms-auth/pkg/go/gen/email/v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (s *AuthServer) SendEmail(ctx context.Context, req *emailv1.SendEmailRequest) (*emptypb.Empty, error) {
|
|
||||||
panic("not implemented")
|
|
||||||
}
|
|
|
@ -1 +1,25 @@
|
||||||
package transport
|
package transport
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ReqWithToken interface {
|
||||||
|
GetToken() string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *TesterServer) AuthInterceptor() grpc.UnaryServerInterceptor {
|
||||||
|
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||||
|
reqWithToken, ok := req.(ReqWithToken)
|
||||||
|
if !ok {
|
||||||
|
return nil, status.Errorf(codes.Unknown, "") // FIXME
|
||||||
|
}
|
||||||
|
|
||||||
|
token := reqWithToken.GetToken()
|
||||||
|
|
||||||
|
return handler(ctx, req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -2,93 +2,40 @@ package transport
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"git.sch9.ru/new_gate/ms-tester/internal/models"
|
||||||
|
testerv1 "git.sch9.ru/new_gate/ms-tester/pkg/go/gen/tester/v1"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"google.golang.org/protobuf/types/known/timestamppb"
|
"google.golang.org/protobuf/types/known/timestamppb"
|
||||||
"ms-auth/internal/storage"
|
|
||||||
emailv1 "ms-auth/pkg/go/gen/email/v1"
|
|
||||||
sessionv1 "ms-auth/pkg/go/gen/session/v1"
|
|
||||||
userv1 "ms-auth/pkg/go/gen/user/v1"
|
|
||||||
"net"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SessionServiceI interface {
|
type ProblemService interface {
|
||||||
Create(ctx context.Context, handle, password string) (*string, error)
|
CreateProblem(ctx context.Context, problem *models.Problem) (int32, error)
|
||||||
Read(ctx context.Context, token string) (*int32, error)
|
ReadProblem(ctx context.Context, id int32) (*models.Problem, error)
|
||||||
Update(ctx context.Context, token string) error
|
UpdateProblem(ctx context.Context, problem *models.Problem) error
|
||||||
Delete(ctx context.Context, token string) error
|
DeleteProblem(ctx context.Context, id int32) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserServiceI interface {
|
type TesterServer struct {
|
||||||
CreateUser(ctx context.Context, token, username, password string, email *string, expiresAt *time.Time, role *int32) (*int32, error)
|
testerv1.UnimplementedTesterServiceServer
|
||||||
ReadUser(ctx context.Context, token string, id int32) (*storage.User, error)
|
problemService ProblemService
|
||||||
UpdateUser(ctx context.Context, token string, id int32, username *string, password *string, email *string, expiresAt *time.Time, role *int32) error
|
|
||||||
DeleteUser(ctx context.Context, token string, id int32) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type AuthServer struct {
|
|
||||||
emailv1.UnimplementedEmailServiceServer
|
|
||||||
|
|
||||||
sessionv1.UnimplementedSessionServiceServer
|
|
||||||
sessionService SessionServiceI
|
|
||||||
|
|
||||||
userv1.UnimplementedUserServiceServer
|
|
||||||
userService UserServiceI
|
|
||||||
|
|
||||||
gRPCServer *grpc.Server
|
gRPCServer *grpc.Server
|
||||||
logger *zap.Logger
|
logger *zap.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAuthServer creates a new instance of the AuthServer struct.
|
func NewTesterServer(problemService ProblemService, gRPCServer *grpc.Server, logger *zap.Logger) *TesterServer {
|
||||||
//
|
server := &TesterServer{
|
||||||
// Parameters:
|
problemService: problemService,
|
||||||
// - sessionService: A pointer to the SessionServiceI interface.
|
|
||||||
// - gRPCServer: A pointer to the grpc.Server struct.
|
|
||||||
// - logger: A pointer to the zap.Logger struct.
|
|
||||||
//
|
|
||||||
// Returns:
|
|
||||||
// - *AuthServer: A pointer to the AuthServer struct.
|
|
||||||
func NewAuthServer(sessionService SessionServiceI, userService UserServiceI, gRPCServer *grpc.Server, logger *zap.Logger) *AuthServer {
|
|
||||||
return &AuthServer{
|
|
||||||
sessionService: sessionService,
|
|
||||||
userService: userService,
|
|
||||||
gRPCServer: gRPCServer,
|
gRPCServer: gRPCServer,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Start starts the AuthServer and listens on port :8090.
|
testerv1.RegisterTesterServiceServer(gRPCServer, server)
|
||||||
//
|
|
||||||
// It creates a listener on the specified address and starts serving incoming requests.
|
|
||||||
// It also logs the server start and any errors that occur during serving.
|
|
||||||
//
|
|
||||||
// No parameters.
|
|
||||||
// No return values.
|
|
||||||
func (s *AuthServer) Start() {
|
|
||||||
lis, err := net.Listen("tcp", ":8090")
|
|
||||||
if err != nil {
|
|
||||||
s.logger.Fatal("")
|
|
||||||
}
|
|
||||||
|
|
||||||
sessionv1.RegisterSessionServiceServer(s.gRPCServer, s)
|
return server
|
||||||
go func() {
|
|
||||||
s.logger.Info("Listening on :8090")
|
|
||||||
if err := s.gRPCServer.Serve(lis); err != nil {
|
|
||||||
panic(err.Error())
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
s.logger.Info("server started")
|
|
||||||
}
|
|
||||||
|
|
||||||
// GracefullyStop stops the server gracefully.
|
|
||||||
//
|
|
||||||
// No parameters.
|
|
||||||
// No return values.
|
|
||||||
func (s *AuthServer) GracefullyStop() {
|
|
||||||
s.gRPCServer.GracefulStop()
|
|
||||||
s.logger.Info("server stopped")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func AsTimeP(t *timestamppb.Timestamp) *time.Time {
|
func AsTimeP(t *timestamppb.Timestamp) *time.Time {
|
||||||
|
@ -99,25 +46,9 @@ func AsTimeP(t *timestamppb.Timestamp) *time.Time {
|
||||||
return &tt
|
return &tt
|
||||||
}
|
}
|
||||||
|
|
||||||
func AsInt32P(v *userv1.Role) *int32 {
|
|
||||||
if v == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
vv := int32(v.Number())
|
|
||||||
return &vv
|
|
||||||
}
|
|
||||||
|
|
||||||
func AsTimestampP(t *time.Time) *timestamppb.Timestamp {
|
func AsTimestampP(t *time.Time) *timestamppb.Timestamp {
|
||||||
if t == nil {
|
if t == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return timestamppb.New(*t)
|
return timestamppb.New(*t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func AsRoleP(r *int32) *userv1.Role {
|
|
||||||
if r == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
rr := userv1.Role(*r)
|
|
||||||
return &rr
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
package transport
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"google.golang.org/grpc/codes"
|
|
||||||
"google.golang.org/grpc/status"
|
|
||||||
"google.golang.org/protobuf/types/known/emptypb"
|
|
||||||
sessionv1 "ms-auth/pkg/go/gen/session/v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (s *AuthServer) Create(ctx context.Context, req *sessionv1.CreateSessionRequest) (*sessionv1.CreateSessionResponse, error) {
|
|
||||||
token, err := s.sessionService.Create(ctx, req.GetHandle(), req.GetPassword())
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Unknown, err.Error()) // FIXME
|
|
||||||
}
|
|
||||||
return &sessionv1.CreateSessionResponse{
|
|
||||||
Token: *token,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *AuthServer) Read(ctx context.Context, req *sessionv1.ReadSessionRequest) (*sessionv1.ReadSessionResponse, error) {
|
|
||||||
id, err := s.sessionService.Read(ctx, req.GetToken())
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Unknown, err.Error()) // FIXME
|
|
||||||
}
|
|
||||||
return &sessionv1.ReadSessionResponse{
|
|
||||||
UserId: *id,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *AuthServer) Update(ctx context.Context, req *sessionv1.UpdateSessionRequest) (*emptypb.Empty, error) {
|
|
||||||
err := s.sessionService.Update(ctx, req.GetToken())
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Unknown, err.Error()) // FIXME
|
|
||||||
}
|
|
||||||
return &emptypb.Empty{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *AuthServer) Delete(ctx context.Context, req *sessionv1.DeleteSessionRequest) (*emptypb.Empty, error) {
|
|
||||||
err := s.sessionService.Delete(ctx, req.GetToken())
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Unknown, err.Error()) // FIXME
|
|
||||||
}
|
|
||||||
return &emptypb.Empty{}, nil
|
|
||||||
}
|
|
82
internal/transport/tester.go
Normal file
82
internal/transport/tester.go
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
package transport
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"git.sch9.ru/new_gate/ms-tester/internal/lib"
|
||||||
|
"git.sch9.ru/new_gate/ms-tester/internal/models"
|
||||||
|
testerv1 "git.sch9.ru/new_gate/ms-tester/pkg/go/gen/tester/v1"
|
||||||
|
"google.golang.org/grpc/codes"
|
||||||
|
"google.golang.org/grpc/status"
|
||||||
|
"google.golang.org/protobuf/types/known/emptypb"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *TesterServer) CreateProblem(ctx context.Context, req *testerv1.CreateProblemRequest) (*testerv1.CreateProblemResponse, error) {
|
||||||
|
problem := req.GetProblem()
|
||||||
|
if problem == nil {
|
||||||
|
return nil, status.Errorf(codes.Unknown, "") // FIXME
|
||||||
|
}
|
||||||
|
id, err := s.problemService.CreateProblem(
|
||||||
|
ctx,
|
||||||
|
&models.Problem{
|
||||||
|
Name: lib.AsStringP(problem.Name),
|
||||||
|
Description: lib.AsStringP(problem.Description),
|
||||||
|
TimeLimit: lib.AsInt32P(problem.TimeLimit),
|
||||||
|
MemoryLimit: lib.AsInt32P(problem.MemoryLimit),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Unknown, err.Error()) // FIXME
|
||||||
|
}
|
||||||
|
|
||||||
|
return &testerv1.CreateProblemResponse{
|
||||||
|
Id: id,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *TesterServer) ReadProblem(ctx context.Context, req *testerv1.ReadProblemRequest) (*testerv1.ReadProblemResponse, error) {
|
||||||
|
problem, err := s.problemService.ReadProblem(ctx, req.GetId())
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Unknown, err.Error()) // FIXME
|
||||||
|
}
|
||||||
|
return &testerv1.ReadProblemResponse{
|
||||||
|
Problem: &testerv1.ReadProblemResponse_Problem{
|
||||||
|
Id: *problem.Id,
|
||||||
|
Name: *problem.Name,
|
||||||
|
Description: *problem.Description,
|
||||||
|
TimeLimit: *problem.TimeLimit,
|
||||||
|
MemoryLimit: *problem.MemoryLimit,
|
||||||
|
CreatedAt: AsTimestampP(problem.CreatedAt),
|
||||||
|
UpdatedAt: AsTimestampP(problem.UpdatedAt),
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *TesterServer) UpdateProblem(ctx context.Context, req *testerv1.UpdateProblemRequest) (*emptypb.Empty, error) {
|
||||||
|
problem := req.GetProblem()
|
||||||
|
if problem == nil {
|
||||||
|
return nil, status.Errorf(codes.Unknown, "") // FIXME
|
||||||
|
}
|
||||||
|
err := s.problemService.UpdateProblem(
|
||||||
|
ctx,
|
||||||
|
&models.Problem{
|
||||||
|
Id: lib.AsInt32P(problem.Id),
|
||||||
|
Name: problem.Name,
|
||||||
|
Description: problem.Description,
|
||||||
|
TimeLimit: problem.TimeLimit,
|
||||||
|
MemoryLimit: problem.MemoryLimit,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Unknown, err.Error()) // FIXME
|
||||||
|
}
|
||||||
|
|
||||||
|
return &emptypb.Empty{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *TesterServer) DeleteProblem(ctx context.Context, req *testerv1.DeleteProblemRequest) (*emptypb.Empty, error) {
|
||||||
|
err := s.problemService.DeleteProblem(ctx, req.GetId())
|
||||||
|
if err != nil {
|
||||||
|
return nil, status.Errorf(codes.Unknown, err.Error()) // FIXME
|
||||||
|
}
|
||||||
|
return &emptypb.Empty{}, nil
|
||||||
|
}
|
|
@ -1,124 +0,0 @@
|
||||||
package transport
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"google.golang.org/grpc/codes"
|
|
||||||
"google.golang.org/grpc/status"
|
|
||||||
"google.golang.org/protobuf/types/known/emptypb"
|
|
||||||
userv1 "ms-auth/pkg/go/gen/user/v1"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (s *AuthServer) CreateUser(ctx context.Context, req *userv1.CreateUserRequest) (*userv1.CreateUserResponse, error) {
|
|
||||||
user := req.GetUser()
|
|
||||||
if user == nil {
|
|
||||||
return nil, status.Errorf(codes.Unknown, "") // FIXME
|
|
||||||
}
|
|
||||||
id, err := s.userService.CreateUser(
|
|
||||||
ctx,
|
|
||||||
req.GetToken(),
|
|
||||||
user.GetUsername(),
|
|
||||||
user.GetPassword(),
|
|
||||||
user.Email,
|
|
||||||
AsTimeP(user.ExpiresAt),
|
|
||||||
AsInt32P(user.Role),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Unknown, err.Error()) // FIXME
|
|
||||||
}
|
|
||||||
|
|
||||||
return &userv1.CreateUserResponse{
|
|
||||||
Id: *id,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *AuthServer) ReadUser(ctx context.Context, req *userv1.ReadUserRequest) (*userv1.ReadUserResponse, error) {
|
|
||||||
user, err := s.userService.ReadUser(
|
|
||||||
ctx,
|
|
||||||
req.GetToken(),
|
|
||||||
req.GetId(),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Unknown, err.Error()) // FIXME
|
|
||||||
}
|
|
||||||
|
|
||||||
return &userv1.ReadUserResponse{
|
|
||||||
User: &userv1.ReadUserResponse_User{
|
|
||||||
Id: user.Id,
|
|
||||||
Username: user.Username,
|
|
||||||
Email: user.Email,
|
|
||||||
ExpiresAt: AsTimestampP(&user.ExpiresAt),
|
|
||||||
CreatedAt: AsTimestampP(&user.CreatedAt),
|
|
||||||
Role: *AsRoleP(&user.Role),
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *AuthServer) UpdateUser(ctx context.Context, req *userv1.UpdateUserRequest) (*emptypb.Empty, error) {
|
|
||||||
user := req.GetUser()
|
|
||||||
if user == nil {
|
|
||||||
return nil, status.Errorf(codes.Unknown, "") // FIXME
|
|
||||||
}
|
|
||||||
err := s.userService.UpdateUser(
|
|
||||||
ctx,
|
|
||||||
req.GetToken(),
|
|
||||||
user.GetId(),
|
|
||||||
user.Username,
|
|
||||||
user.Password,
|
|
||||||
user.Email,
|
|
||||||
AsTimeP(user.ExpiresAt),
|
|
||||||
AsInt32P(user.Role),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Unknown, err.Error()) // FIXME
|
|
||||||
}
|
|
||||||
return &emptypb.Empty{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *AuthServer) DeleteUser(ctx context.Context, req *userv1.DeleteUserRequest) (*emptypb.Empty, error) {
|
|
||||||
err := s.userService.DeleteUser(
|
|
||||||
ctx,
|
|
||||||
req.GetToken(),
|
|
||||||
req.GetId(),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, status.Errorf(codes.Unknown, err.Error()) // FIXME
|
|
||||||
}
|
|
||||||
return &emptypb.Empty{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *AuthServer) ConfirmEmail(ctx context.Context, req *userv1.ConfirmEmailRequest) (*emptypb.Empty, error) {
|
|
||||||
panic("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *AuthServer) RegisterUser(ctx context.Context, req *userv1.RegisterUserRequest) (*emptypb.Empty, error) {
|
|
||||||
panic("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *AuthServer) ConfirmRegisterUser(ctx context.Context, req *userv1.ConfirmRegisterUserRequest) (*emptypb.Empty, error) {
|
|
||||||
panic("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *AuthServer) ResetPassword(ctx context.Context, req *userv1.ResetPasswordRequest) (*emptypb.Empty, error) {
|
|
||||||
panic("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *AuthServer) ConfirmResetPassword(ctx context.Context, req *userv1.ConfirmResetPasswordRequest) (*emptypb.Empty, error) {
|
|
||||||
panic("not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func shortenEmail(email *string) *string {
|
|
||||||
if email == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
parts := strings.Split(*email, "@")
|
|
||||||
p1 := parts[0]
|
|
||||||
p2 := parts[1]
|
|
||||||
a := "****"
|
|
||||||
if len(p1) <= 4 {
|
|
||||||
e := a + "@" + p2
|
|
||||||
return &e
|
|
||||||
}
|
|
||||||
e := p1[:len(p1)-4] + a + "@" + p2
|
|
||||||
return &e
|
|
||||||
}
|
|
70
main.go
70
main.go
|
@ -1,47 +1,33 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
"google.golang.org/grpc"
|
|
||||||
"ms-auth/internal/app"
|
|
||||||
"ms-auth/internal/lib"
|
|
||||||
"ms-auth/internal/services"
|
|
||||||
"ms-auth/internal/storage"
|
|
||||||
"ms-auth/internal/transport"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cfg := lib.MustSetupConfig()
|
//cfg := lib.MustSetupConfig()
|
||||||
|
//
|
||||||
|
//var logger *zap.Logger
|
||||||
|
//if cfg.Env == "prod" {
|
||||||
|
// logger = zap.Must(zap.NewProduction())
|
||||||
|
//} else if cfg.Env == "dev" {
|
||||||
|
// logger = zap.Must(zap.NewDevelopment())
|
||||||
|
//} else {
|
||||||
|
// panic(fmt.Sprintf(`error reading config: env expected "prod" or "dev", got "%s"`, cfg.Env))
|
||||||
|
//}
|
||||||
|
|
||||||
var logger *zap.Logger
|
//postgres := storage.NewUserStorage(cfg.PostgresDSN, logger)
|
||||||
if cfg.Env == "prod" {
|
//
|
||||||
logger = zap.Must(zap.NewProduction())
|
//vk := storage.NewValkeyStorage(cfg.RedisDSN, cfg, logger)
|
||||||
} else if cfg.Env == "dev" {
|
//
|
||||||
logger = zap.Must(zap.NewDevelopment())
|
//sessionService := services.NewSessionService(vk, postgres, cfg)
|
||||||
} else {
|
//userService := services.NewUserService(postgres, vk, vk, cfg)
|
||||||
panic(fmt.Sprintf(`error reading config: env expected "prod" or "dev", got "%s"`, cfg.Env))
|
//
|
||||||
}
|
//server := transport.NewAuthServer(sessionService, userService, grpc.NewServer(), logger)
|
||||||
|
//
|
||||||
postgres := storage.NewUserStorage(cfg.PostgresDSN, logger)
|
//application := app.NewApp(cfg, server)
|
||||||
|
//
|
||||||
vk := storage.NewValkeyStorage(cfg.RedisDSN, cfg, logger)
|
//application.Start()
|
||||||
|
//
|
||||||
sessionService := services.NewSessionService(vk, postgres, cfg)
|
//stop := make(chan os.Signal, 1)
|
||||||
userService := services.NewUserService(postgres, vk, vk, cfg)
|
//signal.Notify(stop, syscall.SIGTERM, syscall.SIGINT)
|
||||||
|
//
|
||||||
server := transport.NewAuthServer(sessionService, userService, grpc.NewServer(), logger)
|
//<-stop
|
||||||
|
//application.GracefullyStop()
|
||||||
application := app.NewApp(cfg, server)
|
|
||||||
|
|
||||||
application.Start()
|
|
||||||
|
|
||||||
stop := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(stop, syscall.SIGTERM, syscall.SIGINT)
|
|
||||||
|
|
||||||
<-stop
|
|
||||||
application.GracefullyStop()
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,412 +0,0 @@
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
|
||||||
// versions:
|
|
||||||
// protoc-gen-go v1.28.1
|
|
||||||
// protoc (unknown)
|
|
||||||
// source: user/v1/user.proto
|
|
||||||
|
|
||||||
package userv1
|
|
||||||
|
|
||||||
import (
|
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
|
||||||
_ "google.golang.org/protobuf/types/known/emptypb"
|
|
||||||
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
|
||||||
reflect "reflect"
|
|
||||||
sync "sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Verify that this generated code is sufficiently up-to-date.
|
|
||||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
|
||||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
|
||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
|
||||||
)
|
|
||||||
|
|
||||||
type Role int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
Role_ROLE_SPECTATOR_UNSPECIFIED Role = 0
|
|
||||||
Role_ROLE_PARTICIPANT Role = 1
|
|
||||||
Role_ROLE_MODERATOR Role = 2
|
|
||||||
Role_ROLE_ADMIN Role = 3
|
|
||||||
)
|
|
||||||
|
|
||||||
// Enum value maps for Role.
|
|
||||||
var (
|
|
||||||
Role_name = map[int32]string{
|
|
||||||
0: "ROLE_SPECTATOR_UNSPECIFIED",
|
|
||||||
1: "ROLE_PARTICIPANT",
|
|
||||||
2: "ROLE_MODERATOR",
|
|
||||||
3: "ROLE_ADMIN",
|
|
||||||
}
|
|
||||||
Role_value = map[string]int32{
|
|
||||||
"ROLE_SPECTATOR_UNSPECIFIED": 0,
|
|
||||||
"ROLE_PARTICIPANT": 1,
|
|
||||||
"ROLE_MODERATOR": 2,
|
|
||||||
"ROLE_ADMIN": 3,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func (x Role) Enum() *Role {
|
|
||||||
p := new(Role)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x Role) String() string {
|
|
||||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Role) Descriptor() protoreflect.EnumDescriptor {
|
|
||||||
return file_user_v1_user_proto_enumTypes[0].Descriptor()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Role) Type() protoreflect.EnumType {
|
|
||||||
return &file_user_v1_user_proto_enumTypes[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x Role) Number() protoreflect.EnumNumber {
|
|
||||||
return protoreflect.EnumNumber(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use Role.Descriptor instead.
|
|
||||||
func (Role) EnumDescriptor() ([]byte, []int) {
|
|
||||||
return file_user_v1_user_proto_rawDescGZIP(), []int{0}
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreateUserRequest struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"`
|
|
||||||
User *CreateUserRequest_User `protobuf:"bytes,2,opt,name=user,proto3" json:"user,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CreateUserRequest) Reset() {
|
|
||||||
*x = CreateUserRequest{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_user_v1_user_proto_msgTypes[0]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CreateUserRequest) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*CreateUserRequest) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *CreateUserRequest) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_user_v1_user_proto_msgTypes[0]
|
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use CreateUserRequest.ProtoReflect.Descriptor instead.
|
|
||||||
func (*CreateUserRequest) Descriptor() ([]byte, []int) {
|
|
||||||
return file_user_v1_user_proto_rawDescGZIP(), []int{0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CreateUserRequest) GetToken() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Token
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CreateUserRequest) GetUser() *CreateUserRequest_User {
|
|
||||||
if x != nil {
|
|
||||||
return x.User
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreateUserResponse struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CreateUserResponse) Reset() {
|
|
||||||
*x = CreateUserResponse{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_user_v1_user_proto_msgTypes[1]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CreateUserResponse) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*CreateUserResponse) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *CreateUserResponse) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_user_v1_user_proto_msgTypes[1]
|
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use CreateUserResponse.ProtoReflect.Descriptor instead.
|
|
||||||
func (*CreateUserResponse) Descriptor() ([]byte, []int) {
|
|
||||||
return file_user_v1_user_proto_rawDescGZIP(), []int{1}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CreateUserResponse) GetId() int32 {
|
|
||||||
if x != nil {
|
|
||||||
return x.Id
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type CreateUserRequest_User struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"`
|
|
||||||
Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
|
|
||||||
Email *string `protobuf:"bytes,3,opt,name=email,proto3,oneof" json:"email,omitempty"`
|
|
||||||
ExpiresAt *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=expires_at,json=expiresAt,proto3,oneof" json:"expires_at,omitempty"`
|
|
||||||
Role *Role `protobuf:"varint,5,opt,name=role,proto3,enum=proto.user.v1.Role,oneof" json:"role,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CreateUserRequest_User) Reset() {
|
|
||||||
*x = CreateUserRequest_User{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_user_v1_user_proto_msgTypes[2]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CreateUserRequest_User) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*CreateUserRequest_User) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *CreateUserRequest_User) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_user_v1_user_proto_msgTypes[2]
|
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use CreateUserRequest_User.ProtoReflect.Descriptor instead.
|
|
||||||
func (*CreateUserRequest_User) Descriptor() ([]byte, []int) {
|
|
||||||
return file_user_v1_user_proto_rawDescGZIP(), []int{0, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CreateUserRequest_User) GetUsername() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Username
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CreateUserRequest_User) GetPassword() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Password
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CreateUserRequest_User) GetEmail() string {
|
|
||||||
if x != nil && x.Email != nil {
|
|
||||||
return *x.Email
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CreateUserRequest_User) GetExpiresAt() *timestamppb.Timestamp {
|
|
||||||
if x != nil {
|
|
||||||
return x.ExpiresAt
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *CreateUserRequest_User) GetRole() Role {
|
|
||||||
if x != nil && x.Role != nil {
|
|
||||||
return *x.Role
|
|
||||||
}
|
|
||||||
return Role_ROLE_SPECTATOR_UNSPECIFIED
|
|
||||||
}
|
|
||||||
|
|
||||||
var File_user_v1_user_proto protoreflect.FileDescriptor
|
|
||||||
|
|
||||||
var file_user_v1_user_proto_rawDesc = []byte{
|
|
||||||
0x0a, 0x12, 0x75, 0x73, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x70,
|
|
||||||
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0d, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x75, 0x73, 0x65, 0x72,
|
|
||||||
0x2e, 0x76, 0x31, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74,
|
|
||||||
0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70,
|
|
||||||
0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f,
|
|
||||||
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
|
||||||
0x6f, 0x22, 0xd0, 0x02, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72,
|
|
||||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e,
|
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x39, 0x0a,
|
|
||||||
0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x72,
|
|
||||||
0x6f, 0x74, 0x6f, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61,
|
|
||||||
0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x55, 0x73,
|
|
||||||
0x65, 0x72, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x1a, 0xe9, 0x01, 0x0a, 0x04, 0x55, 0x73, 0x65,
|
|
||||||
0x72, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
|
|
||||||
0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a,
|
|
||||||
0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
|
|
||||||
0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x19, 0x0a, 0x05, 0x65, 0x6d, 0x61,
|
|
||||||
0x69, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69,
|
|
||||||
0x6c, 0x88, 0x01, 0x01, 0x12, 0x3e, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f,
|
|
||||||
0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
|
|
||||||
0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73,
|
|
||||||
0x74, 0x61, 0x6d, 0x70, 0x48, 0x01, 0x52, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41,
|
|
||||||
0x74, 0x88, 0x01, 0x01, 0x12, 0x2c, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01,
|
|
||||||
0x28, 0x0e, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e,
|
|
||||||
0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x48, 0x02, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x88,
|
|
||||||
0x01, 0x01, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x42, 0x0d, 0x0a, 0x0b,
|
|
||||||
0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x5f,
|
|
||||||
0x72, 0x6f, 0x6c, 0x65, 0x22, 0x24, 0x0a, 0x12, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73,
|
|
||||||
0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64,
|
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x02, 0x69, 0x64, 0x2a, 0x60, 0x0a, 0x04, 0x52, 0x6f,
|
|
||||||
0x6c, 0x65, 0x12, 0x1e, 0x0a, 0x1a, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x53, 0x50, 0x45, 0x43, 0x54,
|
|
||||||
0x41, 0x54, 0x4f, 0x52, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44,
|
|
||||||
0x10, 0x00, 0x12, 0x14, 0x0a, 0x10, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x50, 0x41, 0x52, 0x54, 0x49,
|
|
||||||
0x43, 0x49, 0x50, 0x41, 0x4e, 0x54, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x52, 0x4f, 0x4c, 0x45,
|
|
||||||
0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x52, 0x41, 0x54, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a,
|
|
||||||
0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x41, 0x44, 0x4d, 0x49, 0x4e, 0x10, 0x03, 0x32, 0x60, 0x0a, 0x0b,
|
|
||||||
0x55, 0x73, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x51, 0x0a, 0x0a, 0x43,
|
|
||||||
0x72, 0x65, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x20, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
|
||||||
0x6f, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
|
|
||||||
0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x70, 0x72,
|
|
||||||
0x6f, 0x74, 0x6f, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61,
|
|
||||||
0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x97,
|
|
||||||
0x01, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x75, 0x73, 0x65,
|
|
||||||
0x72, 0x2e, 0x76, 0x31, 0x42, 0x09, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50,
|
|
||||||
0x01, 0x5a, 0x21, 0x6d, 0x73, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x67,
|
|
||||||
0x6f, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x3b, 0x75, 0x73,
|
|
||||||
0x65, 0x72, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x50, 0x55, 0x58, 0xaa, 0x02, 0x0d, 0x50, 0x72, 0x6f,
|
|
||||||
0x74, 0x6f, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x0d, 0x50, 0x72, 0x6f,
|
|
||||||
0x74, 0x6f, 0x5c, 0x55, 0x73, 0x65, 0x72, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x19, 0x50, 0x72, 0x6f,
|
|
||||||
0x74, 0x6f, 0x5c, 0x55, 0x73, 0x65, 0x72, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65,
|
|
||||||
0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x3a, 0x3a,
|
|
||||||
0x55, 0x73, 0x65, 0x72, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
file_user_v1_user_proto_rawDescOnce sync.Once
|
|
||||||
file_user_v1_user_proto_rawDescData = file_user_v1_user_proto_rawDesc
|
|
||||||
)
|
|
||||||
|
|
||||||
func file_user_v1_user_proto_rawDescGZIP() []byte {
|
|
||||||
file_user_v1_user_proto_rawDescOnce.Do(func() {
|
|
||||||
file_user_v1_user_proto_rawDescData = protoimpl.X.CompressGZIP(file_user_v1_user_proto_rawDescData)
|
|
||||||
})
|
|
||||||
return file_user_v1_user_proto_rawDescData
|
|
||||||
}
|
|
||||||
|
|
||||||
var file_user_v1_user_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
|
||||||
var file_user_v1_user_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
|
|
||||||
var file_user_v1_user_proto_goTypes = []interface{}{
|
|
||||||
(Role)(0), // 0: proto.user.v1.Role
|
|
||||||
(*CreateUserRequest)(nil), // 1: proto.user.v1.CreateUserRequest
|
|
||||||
(*CreateUserResponse)(nil), // 2: proto.user.v1.CreateUserResponse
|
|
||||||
(*CreateUserRequest_User)(nil), // 3: proto.user.v1.CreateUserRequest.User
|
|
||||||
(*timestamppb.Timestamp)(nil), // 4: google.protobuf.Timestamp
|
|
||||||
}
|
|
||||||
var file_user_v1_user_proto_depIdxs = []int32{
|
|
||||||
3, // 0: proto.user.v1.CreateUserRequest.user:type_name -> proto.user.v1.CreateUserRequest.User
|
|
||||||
4, // 1: proto.user.v1.CreateUserRequest.User.expires_at:type_name -> google.protobuf.Timestamp
|
|
||||||
0, // 2: proto.user.v1.CreateUserRequest.User.role:type_name -> proto.user.v1.Role
|
|
||||||
1, // 3: proto.user.v1.UserService.CreateUser:input_type -> proto.user.v1.CreateUserRequest
|
|
||||||
2, // 4: proto.user.v1.UserService.CreateUser:output_type -> proto.user.v1.CreateUserResponse
|
|
||||||
4, // [4:5] is the sub-list for method output_type
|
|
||||||
3, // [3:4] is the sub-list for method input_type
|
|
||||||
3, // [3:3] is the sub-list for extension type_name
|
|
||||||
3, // [3:3] is the sub-list for extension extendee
|
|
||||||
0, // [0:3] is the sub-list for field type_name
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() { file_user_v1_user_proto_init() }
|
|
||||||
func file_user_v1_user_proto_init() {
|
|
||||||
if File_user_v1_user_proto != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !protoimpl.UnsafeEnabled {
|
|
||||||
file_user_v1_user_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*CreateUserRequest); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_user_v1_user_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*CreateUserResponse); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_user_v1_user_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*CreateUserRequest_User); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file_user_v1_user_proto_msgTypes[2].OneofWrappers = []interface{}{}
|
|
||||||
type x struct{}
|
|
||||||
out := protoimpl.TypeBuilder{
|
|
||||||
File: protoimpl.DescBuilder{
|
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
|
||||||
RawDescriptor: file_user_v1_user_proto_rawDesc,
|
|
||||||
NumEnums: 1,
|
|
||||||
NumMessages: 3,
|
|
||||||
NumExtensions: 0,
|
|
||||||
NumServices: 1,
|
|
||||||
},
|
|
||||||
GoTypes: file_user_v1_user_proto_goTypes,
|
|
||||||
DependencyIndexes: file_user_v1_user_proto_depIdxs,
|
|
||||||
EnumInfos: file_user_v1_user_proto_enumTypes,
|
|
||||||
MessageInfos: file_user_v1_user_proto_msgTypes,
|
|
||||||
}.Build()
|
|
||||||
File_user_v1_user_proto = out.File
|
|
||||||
file_user_v1_user_proto_rawDesc = nil
|
|
||||||
file_user_v1_user_proto_goTypes = nil
|
|
||||||
file_user_v1_user_proto_depIdxs = nil
|
|
||||||
}
|
|
|
@ -1,105 +0,0 @@
|
||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
|
||||||
// versions:
|
|
||||||
// - protoc-gen-go-grpc v1.2.0
|
|
||||||
// - protoc (unknown)
|
|
||||||
// source: user/v1/user.proto
|
|
||||||
|
|
||||||
package userv1
|
|
||||||
|
|
||||||
import (
|
|
||||||
context "context"
|
|
||||||
grpc "google.golang.org/grpc"
|
|
||||||
codes "google.golang.org/grpc/codes"
|
|
||||||
status "google.golang.org/grpc/status"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
|
||||||
// is compatible with the grpc package it is being compiled against.
|
|
||||||
// Requires gRPC-Go v1.32.0 or later.
|
|
||||||
const _ = grpc.SupportPackageIsVersion7
|
|
||||||
|
|
||||||
// UserServiceClient is the client API for UserService service.
|
|
||||||
//
|
|
||||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
|
||||||
type UserServiceClient interface {
|
|
||||||
CreateUser(ctx context.Context, in *CreateUserRequest, opts ...grpc.CallOption) (*CreateUserResponse, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type userServiceClient struct {
|
|
||||||
cc grpc.ClientConnInterface
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewUserServiceClient(cc grpc.ClientConnInterface) UserServiceClient {
|
|
||||||
return &userServiceClient{cc}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *userServiceClient) CreateUser(ctx context.Context, in *CreateUserRequest, opts ...grpc.CallOption) (*CreateUserResponse, error) {
|
|
||||||
out := new(CreateUserResponse)
|
|
||||||
err := c.cc.Invoke(ctx, "/proto.user.v1.UserService/CreateUser", in, out, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserServiceServer is the server API for UserService service.
|
|
||||||
// All implementations must embed UnimplementedUserServiceServer
|
|
||||||
// for forward compatibility
|
|
||||||
type UserServiceServer interface {
|
|
||||||
CreateUser(context.Context, *CreateUserRequest) (*CreateUserResponse, error)
|
|
||||||
mustEmbedUnimplementedUserServiceServer()
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnimplementedUserServiceServer must be embedded to have forward compatible implementations.
|
|
||||||
type UnimplementedUserServiceServer struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (UnimplementedUserServiceServer) CreateUser(context.Context, *CreateUserRequest) (*CreateUserResponse, error) {
|
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method CreateUser not implemented")
|
|
||||||
}
|
|
||||||
func (UnimplementedUserServiceServer) mustEmbedUnimplementedUserServiceServer() {}
|
|
||||||
|
|
||||||
// UnsafeUserServiceServer may be embedded to opt out of forward compatibility for this service.
|
|
||||||
// Use of this interface is not recommended, as added methods to UserServiceServer will
|
|
||||||
// result in compilation errors.
|
|
||||||
type UnsafeUserServiceServer interface {
|
|
||||||
mustEmbedUnimplementedUserServiceServer()
|
|
||||||
}
|
|
||||||
|
|
||||||
func RegisterUserServiceServer(s grpc.ServiceRegistrar, srv UserServiceServer) {
|
|
||||||
s.RegisterService(&UserService_ServiceDesc, srv)
|
|
||||||
}
|
|
||||||
|
|
||||||
func _UserService_CreateUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
|
||||||
in := new(CreateUserRequest)
|
|
||||||
if err := dec(in); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if interceptor == nil {
|
|
||||||
return srv.(UserServiceServer).CreateUser(ctx, in)
|
|
||||||
}
|
|
||||||
info := &grpc.UnaryServerInfo{
|
|
||||||
Server: srv,
|
|
||||||
FullMethod: "/proto.user.v1.UserService/CreateUser",
|
|
||||||
}
|
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
|
||||||
return srv.(UserServiceServer).CreateUser(ctx, req.(*CreateUserRequest))
|
|
||||||
}
|
|
||||||
return interceptor(ctx, in, info, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UserService_ServiceDesc is the grpc.ServiceDesc for UserService service.
|
|
||||||
// It's only intended for direct use with grpc.RegisterService,
|
|
||||||
// and not to be introspected or modified (even as a copy)
|
|
||||||
var UserService_ServiceDesc = grpc.ServiceDesc{
|
|
||||||
ServiceName: "proto.user.v1.UserService",
|
|
||||||
HandlerType: (*UserServiceServer)(nil),
|
|
||||||
Methods: []grpc.MethodDesc{
|
|
||||||
{
|
|
||||||
MethodName: "CreateUser",
|
|
||||||
Handler: _UserService_CreateUser_Handler,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Streams: []grpc.StreamDesc{},
|
|
||||||
Metadata: "user/v1/user.proto",
|
|
||||||
}
|
|
62
proto/tester/v1/tester.proto
Normal file
62
proto/tester/v1/tester.proto
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package proto.tester.v1;
|
||||||
|
|
||||||
|
import "google/protobuf/timestamp.proto";
|
||||||
|
import "google/protobuf/empty.proto";
|
||||||
|
|
||||||
|
service TesterService {
|
||||||
|
rpc CreateProblem (CreateProblemRequest) returns (CreateProblemResponse);
|
||||||
|
rpc ReadProblem (ReadProblemRequest) returns (ReadProblemResponse);
|
||||||
|
rpc UpdateProblem (UpdateProblemRequest) returns (google.protobuf.Empty);
|
||||||
|
rpc DeleteProblem (DeleteProblemRequest) returns (google.protobuf.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
message CreateProblemRequest {
|
||||||
|
message Problem {
|
||||||
|
string name = 1;
|
||||||
|
string description = 2;
|
||||||
|
int32 time_limit = 3;
|
||||||
|
int32 memory_limit = 4;
|
||||||
|
}
|
||||||
|
string token = 1;
|
||||||
|
Problem problem = 2;
|
||||||
|
}
|
||||||
|
message CreateProblemResponse {
|
||||||
|
int32 id = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ReadProblemRequest {
|
||||||
|
string token = 1;
|
||||||
|
int32 id = 2;
|
||||||
|
}
|
||||||
|
message ReadProblemResponse {
|
||||||
|
message Problem {
|
||||||
|
int32 id = 1;
|
||||||
|
string name = 2;
|
||||||
|
string description = 3;
|
||||||
|
int32 time_limit = 4;
|
||||||
|
int32 memory_limit = 5;
|
||||||
|
google.protobuf.Timestamp created_at = 6;
|
||||||
|
google.protobuf.Timestamp updated_at = 7;
|
||||||
|
}
|
||||||
|
string token = 1;
|
||||||
|
Problem problem = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message UpdateProblemRequest {
|
||||||
|
message Problem {
|
||||||
|
int32 id = 1;
|
||||||
|
optional string name = 2;
|
||||||
|
optional string description = 3;
|
||||||
|
optional int32 time_limit = 4;
|
||||||
|
optional int32 memory_limit = 5;
|
||||||
|
}
|
||||||
|
string token = 1;
|
||||||
|
Problem problem = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DeleteProblemRequest {
|
||||||
|
string token = 1;
|
||||||
|
int32 id = 2;
|
||||||
|
}
|
|
@ -1,33 +0,0 @@
|
||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package proto.user.v1;
|
|
||||||
|
|
||||||
import "google/protobuf/timestamp.proto";
|
|
||||||
import "google/protobuf/empty.proto";
|
|
||||||
|
|
||||||
service UserService {
|
|
||||||
rpc CreateUser (CreateUserRequest) returns (CreateUserResponse);
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Role {
|
|
||||||
ROLE_SPECTATOR_UNSPECIFIED = 0;
|
|
||||||
ROLE_PARTICIPANT = 1;
|
|
||||||
ROLE_MODERATOR = 2;
|
|
||||||
ROLE_ADMIN = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message CreateUserRequest {
|
|
||||||
message User {
|
|
||||||
string username = 1;
|
|
||||||
string password = 2;
|
|
||||||
optional string email = 3;
|
|
||||||
optional google.protobuf.Timestamp expires_at = 4;
|
|
||||||
optional Role role = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
string token = 1;
|
|
||||||
User user = 2;
|
|
||||||
}
|
|
||||||
message CreateUserResponse {
|
|
||||||
int32 id = 1;
|
|
||||||
}
|
|
Loading…
Reference in a new issue