-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
release/38851105: Validation server side and docker-compose #2
base: develop
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# [Задача №00000000](https://bigbosop215.kaiten.ru/space/439413/card/00000000) | ||
|
||
### Что было не так: | ||
<описание проблемы/причины заведения новой фичи> | ||
### Что было сделано: | ||
* слой repository; | ||
* добавлена валидация на уникальность email; | ||
* ручка на получение подборок фильмов; | ||
* написаны тесты и моки. | ||
### Чек лист до ревью : | ||
- [ ] PR разбит на логические коммиты (если нет, то нужно разбить); | ||
- [ ] PR не содержит секретов (пароли, токены, ключи); | ||
- [ ] PR не содержит лишних файлов (например, `.env`); | ||
- [ ] PR не содержит коммитов, которые не относятся к задаче; | ||
|
||
**Перед тем, как отдать на ревью нужно убедиться, что все пункты выполнены** | ||
|
||
### как вливать ветку | ||
Если это обычная задача, то просто `squash merge` в `develop` | ||
Если это хотфикс, то обычный `merge` в `master` и `develop` (должно быть два `pull request`). При этом в ветке должен быть один коммит | ||
Если это релиз, то обычный `merge` и в `master` и в `develop`. Там будет несколько коммитов |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
version: '3' | ||
|
||
volumes: | ||
postgres_volume: | ||
redis: | ||
|
||
services: | ||
validation_ms: | ||
build: | ||
context: ./validation-service/ | ||
dockerfile: Dockerfile | ||
restart: always | ||
ports: | ||
- 5050:5050 | ||
networks: | ||
- netflix | ||
redis: | ||
image: 'redis:latest' | ||
command: redis-server | ||
ports: | ||
- '6379:6379' | ||
Starlexxx marked this conversation as resolved.
Show resolved
Hide resolved
|
||
volumes: | ||
- redis:/data | ||
networks: | ||
- netflix | ||
db: | ||
image: postgres:latest | ||
environment: | ||
- "POSTGRES_DB=netflix" | ||
- "POSTGRES_USER=test" | ||
- "POSTGRES_PASSWORD=test" | ||
ports: | ||
- "5432:5432" | ||
volumes: | ||
- "postgres_volume:/var/lib/postgresql/data" | ||
networks: | ||
- netflix | ||
|
||
|
||
networks: | ||
netflix: | ||
default: | ||
external: | ||
name: netflix |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,21 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"log" | ||
|
||
"github.com/go-park-mail-ru/2024_2_GOATS/validation-service/internal/app" | ||
) | ||
|
||
const serverPort = 5050 | ||
Starlexxx marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
func main() { | ||
|
||
ctx := context.Background() | ||
a, err := app.New(ctx, serverPort) | ||
|
||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
a.Run() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,16 @@ | ||
module github.com/go-park-mail-ru/2024_2_GOATS | ||
module github.com/go-park-mail-ru/2024_2_GOATS/validation-service | ||
|
||
go 1.22.2 | ||
|
||
require ( | ||
google.golang.org/grpc v1.65.0 | ||
google.golang.org/protobuf v1.34.2 | ||
) | ||
|
||
require ( | ||
golang.org/x/net v0.26.0 // indirect | ||
golang.org/x/sys v0.21.0 // indirect | ||
golang.org/x/text v0.16.0 // indirect | ||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect | ||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 // indirect | ||
google.golang.org/protobuf v1.34.2 // indirect | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,27 @@ | ||
package converter | ||
|
||
import ( | ||
"github.com/go-park-mail-ru/2024_2_GOATS/validation-service/internal/app/model" | ||
desc "github.com/go-park-mail-ru/2024_2_GOATS/validation-service/internal/pb/validation" | ||
"google.golang.org/protobuf/types/known/timestamppb" | ||
) | ||
|
||
func ToUserRegisterDataFromDesc(data *desc.ValidateRegistrationRequest) *model.UserRegisterData { | ||
birthday := data.GetBitrhdate().AsTime() | ||
ts := timestamppb.New(birthday) | ||
|
||
return &model.UserRegisterData{ | ||
Email: data.GetEmail(), | ||
Password: data.GetPassword(), | ||
PasswordConfirm: data.GetPasswordConfirm(), | ||
Sex: data.GetSex(), | ||
Birthday: int(ts.Seconds), | ||
} | ||
} | ||
|
||
func ToErrorsFromServ(data *model.ErrorResponse) *desc.ErrorMessage { | ||
return &desc.ErrorMessage{ | ||
Code: data.Code, | ||
Error: data.Error, | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,23 @@ | ||
package handler | ||
package validation | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/go-park-mail-ru/2024_2_GOATS/validation-service/internal/app/model" | ||
desc "github.com/go-park-mail-ru/2024_2_GOATS/validation-service/internal/pb/validation" | ||
) | ||
|
||
type ValidationService interface { | ||
ValidateRegistration(ctx context.Context, userData *model.UserRegisterData) *model.ValidationResponse | ||
} | ||
|
||
type Implementation struct { | ||
desc.UnimplementedValidationServer | ||
validationService ValidationService | ||
} | ||
|
||
func NewImplementation(validationService ValidationService) *Implementation { | ||
return &Implementation{ | ||
validationService: validationService, | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package validation | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/go-park-mail-ru/2024_2_GOATS/validation-service/internal/app/api/converter" | ||
desc "github.com/go-park-mail-ru/2024_2_GOATS/validation-service/internal/pb/validation" | ||
) | ||
|
||
func (i *Implementation) ValidateRegistration(ctx context.Context, req *desc.ValidateRegistrationRequest) (*desc.ValidationResponse, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Вот пока не знаю, как избавиться от контекста в аргументах функции. Типо это же из pb файла такой интерфейс |
||
validData := i.validationService.ValidateRegistration(ctx, converter.ToUserRegisterDataFromDesc(req)) | ||
descErrors := make([]*desc.ErrorMessage, 0) | ||
for _, errData := range validData.Errors { | ||
descErrors = append(descErrors, converter.ToErrorsFromServ(&errData)) | ||
} | ||
|
||
return &desc.ValidationResponse{ | ||
Success: validData.Success, | ||
Errors: descErrors, | ||
}, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,48 @@ | ||
package main | ||
package app | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"log" | ||
"net" | ||
|
||
"google.golang.org/grpc" | ||
"google.golang.org/grpc/reflection" | ||
|
||
validationAPI "github.com/go-park-mail-ru/2024_2_GOATS/validation-service/internal/app/api/validation" | ||
validationService "github.com/go-park-mail-ru/2024_2_GOATS/validation-service/internal/app/service/validation" | ||
desc "github.com/go-park-mail-ru/2024_2_GOATS/validation-service/internal/pb/validation" | ||
) | ||
|
||
type App struct { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. хочу видеть сущность конфиг, где будет listener, он из ямлика будет читать адрес и порт. Рут контекст будет обогощаться этим конфигом, потом вы из него сможете достать конфиг где угодно There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Что-то типо? type Config struct {
listenerAddress string `yaml:"listener_address"`
listenerPort int `yaml:"listener_port"`
}
type App struct {
serverPort int
validationService validationAPI.ValidationService
config Config
} В конструкторе App читаю конфиг из ямла и добавляю в контекст |
||
serverPort int | ||
validationService validationAPI.ValidationService | ||
} | ||
|
||
func New(ctx context.Context, serverPort int) (*App, error) { | ||
validationService := validationService.NewService() | ||
|
||
return &App{ | ||
serverPort: serverPort, | ||
validationService: validationService, | ||
}, nil | ||
} | ||
|
||
func (a *App) Run() { | ||
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", a.serverPort)) | ||
if err != nil { | ||
log.Fatal("Failed to listen: %v", err) | ||
} | ||
|
||
validationSrv := validationService.NewService() | ||
s := grpc.NewServer() | ||
reflection.Register(s) | ||
|
||
desc.RegisterValidationServer(s, validationAPI.NewImplementation(validationSrv)) | ||
|
||
log.Printf("Server listening at %v", lis.Addr()) | ||
|
||
if err = s.Serve(lis); err != nil { | ||
log.Fatalf("failed to serve: %v", err) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package errors | ||
|
||
var ( | ||
ErrInvalidEmailCode = "invalid_email" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. А почему не сделать обычные ошибки через errors.New |
||
ErrInvalidEmailText = "email is incorrect" | ||
ErrInvalidPasswordCode = "invalid_password" | ||
ErrInvalidPasswordText = "password is too short. The minimal len is 8" | ||
ErrInvalidSexCode = "invalid_sex" | ||
ErrInvalidSexText = "only male or female allowed" | ||
ErrInvalidBirthdateCode = "invalid_birthdate" | ||
ErrInvalidBirthdateText = "bithdate should be before current time" | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,19 @@ | ||
package model | ||
|
||
type UserRegisterData struct { | ||
Email string | ||
Password string | ||
PasswordConfirm string | ||
Sex string | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Даже если вы собираетесь поддерживать 50+ гендеров, как нетфликс, string это расточительство |
||
Birthday int | ||
Starlexxx marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
type ErrorResponse struct { | ||
Code string | ||
Error string | ||
} | ||
|
||
type ValidationResponse struct { | ||
Success bool | ||
Errors []ErrorResponse | ||
} |
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package helpers | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"regexp" | ||
"slices" | ||
"time" | ||
|
||
errVals "github.com/go-park-mail-ru/2024_2_GOATS/validation-service/internal/app/errors" | ||
"google.golang.org/protobuf/types/known/timestamppb" | ||
) | ||
|
||
var ( | ||
emailRegex = regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$") | ||
passwordLength = 8 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. кажется, это константа должна быть |
||
sexVals = []string{"male", "female"} | ||
) | ||
|
||
func ValidatePassword(pass, passConf string) error { | ||
if passConf == "" { | ||
log.Println("password confirm is missing, but now its OK") | ||
} | ||
|
||
if len(pass) < passwordLength { | ||
log.Println(errVals.ErrInvalidPasswordText) | ||
return fmt.Errorf(errVals.ErrInvalidPasswordText) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func ValidateEmail(email string) error { | ||
if !emailRegex.MatchString(email) { | ||
log.Println(errVals.ErrInvalidEmailText) | ||
return fmt.Errorf(errVals.ErrInvalidEmailText) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func ValidateBirthdate(birthdate int) error { | ||
ts := timestamppb.New(time.Now()) | ||
if int(ts.Seconds) < birthdate { | ||
log.Println(errVals.ErrInvalidBirthdateCode) | ||
return fmt.Errorf(errVals.ErrInvalidBirthdateText) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func ValidateSex(sex string) error { | ||
if !slices.Contains(sexVals, sex) { | ||
log.Println(errVals.ErrInvalidSexCode) | ||
return fmt.Errorf(errVals.ErrInvalidSexText) | ||
} | ||
|
||
return nil | ||
} |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deprecated