├── .dockerignore ├── .gitignore ├── pkg ├── common │ ├── adapter │ │ ├── protoutil │ │ │ ├── errors.go │ │ │ └── map.go │ │ ├── application │ │ │ ├── arguments.go │ │ │ ├── provider.go │ │ │ ├── provider_test.go │ │ │ └── application.go │ │ ├── auth │ │ │ ├── policy.csv │ │ │ ├── model.conf │ │ │ ├── public.key.pem │ │ │ ├── config.go │ │ │ ├── rights_enforcer.go │ │ │ ├── claims.go │ │ │ ├── role_enforcer.go │ │ │ ├── jwt_helper.go │ │ │ ├── private.key.pem │ │ │ ├── role_enforcer_test.go │ │ │ ├── session_manager.go │ │ │ └── jwt_helper_test.go │ │ ├── server │ │ │ └── grpc │ │ │ │ ├── config.go │ │ │ │ ├── mux_option │ │ │ │ └── marshaler.go │ │ │ │ ├── grpc_option │ │ │ │ ├── panic.go │ │ │ │ ├── validator.go │ │ │ │ ├── auth.go │ │ │ │ └── enforcer.go │ │ │ │ ├── method.go │ │ │ │ ├── errors.go │ │ │ │ └── server.go │ │ ├── validator │ │ │ ├── message.go │ │ │ ├── uint32.go │ │ │ ├── enum.go │ │ │ ├── float64.go │ │ │ ├── uint32_test.go │ │ │ ├── validator.go │ │ │ ├── list.go │ │ │ ├── enum_test.go │ │ │ ├── string.go │ │ │ ├── float64_test.go │ │ │ ├── datetime.go │ │ │ ├── datetime_test.go │ │ │ ├── validator_test.go │ │ │ └── string_test.go │ │ ├── ctxutil │ │ │ └── helper_funcs.go │ │ ├── constructors.go │ │ └── log │ │ │ └── logger.go │ ├── collection │ │ ├── map.go │ │ ├── iterator.go │ │ └── slice.go │ └── gen │ │ └── api │ │ └── proto │ │ └── v1 │ │ ├── header.pb.go │ │ ├── order_service_grpc.pb.go │ │ ├── product_service_grpc.pb.go │ │ ├── order_service.pb.gw.go │ │ ├── order_service.pb.go │ │ ├── common.pb.go │ │ ├── product_service.pb.gw.go │ │ ├── order.pb.go │ │ └── user_service_grpc.pb.go ├── product │ ├── domain │ │ └── service │ │ │ ├── errors.go │ │ │ └── product.go │ └── infra │ │ ├── constructors.go │ │ ├── form │ │ └── product.go │ │ ├── app │ │ └── server.go │ │ └── service │ │ └── product.go ├── order │ ├── domain │ │ └── service │ │ │ ├── errors.go │ │ │ └── order.go │ └── infra │ │ ├── constructors.go │ │ ├── form │ │ └── order.go │ │ ├── app │ │ └── server.go │ │ ├── middleware │ │ ├── order_rights_enforcer.go │ │ └── order_rights_enforcer_test.go │ │ └── service │ │ └── order.go └── user │ ├── domain │ └── service │ │ ├── errors.go │ │ ├── user.go │ │ └── user_product.go │ └── infra │ ├── form │ ├── user.go │ ├── order.go │ └── user_product.go │ ├── constructors.go │ ├── middleware │ ├── user_rights_enforcer.go │ ├── user_product_right_enforcer.go │ ├── user_rights_enforcer_test.go │ └── user_product_right_enforcer_test.go │ ├── service │ ├── user.go │ └── user_product.go │ └── app │ └── server.go ├── buf.yaml ├── deployments ├── Dockerfile ├── docker-compose.yml └── nginx.conf ├── configs ├── enforcer │ ├── model.conf │ └── policy.csv ├── ssl │ ├── public.key.pem │ ├── crt.pem │ └── private.key.pem └── config.yml ├── api └── proto │ └── v1 │ ├── common.proto │ ├── header.proto │ ├── product.proto │ ├── order_service.proto │ ├── order.proto │ ├── product_service.proto │ ├── user.proto │ └── user_service.proto ├── buf.gen.yaml ├── README.md ├── cmd ├── order-server │ └── main.go ├── product-server │ └── main.go └── user-server │ └── main.go ├── LICENSE ├── buf.lock ├── Makefile └── go.mod /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | .idea 3 | mock_* 4 | vendor/ -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | build/ 3 | vendor/ 4 | test.go -------------------------------------------------------------------------------- /pkg/common/adapter/protoutil/errors.go: -------------------------------------------------------------------------------- 1 | package protoutil 2 | 3 | import "github.com/pkg/errors" 4 | 5 | var ( 6 | ErrKeyNotFound = errors.New("Ключ не найден") 7 | ) 8 | -------------------------------------------------------------------------------- /pkg/product/domain/service/errors.go: -------------------------------------------------------------------------------- 1 | package productsrv 2 | 3 | import "github.com/pkg/errors" 4 | 5 | var ( 6 | ErrProductNotFound = errors.New("Товар не найден") 7 | ) 8 | -------------------------------------------------------------------------------- /pkg/common/adapter/application/arguments.go: -------------------------------------------------------------------------------- 1 | package application 2 | 3 | type Arguments struct { 4 | ConfigFilename string `short:"c" long:"config" description:"A path to config file" required:"true"` 5 | } 6 | -------------------------------------------------------------------------------- /pkg/order/domain/service/errors.go: -------------------------------------------------------------------------------- 1 | package ordersrv 2 | 3 | import "github.com/pkg/errors" 4 | 5 | var ( 6 | ErrOrderNotFound = errors.New("Заказ не найден") 7 | ErrOrderAmountNotEqual = errors.New("Неверная сумма заказа") 8 | ) 9 | -------------------------------------------------------------------------------- /buf.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | deps: 3 | - buf.build/googleapis/googleapis 4 | - buf.build/grpc/grpc 5 | - buf.build/grpc-ecosystem/grpc-gateway 6 | - buf.build/nvxx/protopatch 7 | breaking: 8 | use: 9 | - FILE 10 | lint: 11 | use: 12 | - DEFAULT -------------------------------------------------------------------------------- /pkg/product/infra/constructors.go: -------------------------------------------------------------------------------- 1 | package productsadap 2 | 3 | import ( 4 | productsrcimpl "github.com/byorty/enterprise-application/pkg/product/infra/service" 5 | "go.uber.org/fx" 6 | ) 7 | 8 | var Constructors = fx.Provide( 9 | productsrcimpl.NewFxProductService, 10 | ) 11 | -------------------------------------------------------------------------------- /pkg/common/adapter/auth/policy.csv: -------------------------------------------------------------------------------- 1 | p, USER_GROUP_GUEST, ROLE_USER, PERMISSION_READ 2 | p, USER_GROUP_GUEST, ROLE_USER, PERMISSION_WRITE 3 | 4 | p, USER_GROUP_CUSTOMER, ROLE_ORDER, PERMISSION_READ 5 | 6 | g, GUEST, USER_GROUP_GUEST 7 | g, CUSTOMER, USER_GROUP_GUEST 8 | g, CUSTOMER, USER_GROUP_CUSTOMER 9 | -------------------------------------------------------------------------------- /deployments/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:latest 2 | 3 | ARG BUILD_APP_NAME 4 | 5 | ENV PROJECT_DIR=/go 6 | 7 | RUN apk add tzdata 8 | 9 | COPY ./build/${BUILD_APP_NAME} ${PROJECT_DIR}/bin/app 10 | COPY ./configs ${PROJECT_DIR}/configs 11 | 12 | CMD ${PROJECT_DIR}/bin/app -c ${PROJECT_DIR}/configs/config.yml 13 | -------------------------------------------------------------------------------- /pkg/user/domain/service/errors.go: -------------------------------------------------------------------------------- 1 | package usersrv 2 | 3 | import "github.com/pkg/errors" 4 | 5 | var ( 6 | ErrUserNotFound = errors.New("Пользователь не найден") 7 | ErrUserAlreadyExists = errors.New("Пользователь уже существует") 8 | ErrUserProductNotFound = errors.New("Товары пользователя не найдены") 9 | ) 10 | -------------------------------------------------------------------------------- /pkg/user/infra/form/user.go: -------------------------------------------------------------------------------- 1 | package form 2 | 3 | import "github.com/byorty/enterprise-application/pkg/common/adapter/validator" 4 | 5 | var ( 6 | PhoneNumber = validator.Form{ 7 | "phone_number": validator.NewPhoneNumber(), 8 | } 9 | UserUUID = validator.Form{ 10 | "user_uuid": validator.NewUUID(), 11 | } 12 | ) 13 | -------------------------------------------------------------------------------- /configs/enforcer/model.conf: -------------------------------------------------------------------------------- 1 | [request_definition] 2 | r = group, role, perm 3 | 4 | [policy_definition] 5 | p = group, role, perm 6 | 7 | [role_definition] 8 | g = _, _ 9 | 10 | [policy_effect] 11 | e = some(where (p.eft == allow)) 12 | 13 | [matchers] 14 | m = g(r.group, p.group) \ 15 | && r.role == p.role \ 16 | && r.perm == p.perm -------------------------------------------------------------------------------- /pkg/common/adapter/auth/model.conf: -------------------------------------------------------------------------------- 1 | [request_definition] 2 | r = group, role, perm 3 | 4 | [policy_definition] 5 | p = group, role, perm 6 | 7 | [role_definition] 8 | g = _, _ 9 | 10 | [policy_effect] 11 | e = some(where (p.eft == allow)) 12 | 13 | [matchers] 14 | m = g(r.group, p.group) \ 15 | && r.role == p.role \ 16 | && r.perm == p.perm -------------------------------------------------------------------------------- /pkg/order/infra/constructors.go: -------------------------------------------------------------------------------- 1 | package orderadap 2 | 3 | import ( 4 | "github.com/byorty/enterprise-application/pkg/order/infra/middleware" 5 | ordersrvimpl "github.com/byorty/enterprise-application/pkg/order/infra/service" 6 | "go.uber.org/fx" 7 | ) 8 | 9 | var Constructors = fx.Provide( 10 | ordersrvimpl.NewFxOrderService, 11 | middleware.NewFxOrderRightsEnforcer, 12 | ) 13 | -------------------------------------------------------------------------------- /pkg/common/adapter/server/grpc/config.go: -------------------------------------------------------------------------------- 1 | package grpc 2 | 3 | type Config struct { 4 | Host string `yaml:"host"` 5 | GrpcPort int `yaml:"grpc_port"` 6 | HttpPort int `yaml:"http_port"` 7 | MaxSendMessageLength int `yaml:"max_send_message_length"` 8 | MaxReceiveMessageLength int `yaml:"max_receive_message_length"` 9 | } 10 | -------------------------------------------------------------------------------- /pkg/product/domain/service/product.go: -------------------------------------------------------------------------------- 1 | package productsrv 2 | 3 | import ( 4 | "context" 5 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 6 | ) 7 | 8 | type ProductService interface { 9 | GetAllByFilter(ctx context.Context, params *pbv1.ProductsRequestFilter, paginator *pbv1.Paginator) ([]*pbv1.Product, uint32, error) 10 | GetByUUID(ctx context.Context, uuid string) (*pbv1.Product, error) 11 | } 12 | -------------------------------------------------------------------------------- /pkg/user/domain/service/user.go: -------------------------------------------------------------------------------- 1 | package usersrv 2 | 3 | import ( 4 | "context" 5 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 6 | ) 7 | 8 | type UserService interface { 9 | Register(ctx context.Context, phoneNumber string) (*pbv1.TokenResponse, error) 10 | Authorize(ctx context.Context, phoneNumber string) (*pbv1.TokenResponse, error) 11 | GetByUUID(ctx context.Context, uuid string) (*pbv1.User, error) 12 | } 13 | -------------------------------------------------------------------------------- /pkg/user/infra/constructors.go: -------------------------------------------------------------------------------- 1 | package useradap 2 | 3 | import ( 4 | "github.com/byorty/enterprise-application/pkg/user/infra/middleware" 5 | usersrvimpl "github.com/byorty/enterprise-application/pkg/user/infra/service" 6 | "go.uber.org/fx" 7 | ) 8 | 9 | var Constructors = fx.Provide( 10 | usersrvimpl.NewFxUserService, 11 | usersrvimpl.NewFxUserProductService, 12 | middleware.NewFxUserRightsEnforcer, 13 | middleware.NewFxUserProductRightsEnforcer, 14 | ) 15 | -------------------------------------------------------------------------------- /pkg/common/adapter/validator/message.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "context" 5 | "google.golang.org/protobuf/reflect/protoreflect" 6 | ) 7 | 8 | func NewMessage(form Form) Validator { 9 | return &messageValidator{ 10 | form: form, 11 | } 12 | } 13 | 14 | type messageValidator struct { 15 | form Form 16 | } 17 | 18 | func (v messageValidator) Validate(ctx context.Context, value protoreflect.Value) error { 19 | return v.form.Validate(ctx, value.Message()) 20 | } 21 | -------------------------------------------------------------------------------- /pkg/order/infra/form/order.go: -------------------------------------------------------------------------------- 1 | package form 2 | 3 | import ( 4 | "github.com/byorty/enterprise-application/pkg/common/adapter/validator" 5 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 6 | ) 7 | 8 | var ( 9 | Checkout = validator.Form{ 10 | "order_uuid": validator.NewUUID(), 11 | "params": validator.NewMessage(validator.Form{ 12 | "amount": validator.NewFloat64Gt(0), 13 | "status": validator.NewEnum(pbv1.OrderStatus_name), 14 | }), 15 | } 16 | ) 17 | -------------------------------------------------------------------------------- /api/proto/v1/common.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pb.v1; 4 | 5 | option go_package = "github.com/byorty/enterprise-application/pkg/common/gen/pbv1"; 6 | 7 | message Paginator { 8 | uint32 offset = 1; 9 | uint32 limit = 2; 10 | } 11 | 12 | message UserProduct { 13 | string uuid = 1; 14 | string product_uuid = 2; 15 | uint32 count = 3; 16 | } 17 | 18 | message Error { 19 | uint32 code = 1; 20 | string message = 2; 21 | map details = 3; 22 | } -------------------------------------------------------------------------------- /configs/ssl/public.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5XA9psvNPu/my+Hv4nPF 3 | 8ESoJ2hufkylgxh5yZulxg9YcNMNpryob1ew0klEyBW7Vmkc+YHmGooNcSpjxtUZ 4 | z/BZY4YJ4a4HRaddQL/ZO5nFHqHLe81PhgBOx3WAlp0ogxHrhhcTX1yw6hT9nXsm 5 | e6jyYDquzrxHN/6V/61xjJI/SUk0+YJnUUgfqqcfpicyBu4Q1YxbX8XyUTHhPhHK 6 | a318r02FYKdAlrl0m6dPRbPnhO9JogiQ0jx4Ds032DXF36fxInIiFPIxhxHKNW1i 7 | ICEfex9sJalZf3+fGNlxtzQtthVD5LvobVwDWPVZuk4uKa+KCiLh8yMeFWtSWgZ7 8 | DQIDAQAB 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /pkg/order/domain/service/order.go: -------------------------------------------------------------------------------- 1 | package ordersrv 2 | 3 | import ( 4 | "context" 5 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 6 | ) 7 | 8 | type OrderService interface { 9 | Create(ctx context.Context, userUUID string, params *pbv1.CreateOrderRequestParams) (*pbv1.Order, error) 10 | Checkout(ctx context.Context, orderUUID string, params *pbv1.CheckoutOrderRequestParams) (*pbv1.Order, error) 11 | GetByUUID(ctx context.Context, orderUUID string) (*pbv1.Order, error) 12 | } 13 | -------------------------------------------------------------------------------- /pkg/common/adapter/auth/public.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5XA9psvNPu/my+Hv4nPF 3 | 8ESoJ2hufkylgxh5yZulxg9YcNMNpryob1ew0klEyBW7Vmkc+YHmGooNcSpjxtUZ 4 | z/BZY4YJ4a4HRaddQL/ZO5nFHqHLe81PhgBOx3WAlp0ogxHrhhcTX1yw6hT9nXsm 5 | e6jyYDquzrxHN/6V/61xjJI/SUk0+YJnUUgfqqcfpicyBu4Q1YxbX8XyUTHhPhHK 6 | a318r02FYKdAlrl0m6dPRbPnhO9JogiQ0jx4Ds032DXF36fxInIiFPIxhxHKNW1i 7 | ICEfex9sJalZf3+fGNlxtzQtthVD5LvobVwDWPVZuk4uKa+KCiLh8yMeFWtSWgZ7 8 | DQIDAQAB 9 | -----END PUBLIC KEY----- 10 | -------------------------------------------------------------------------------- /configs/enforcer/policy.csv: -------------------------------------------------------------------------------- 1 | p, USER_GROUP_GUEST, ROLE_USER, PERMISSION_WRITE 2 | p, USER_GROUP_GUEST, ROLE_PRODUCT, PERMISSION_READ 3 | 4 | p, USER_GROUP_CUSTOMER, ROLE_USER, PERMISSION_READ 5 | p, USER_GROUP_CUSTOMER, ROLE_ORDER, PERMISSION_READ 6 | p, USER_GROUP_CUSTOMER, ROLE_ORDER, PERMISSION_WRITE 7 | p, USER_GROUP_CUSTOMER, ROLE_USER_PRODUCT, PERMISSION_READ 8 | p, USER_GROUP_CUSTOMER, ROLE_USER_PRODUCT, PERMISSION_WRITE 9 | 10 | g, GUEST, USER_GROUP_GUEST 11 | g, CUSTOMER, USER_GROUP_GUEST 12 | g, CUSTOMER, USER_GROUP_CUSTOMER 13 | -------------------------------------------------------------------------------- /pkg/common/adapter/auth/config.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import "time" 4 | 5 | type RoleEnforcerConfig struct { 6 | ModelFile string `yaml:"model_file"` 7 | PolicyFile string `yaml:"policy_file"` 8 | } 9 | 10 | type SslConfig struct { 11 | CertFile string `yaml:"cert_file"` 12 | PrivateKeyFile string `yaml:"private_key_file"` 13 | PublicKeyFile string `yaml:"public_key_file"` 14 | } 15 | 16 | type SessionConfig struct { 17 | Audience string `yaml:"audience"` 18 | Issuer string `yaml:"issuer"` 19 | Duration time.Duration `yaml:"duration"` 20 | } 21 | -------------------------------------------------------------------------------- /pkg/user/domain/service/user_product.go: -------------------------------------------------------------------------------- 1 | package usersrv 2 | 3 | import ( 4 | "context" 5 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 6 | ) 7 | 8 | type UserProductService interface { 9 | GetAllByFilter(ctx context.Context, params pbv1.GetUserProductRequestParams) ([]*pbv1.UserProduct, error) 10 | Put(ctx context.Context, userUUID string, params *pbv1.PutProductRequestParams) ([]*pbv1.UserProduct, error) 11 | Change(ctx context.Context, userUUID string, userProductUUID string, params *pbv1.ChangeProductRequestParams) ([]*pbv1.UserProduct, error) 12 | } 13 | -------------------------------------------------------------------------------- /configs/config.yml: -------------------------------------------------------------------------------- 1 | server: 2 | http_port: 8080 3 | grpc_port: 8181 4 | max_send_message_length: 2147483647 5 | max_receive_message_length: 63554432 6 | 7 | enforcer: 8 | model_file: ${PROJECT_DIR}/configs/enforcer/model.conf 9 | policy_file: ${PROJECT_DIR}/configs/enforcer/policy.csv 10 | 11 | ssl: 12 | cert_file: ${PROJECT_DIR}/configs/ssl/crt.pem 13 | private_key_file: ${PROJECT_DIR}/configs/ssl/private.key.pem 14 | public_key_file: ${PROJECT_DIR}/configs/ssl/public.key.pem 15 | 16 | session: 17 | audience: Enterprise Application 18 | issuer: Solomonov 19 | duration: 168h -------------------------------------------------------------------------------- /pkg/user/infra/form/order.go: -------------------------------------------------------------------------------- 1 | package form 2 | 3 | import "github.com/byorty/enterprise-application/pkg/common/adapter/validator" 4 | 5 | var ( 6 | CreateOrder = validator.Form{ 7 | "user_uuid": validator.NewUUID(), 8 | "params": validator.NewMessage(validator.Form{ 9 | "products": validator.NewReqList( 10 | validator.NewMessage(validator.Form{ 11 | "product_uuid": validator.NewUUID(), 12 | "count": minProductCountValidator, 13 | }), 14 | ), 15 | "address": validator.NewStringWithMaxLen(255), 16 | "delivered_at": validator.NewDeliveredAt(), 17 | }), 18 | } 19 | ) 20 | -------------------------------------------------------------------------------- /buf.gen.yaml: -------------------------------------------------------------------------------- 1 | version: v1 2 | plugins: 3 | - name: go-patch 4 | out: pkg/common/gen 5 | opt: 6 | - paths=source_relative 7 | - plugin=go 8 | - name: go-patch 9 | out: pkg/common/gen 10 | opt: 11 | - paths=source_relative 12 | - plugin=go-grpc 13 | - require_unimplemented_servers=false 14 | - name: grpc-gateway 15 | out: pkg/common/gen 16 | opt: 17 | - paths=source_relative 18 | - name: openapiv2 19 | out: api/openapi-spec 20 | opt: 21 | - output_format=yaml 22 | - allow_merge=true 23 | - merge_file_name=api 24 | - json_names_for_fields=false 25 | - openapi_naming_strategy=simple -------------------------------------------------------------------------------- /pkg/common/adapter/validator/uint32.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "google.golang.org/protobuf/reflect/protoreflect" 7 | ) 8 | 9 | func NewUint32(condition string) Validator { 10 | return &uint32Validator{ 11 | condition: condition, 12 | } 13 | } 14 | 15 | func NewUint32Min(min uint32) Validator { 16 | return NewUint32(fmt.Sprintf("gte=%d", min)) 17 | } 18 | 19 | type uint32Validator struct { 20 | condition string 21 | } 22 | 23 | func (u uint32Validator) Validate(ctx context.Context, value protoreflect.Value) error { 24 | return validate.VarCtx(ctx, value.Uint(), u.condition) 25 | } 26 | -------------------------------------------------------------------------------- /pkg/common/adapter/auth/rights_enforcer.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "context" 5 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 6 | "go.uber.org/fx" 7 | "google.golang.org/protobuf/reflect/protoreflect" 8 | ) 9 | 10 | type RightsEnforcer interface { 11 | Enforce(ctx context.Context, session pbv1.Session, value protoreflect.Value) (context.Context, error) 12 | } 13 | 14 | type RightsEnforcerDescriptorOut struct { 15 | fx.Out 16 | Descriptor RightsEnforcerDescriptor `group:"rights_enforcer"` 17 | } 18 | 19 | type RightsEnforcerDescriptor struct { 20 | Name string 21 | RightsEnforcer RightsEnforcer 22 | } 23 | -------------------------------------------------------------------------------- /pkg/common/adapter/auth/claims.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 5 | "github.com/dgrijalva/jwt-go" 6 | "github.com/pkg/errors" 7 | ) 8 | 9 | type SessionClaims struct { 10 | jwt.StandardClaims 11 | pbv1.Session 12 | } 13 | 14 | func (c SessionClaims) Valid() error { 15 | err := c.StandardClaims.Valid() 16 | if err != nil { 17 | return err 18 | } 19 | 20 | if len(c.Uuid) == 0 { 21 | return errors.New("uuid is invalid") 22 | } 23 | 24 | if _, ok := pbv1.UserGroup_name[int32(c.Group)]; !ok { 25 | return errors.New("group is invalid") 26 | } 27 | 28 | return nil 29 | } 30 | -------------------------------------------------------------------------------- /pkg/common/adapter/validator/enum.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "context" 5 | "google.golang.org/protobuf/reflect/protoreflect" 6 | ) 7 | 8 | func NewEnum(values map[int32]string) Validator { 9 | return &enumValidator{ 10 | values: values, 11 | } 12 | } 13 | 14 | type enumValidator struct { 15 | values map[int32]string 16 | } 17 | 18 | func (e enumValidator) Validate(ctx context.Context, value protoreflect.Value) error { 19 | enumValue := int32(value.Enum()) 20 | err := validate.VarCtx(ctx, enumValue, "gt=0") 21 | if err != nil { 22 | return err 23 | } 24 | 25 | _, ok := e.values[enumValue] 26 | return validate.VarCtx(ctx, ok, "eq=true") 27 | } 28 | -------------------------------------------------------------------------------- /pkg/common/adapter/ctxutil/helper_funcs.go: -------------------------------------------------------------------------------- 1 | package ctxutil 2 | 3 | import ( 4 | "context" 5 | "github.com/pkg/errors" 6 | ) 7 | 8 | const ( 9 | Session = "session" 10 | User = "user" 11 | UserProduct = "user_product" 12 | Order = "order" 13 | ) 14 | 15 | var ( 16 | ErrNotFound = errors.Errorf("Контекст не содержит ключ") 17 | ) 18 | 19 | func Set(ctx context.Context, key string, value interface{}) context.Context { 20 | return context.WithValue(ctx, key, value) 21 | } 22 | 23 | func Get[T any](ctx context.Context, key string) (T, error) { 24 | v, ok := ctx.Value(key).(T) 25 | if !ok { 26 | return v, ErrNotFound 27 | } 28 | 29 | return v, nil 30 | } 31 | -------------------------------------------------------------------------------- /pkg/common/adapter/server/grpc/mux_option/marshaler.go: -------------------------------------------------------------------------------- 1 | package mux_option 2 | 3 | import ( 4 | "github.com/byorty/enterprise-application/pkg/common/adapter/server/grpc" 5 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 6 | "google.golang.org/protobuf/encoding/protojson" 7 | ) 8 | 9 | func NewFxMarshalerOption() grpc.MiddlewareOut { 10 | return grpc.MiddlewareOut{ 11 | MuxMiddleware: grpc.Middleware{ 12 | MuxOption: runtime.WithMarshalerOption(runtime.MIMEWildcard, &runtime.JSONPb{ 13 | MarshalOptions: protojson.MarshalOptions{ 14 | UseProtoNames: true, 15 | EmitUnpopulated: true, 16 | }, 17 | UnmarshalOptions: protojson.UnmarshalOptions{}, 18 | }), 19 | }, 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /pkg/user/infra/form/user_product.go: -------------------------------------------------------------------------------- 1 | package form 2 | 3 | import "github.com/byorty/enterprise-application/pkg/common/adapter/validator" 4 | 5 | var ( 6 | minProductCountValidator = validator.NewUint32Min(1) 7 | PutProduct = validator.Form{ 8 | "user_uuid": validator.NewUUID(), 9 | "params": validator.NewMessage(validator.Form{ 10 | "product_uuid": validator.NewUUID(), 11 | "product_count": minProductCountValidator, 12 | }), 13 | } 14 | ChangeProduct = validator.Form{ 15 | "user_uuid": validator.NewUUID(), 16 | "user_product_uuid": validator.NewUUID(), 17 | "params": validator.NewMessage(validator.Form{ 18 | "count": minProductCountValidator, 19 | }), 20 | } 21 | ) 22 | -------------------------------------------------------------------------------- /pkg/common/adapter/validator/float64.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "google.golang.org/protobuf/reflect/protoreflect" 7 | ) 8 | 9 | func NewFloat64(condition string) Validator { 10 | return &float64Validator{ 11 | condition: condition, 12 | } 13 | } 14 | 15 | func NewFloat64Gt(min float64) Validator { 16 | return NewFloat64(fmt.Sprintf("gt=%f", min)) 17 | } 18 | 19 | func NewFloat64Lt(max float64) Validator { 20 | return NewFloat64(fmt.Sprintf("lt=%f", max)) 21 | } 22 | 23 | type float64Validator struct { 24 | condition string 25 | } 26 | 27 | func (f float64Validator) Validate(ctx context.Context, value protoreflect.Value) error { 28 | return validate.VarCtx(ctx, value.Float(), f.condition) 29 | } 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Enterprise Application 2 | 3 | Пример микросервисного приложения на GRPC и DDD. 4 | 5 | ## Зависимости 6 | 7 | 1. [protoc](https://grpc.io/docs/protoc-installation/) 8 | 2. [docker](https://www.docker.com) 9 | 3. [golang](https://go.dev) 10 | 4. [buf](http://buf.build) 11 | 5. [make](https://ru.wikipedia.org/wiki/Make) 12 | 13 | ## Установка 14 | 15 | ```shell 16 | make install # установка плагинов для сборки proto 17 | make vendor # скачивания зависимостей для проекта 18 | make buf_update # скачивание зависимостей для сборки proto 19 | make buf_generate # генерация golang-файлов из proto-файлов 20 | ``` 21 | 22 | ## Использование 23 | 24 | ```shell 25 | make up # запуск микросервисов 26 | make down # остановка микросервисов 27 | ``` -------------------------------------------------------------------------------- /pkg/common/adapter/server/grpc/grpc_option/panic.go: -------------------------------------------------------------------------------- 1 | package grpc_option 2 | 3 | import ( 4 | "context" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/server/grpc" 6 | gRPC "google.golang.org/grpc" 7 | ) 8 | 9 | func NewFxPanicOption() grpc.MiddlewareOut { 10 | return grpc.MiddlewareOut{ 11 | GrpcMiddleware: grpc.Middleware{ 12 | Priority: int(^uint32(0) >> 1), 13 | GrpcOption: func(ctx context.Context, req interface{}, info *gRPC.UnaryServerInfo, handler gRPC.UnaryHandler) (resp interface{}, err error) { 14 | defer func() { 15 | if r := recover(); r != nil { 16 | err = grpc.ErrInternal(err) 17 | } 18 | }() 19 | 20 | resp, err = handler(ctx, req) 21 | return resp, err 22 | }, 23 | }, 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /pkg/product/infra/form/product.go: -------------------------------------------------------------------------------- 1 | package form 2 | 3 | import "github.com/byorty/enterprise-application/pkg/common/adapter/validator" 4 | 5 | var ( 6 | ProductUUID = validator.Form{ 7 | "product_uuid": validator.NewUUID(), 8 | } 9 | Products = validator.Form{ 10 | "filter": validator.NewMessage(validator.Form{ 11 | "uuid_in": validator.NewOptList(validator.NewUUID()), 12 | "name_contains": validator.NewAlphanumeric(), 13 | "price_gt": validator.NewFloat64Gt(0), 14 | "price_lt": validator.NewFloat64Lt(1000000), 15 | "properties_eq": validator.NewOptList( 16 | validator.NewMessage(validator.Form{ 17 | "name": validator.NewAlphanumeric(), 18 | "value": validator.NewAlphanumeric(), 19 | }), 20 | ), 21 | }), 22 | } 23 | ) 24 | -------------------------------------------------------------------------------- /pkg/common/adapter/validator/uint32_test.go: -------------------------------------------------------------------------------- 1 | package validator_test 2 | 3 | import ( 4 | "context" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/validator" 6 | "github.com/stretchr/testify/suite" 7 | "google.golang.org/protobuf/reflect/protoreflect" 8 | "testing" 9 | ) 10 | 11 | func TestUint32ValidatorSuite(t *testing.T) { 12 | suite.Run(t, new(Uint32ValidatorSuite)) 13 | } 14 | 15 | type Uint32ValidatorSuite struct { 16 | suite.Suite 17 | } 18 | 19 | func (s *Uint32ValidatorSuite) TestMin() { 20 | v := validator.NewUint32Min(10) 21 | s.NotNil(v.Validate(context.Background(), protoreflect.ValueOf(uint32(0)))) 22 | s.Nil(v.Validate(context.Background(), protoreflect.ValueOf(uint32(10)))) 23 | s.Nil(v.Validate(context.Background(), protoreflect.ValueOf(uint32(15)))) 24 | } 25 | -------------------------------------------------------------------------------- /api/proto/v1/header.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pb.v1; 4 | 5 | import "protoc-gen-openapiv2/options/annotations.proto"; 6 | 7 | option go_package = "github.com/byorty/enterprise-application/pkg/common/gen/pbv1"; 8 | option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { 9 | info: { 10 | title: "Enterprise Application API"; 11 | version: "1.0"; 12 | }; 13 | schemes: HTTPS; 14 | security_definitions: { 15 | security: { 16 | key: "Bearer" 17 | value: { 18 | type: TYPE_API_KEY; 19 | in: IN_HEADER; 20 | name: "Authorization" 21 | } 22 | }; 23 | }; 24 | host: "enterprise.application.local"; 25 | consumes: "application/json"; 26 | produces: "application/json"; 27 | }; -------------------------------------------------------------------------------- /pkg/common/adapter/validator/validator.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "context" 5 | "github.com/go-playground/validator/v10" 6 | "google.golang.org/protobuf/reflect/protoreflect" 7 | ) 8 | 9 | var ( 10 | validate = validator.New() 11 | ) 12 | 13 | type Validator interface { 14 | Validate(ctx context.Context, value protoreflect.Value) error 15 | } 16 | 17 | type Form map[string]Validator 18 | 19 | func (f Form) Validate(ctx context.Context, message protoreflect.Message) error { 20 | fields := message.Descriptor().Fields() 21 | for i := 0; i < fields.Len(); i++ { 22 | field := fields.Get(i) 23 | v, ok := f[string(field.Name())] 24 | if !ok { 25 | continue 26 | } 27 | 28 | err := v.Validate(ctx, message.Get(field)) 29 | if err != nil { 30 | return err 31 | } 32 | } 33 | 34 | return nil 35 | } 36 | -------------------------------------------------------------------------------- /pkg/common/adapter/validator/list.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "context" 5 | "google.golang.org/protobuf/reflect/protoreflect" 6 | ) 7 | 8 | func NewReqList(v Validator) Validator { 9 | return &listValidator{ 10 | validator: v, 11 | required: true, 12 | } 13 | } 14 | 15 | func NewOptList(v Validator) Validator { 16 | return &listValidator{ 17 | validator: v, 18 | } 19 | } 20 | 21 | type listValidator struct { 22 | validator Validator 23 | required bool 24 | } 25 | 26 | func (v listValidator) Validate(ctx context.Context, value protoreflect.Value) error { 27 | list := value.List() 28 | if v.required { 29 | err := validate.VarCtx(ctx, list.Len(), "gt=0") 30 | if err != nil { 31 | return err 32 | } 33 | } 34 | 35 | for i := 0; i < list.Len(); i++ { 36 | err := v.validator.Validate(ctx, list.Get(i)) 37 | if err != nil { 38 | return err 39 | } 40 | } 41 | 42 | return nil 43 | } 44 | -------------------------------------------------------------------------------- /pkg/common/adapter/protoutil/map.go: -------------------------------------------------------------------------------- 1 | package protoutil 2 | 3 | import ( 4 | "fmt" 5 | "github.com/byorty/enterprise-application/pkg/common/collection" 6 | "google.golang.org/protobuf/reflect/protoreflect" 7 | ) 8 | 9 | func NewMap[T any]() *Map[T] { 10 | return &Map[T]{ 11 | m: collection.NewMap[string, T](), 12 | } 13 | } 14 | 15 | type Map[T any] struct { 16 | m collection.Map[string, T] 17 | } 18 | 19 | func (m *Map[T]) Set(key string, value T) { 20 | m.m.Set(key, value) 21 | } 22 | 23 | func (m Map[T]) Get(message protoreflect.Message, field protoreflect.FieldDescriptor) (T, error) { 24 | messageName := message.Descriptor().Name() 25 | fieldName := field.Name() 26 | value, ok := m.m.Get(fmt.Sprintf("%s.%s", messageName, fieldName)) 27 | if ok { 28 | return value, nil 29 | } 30 | 31 | value, ok = m.m.Get(string(fieldName)) 32 | if ok { 33 | return value, nil 34 | } 35 | 36 | return value, ErrKeyNotFound 37 | } 38 | -------------------------------------------------------------------------------- /pkg/common/adapter/validator/enum_test.go: -------------------------------------------------------------------------------- 1 | package validator_test 2 | 3 | import ( 4 | "context" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/validator" 6 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 7 | "github.com/stretchr/testify/suite" 8 | "google.golang.org/protobuf/reflect/protoreflect" 9 | "testing" 10 | ) 11 | 12 | func TestEnumValidatorSuite(t *testing.T) { 13 | suite.Run(t, new(EnumValidatorSuite)) 14 | } 15 | 16 | type EnumValidatorSuite struct { 17 | suite.Suite 18 | } 19 | 20 | func (s *EnumValidatorSuite) TestEnum() { 21 | v := validator.NewEnum(pbv1.UserGroup_name) 22 | s.NotNil(v.Validate(context.Background(), protoreflect.ValueOf(pbv1.UserGroupGuest.Number()))) 23 | s.NotNil(v.Validate(context.Background(), protoreflect.ValueOf(pbv1.UserGroup(9999).Number()))) 24 | s.Nil(v.Validate(context.Background(), protoreflect.ValueOf(pbv1.UserGroupCustomer.Number()))) 25 | } 26 | -------------------------------------------------------------------------------- /api/proto/v1/product.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pb.v1; 4 | 5 | option go_package = "github.com/byorty/enterprise-application/pkg/common/gen/pbv1"; 6 | 7 | import "patch/go.proto"; 8 | import "google/protobuf/timestamp.proto"; 9 | 10 | enum ProductStatus { 11 | PRODUCT_STATUS_UNSPECIFIED = 0 [(go.value) = { 12 | name: "ProductStatusUnspecified" 13 | }]; 14 | PRODUCT_STATUS_ACTIVE = 1 [(go.value) = { 15 | name: "ProductStatusActive" 16 | }]; 17 | PRODUCT_STATUS_ARCHIVED = 2 [(go.value) = { 18 | name: "ProductStatusArchived" 19 | }]; 20 | } 21 | 22 | message ProductProperty { 23 | string name = 1; 24 | string value = 2; 25 | } 26 | 27 | message Product { 28 | string uuid = 1; 29 | ProductStatus status = 2; 30 | string name = 3; 31 | double price = 4; 32 | bool availability = 5; 33 | repeated ProductProperty properties = 6; 34 | google.protobuf.Timestamp created_at = 7; 35 | } -------------------------------------------------------------------------------- /pkg/common/adapter/validator/string.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "google.golang.org/protobuf/reflect/protoreflect" 7 | ) 8 | 9 | func NewString(condition string) Validator { 10 | return &stringValidator{ 11 | condition: condition, 12 | } 13 | } 14 | 15 | func NewUUID() Validator { 16 | return NewString("uuid4") 17 | } 18 | 19 | func NewPhoneNumber() Validator { 20 | return NewString("e164") 21 | } 22 | 23 | func NewStringWithMaxLen(l int) Validator { 24 | return NewString(fmt.Sprintf("required,max=%d", l)) 25 | } 26 | 27 | func NewReqString() Validator { 28 | return NewString("required") 29 | } 30 | 31 | func NewAlphanumeric() Validator { 32 | return NewString("alphanum") 33 | } 34 | 35 | type stringValidator struct { 36 | condition string 37 | } 38 | 39 | func (v stringValidator) Validate(ctx context.Context, value protoreflect.Value) error { 40 | return validate.VarCtx(ctx, value.String(), v.condition) 41 | } 42 | -------------------------------------------------------------------------------- /api/proto/v1/order_service.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pb.v1; 4 | 5 | option go_package = "github.com/byorty/enterprise-application/pkg/common/gen/pbv1"; 6 | 7 | import "google/api/annotations.proto"; 8 | import "protoc-gen-openapiv2/options/annotations.proto"; 9 | import "api/proto/v1/common.proto"; 10 | import "api/proto/v1/order.proto"; 11 | 12 | service OrderService { 13 | rpc Checkout(CheckoutOrderRequest) returns (Order) { 14 | option (google.api.http) = { 15 | post: "/v1/orders/{order_uuid}"; 16 | body: "params"; 17 | }; 18 | option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { 19 | summary: "Оплата заказа"; 20 | }; 21 | }; 22 | } 23 | 24 | message CheckoutOrderRequest { 25 | string order_uuid = 1; 26 | CheckoutOrderRequestParams params = 2; 27 | } 28 | 29 | message CheckoutOrderRequestParams { 30 | double amount = 1; 31 | OrderStatus status = 2; 32 | } -------------------------------------------------------------------------------- /pkg/common/adapter/validator/float64_test.go: -------------------------------------------------------------------------------- 1 | package validator_test 2 | 3 | import ( 4 | "context" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/validator" 6 | "github.com/stretchr/testify/suite" 7 | "google.golang.org/protobuf/reflect/protoreflect" 8 | "testing" 9 | ) 10 | 11 | func TestFloat64ValidatorSuite(t *testing.T) { 12 | suite.Run(t, new(Float64ValidatorSuite)) 13 | } 14 | 15 | type Float64ValidatorSuite struct { 16 | suite.Suite 17 | } 18 | 19 | func (s *Float64ValidatorSuite) TestGt() { 20 | v := validator.NewFloat64Gt(10) 21 | s.NotNil(v.Validate(context.Background(), protoreflect.ValueOf(float64(0)))) 22 | s.Nil(v.Validate(context.Background(), protoreflect.ValueOf(float64(11)))) 23 | } 24 | 25 | func (s *Float64ValidatorSuite) TestLt() { 26 | v := validator.NewFloat64Lt(10) 27 | s.NotNil(v.Validate(context.Background(), protoreflect.ValueOf(float64(11)))) 28 | s.Nil(v.Validate(context.Background(), protoreflect.ValueOf(float64(9)))) 29 | } 30 | -------------------------------------------------------------------------------- /pkg/common/adapter/constructors.go: -------------------------------------------------------------------------------- 1 | package commonadap 2 | 3 | import ( 4 | "github.com/byorty/enterprise-application/pkg/common/adapter/application" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/auth" 6 | "github.com/byorty/enterprise-application/pkg/common/adapter/log" 7 | "github.com/byorty/enterprise-application/pkg/common/adapter/server/grpc" 8 | "github.com/byorty/enterprise-application/pkg/common/adapter/server/grpc/grpc_option" 9 | "github.com/byorty/enterprise-application/pkg/common/adapter/server/grpc/mux_option" 10 | "go.uber.org/fx" 11 | ) 12 | 13 | var Constructors = fx.Provide( 14 | application.NewFxProvider, 15 | log.NewFxLogger, 16 | grpc.NewFxServer, 17 | grpc.NewFxMethodDescriptorMap, 18 | grpc_option.NewFxPanicOption, 19 | grpc_option.NewFxAuthOption, 20 | grpc_option.NewFxEnforcerOption, 21 | grpc_option.NewFxValidatorOption, 22 | mux_option.NewFxMarshalerOption, 23 | auth.NewFxJWTHelper, 24 | auth.NewFxRoleEnforcer, 25 | auth.NewFxSessionManager, 26 | ) 27 | -------------------------------------------------------------------------------- /api/proto/v1/order.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pb.v1; 4 | 5 | option go_package = "github.com/byorty/enterprise-application/pkg/common/gen/pbv1"; 6 | 7 | import "patch/go.proto"; 8 | import "google/protobuf/timestamp.proto"; 9 | import "api/proto/v1/common.proto"; 10 | 11 | enum OrderStatus { 12 | ORDER_STATUS_UNSPECIFIED = 0 [(go.value) = { 13 | name: "OrderStatusUnspecified"}]; 14 | ORDER_STATUS_CREATED = 1 [(go.value) = { 15 | name: "OrderStatusCreated" 16 | }]; 17 | ORDER_STATUS_PAID = 2 [(go.value) = { 18 | name: "OrderStatusPaid" 19 | }]; 20 | ORDER_STATUS_DELIVERED = 3 [(go.value) = { 21 | name: "OrderStatusDelivered" 22 | }]; 23 | } 24 | 25 | message Order { 26 | string uuid = 1; 27 | string user_uuid = 2; 28 | double amount = 3; 29 | string address = 4; 30 | OrderStatus status = 5; 31 | repeated UserProduct products = 6; 32 | google.protobuf.Timestamp created_at = 7; 33 | google.protobuf.Timestamp delivered_at = 8; 34 | } -------------------------------------------------------------------------------- /cmd/order-server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | commonadap "github.com/byorty/enterprise-application/pkg/common/adapter" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/application" 6 | "github.com/byorty/enterprise-application/pkg/common/adapter/server/grpc" 7 | orderadap "github.com/byorty/enterprise-application/pkg/order/infra" 8 | orderapp "github.com/byorty/enterprise-application/pkg/order/infra/app" 9 | productsadap "github.com/byorty/enterprise-application/pkg/product/infra" 10 | ) 11 | 12 | func main() { 13 | app := application.New( 14 | commonadap.Constructors, 15 | productsadap.Constructors, 16 | orderadap.Constructors, 17 | orderapp.NewFxOrderServiceServer, 18 | ) 19 | app.Demonize(func( 20 | server grpc.Server, 21 | descriptor grpc.Descriptor, 22 | ) error { 23 | err := server.Register(descriptor) 24 | if err != nil { 25 | return err 26 | } 27 | 28 | err = server.Start() 29 | if err != nil { 30 | return err 31 | } 32 | 33 | return nil 34 | }) 35 | } 36 | -------------------------------------------------------------------------------- /cmd/product-server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | commonadap "github.com/byorty/enterprise-application/pkg/common/adapter" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/application" 6 | "github.com/byorty/enterprise-application/pkg/common/adapter/server/grpc" 7 | orderadap "github.com/byorty/enterprise-application/pkg/order/infra" 8 | productsadap "github.com/byorty/enterprise-application/pkg/product/infra" 9 | productapp "github.com/byorty/enterprise-application/pkg/product/infra/app" 10 | ) 11 | 12 | func main() { 13 | app := application.New( 14 | commonadap.Constructors, 15 | productsadap.Constructors, 16 | orderadap.Constructors, 17 | productapp.NewFxProductServiceServer, 18 | ) 19 | app.Demonize(func( 20 | server grpc.Server, 21 | descriptor grpc.Descriptor, 22 | ) error { 23 | err := server.Register(descriptor) 24 | if err != nil { 25 | return err 26 | } 27 | 28 | err = server.Start() 29 | if err != nil { 30 | return err 31 | } 32 | 33 | return nil 34 | }) 35 | } 36 | -------------------------------------------------------------------------------- /deployments/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | nginx: 5 | image: nginx:alpine 6 | volumes: 7 | - ${PROJECT_DIR}/deployments/nginx.conf:/etc/nginx/conf.d/default.conf:delegated 8 | - ${PROJECT_DIR}/configs/ssl:/etc/nginx/ssl/:delegated 9 | ports: 10 | - "80:80" 11 | - "443:443" 12 | swagger_ui: 13 | image: swaggerapi/swagger-ui 14 | environment: 15 | SWAGGER_JSON: /spec/api.swagger.yaml 16 | volumes: 17 | - ${PROJECT_DIR}/api/openapi-spec/api.swagger.yaml:/spec/api.swagger.yaml 18 | user_server: 19 | build: 20 | context: .. 21 | dockerfile: ${PROJECT_DIR}/deployments/Dockerfile 22 | args: 23 | BUILD_APP_NAME: user-server 24 | order_server: 25 | build: 26 | context: .. 27 | dockerfile: ${PROJECT_DIR}/deployments/Dockerfile 28 | args: 29 | BUILD_APP_NAME: order-server 30 | product_server: 31 | build: 32 | context: .. 33 | dockerfile: ${PROJECT_DIR}/deployments/Dockerfile 34 | args: 35 | BUILD_APP_NAME: product-server -------------------------------------------------------------------------------- /pkg/common/adapter/validator/datetime.go: -------------------------------------------------------------------------------- 1 | package validator 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "google.golang.org/protobuf/reflect/protoreflect" 7 | "google.golang.org/protobuf/types/known/timestamppb" 8 | "time" 9 | ) 10 | 11 | func NewDatetime(duration time.Duration) Validator { 12 | return &datetimeValidator{ 13 | duration: duration, 14 | } 15 | } 16 | 17 | func NewMinDatetime() Validator { 18 | return NewDatetime(-time.Hour * 24 * 365 * 100) 19 | } 20 | 21 | func NewDeliveredAt() Validator { 22 | return NewDatetime(time.Hour * 48) 23 | } 24 | 25 | type datetimeValidator struct { 26 | duration time.Duration 27 | } 28 | 29 | func (v datetimeValidator) Validate(ctx context.Context, value protoreflect.Value) error { 30 | actualDatetime, ok := value.Message().Interface().(*timestamppb.Timestamp) 31 | err := validate.VarCtx(ctx, ok, "eq=true") 32 | if err != nil { 33 | return err 34 | } 35 | 36 | expectedDatetime := time.Now().Add(v.duration) 37 | return validate.VarCtx(ctx, actualDatetime.AsTime().Unix(), fmt.Sprintf("gte=%d", expectedDatetime.Unix())) 38 | } 39 | -------------------------------------------------------------------------------- /cmd/user-server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | commonadap "github.com/byorty/enterprise-application/pkg/common/adapter" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/application" 6 | "github.com/byorty/enterprise-application/pkg/common/adapter/server/grpc" 7 | orderadap "github.com/byorty/enterprise-application/pkg/order/infra" 8 | productsadap "github.com/byorty/enterprise-application/pkg/product/infra" 9 | useradap "github.com/byorty/enterprise-application/pkg/user/infra" 10 | userapp "github.com/byorty/enterprise-application/pkg/user/infra/app" 11 | ) 12 | 13 | func main() { 14 | app := application.New( 15 | commonadap.Constructors, 16 | productsadap.Constructors, 17 | useradap.Constructors, 18 | orderadap.Constructors, 19 | userapp.NewFxUserServiceServer, 20 | ) 21 | app.Demonize(func( 22 | server grpc.Server, 23 | descriptor grpc.Descriptor, 24 | ) error { 25 | err := server.Register(descriptor) 26 | if err != nil { 27 | return err 28 | } 29 | 30 | err = server.Start() 31 | if err != nil { 32 | return err 33 | } 34 | 35 | return nil 36 | }) 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Alexey Solomonov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /pkg/common/collection/map.go: -------------------------------------------------------------------------------- 1 | package collection 2 | 3 | type Map[K comparable, V any] interface { 4 | Set(key K, value V) 5 | Get(key K) (V, bool) 6 | Len() int 7 | Entries() map[K]V 8 | Iterator() Iterator[V] 9 | Remove(key K) 10 | RemoveAll() 11 | } 12 | 13 | func NewMap[K comparable, V any]() Map[K, V] { 14 | return make(genericMap[K, V]) 15 | } 16 | 17 | func ImportMap[K comparable, V any](m map[K]V) Map[K, V] { 18 | return genericMap[K, V](m) 19 | } 20 | 21 | type genericMap[K comparable, V any] map[K]V 22 | 23 | func (m genericMap[K, V]) Set(key K, value V) { 24 | m[key] = value 25 | } 26 | 27 | func (m genericMap[K, V]) Get(key K) (V, bool) { 28 | value, ok := m[key] 29 | return value, ok 30 | } 31 | 32 | func (m genericMap[K, V]) Len() int { 33 | return len(m) 34 | } 35 | 36 | func (m genericMap[K, V]) Entries() map[K]V { 37 | return m 38 | } 39 | 40 | func (m genericMap[K, V]) Iterator() Iterator[V] { 41 | return NewMapIterator[K, V](m) 42 | } 43 | 44 | func (m genericMap[K, V]) Remove(key K) { 45 | delete(m, key) 46 | } 47 | 48 | func (m genericMap[K, V]) RemoveAll() { 49 | for key, _ := range m { 50 | m.Remove(key) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /pkg/common/adapter/validator/datetime_test.go: -------------------------------------------------------------------------------- 1 | package validator_test 2 | 3 | import ( 4 | "context" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/validator" 6 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 7 | "github.com/stretchr/testify/suite" 8 | "google.golang.org/protobuf/reflect/protoreflect" 9 | "google.golang.org/protobuf/types/known/timestamppb" 10 | "testing" 11 | "time" 12 | ) 13 | 14 | func TestDatetimeValidatorSuite(t *testing.T) { 15 | suite.Run(t, new(DatetimeValidatorSuite)) 16 | } 17 | 18 | type DatetimeValidatorSuite struct { 19 | suite.Suite 20 | } 21 | 22 | func (s *DatetimeValidatorSuite) TestAll() { 23 | user := &pbv1.User{} 24 | now := timestamppb.Now().ProtoReflect() 25 | v := validator.NewMinDatetime() 26 | s.NotNil(v.Validate(context.Background(), protoreflect.ValueOf(user.ProtoReflect()))) 27 | s.NotNil(v.Validate(context.Background(), protoreflect.ValueOf(timestamppb.New(time.Time{}).ProtoReflect()))) 28 | s.Nil(v.Validate(context.Background(), protoreflect.ValueOf(now))) 29 | 30 | v = validator.NewDeliveredAt() 31 | s.NotNil(v.Validate(context.Background(), protoreflect.ValueOf(now))) 32 | } 33 | -------------------------------------------------------------------------------- /pkg/common/adapter/server/grpc/grpc_option/validator.go: -------------------------------------------------------------------------------- 1 | package grpc_option 2 | 3 | import ( 4 | "context" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/server/grpc" 6 | gRPC "google.golang.org/grpc" 7 | "google.golang.org/protobuf/reflect/protoreflect" 8 | ) 9 | 10 | func NewFxValidatorOption( 11 | methodDescriptorMap grpc.MethodDescriptorMap, 12 | ) grpc.MiddlewareOut { 13 | return grpc.MiddlewareOut{ 14 | GrpcMiddleware: grpc.Middleware{ 15 | Priority: 97, 16 | GrpcOption: func(ctx context.Context, req interface{}, info *gRPC.UnaryServerInfo, handler gRPC.UnaryHandler) (resp interface{}, err error) { 17 | protoMessage, ok := req.(protoreflect.ProtoMessage) 18 | if !ok { 19 | return handler(ctx, req) 20 | } 21 | 22 | methodDescriptor, ok := methodDescriptorMap.GetByFullName(info.FullMethod) 23 | if !ok { 24 | return handler(ctx, req) 25 | } 26 | 27 | if len(methodDescriptor.Form) == 0 { 28 | return handler(ctx, req) 29 | } 30 | 31 | err = methodDescriptor.Form.Validate(ctx, protoMessage.ProtoReflect()) 32 | if err != nil { 33 | return nil, grpc.ErrInvalidArgument(err) 34 | } 35 | 36 | return handler(ctx, req) 37 | }, 38 | }, 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /pkg/order/infra/app/server.go: -------------------------------------------------------------------------------- 1 | package orderapp 2 | 3 | import ( 4 | "context" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/server/grpc" 6 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 7 | ordersrv "github.com/byorty/enterprise-application/pkg/order/domain/service" 8 | "github.com/byorty/enterprise-application/pkg/order/infra/form" 9 | ) 10 | 11 | var _ pbv1.OrderServiceServer = (*server)(nil) 12 | 13 | func NewFxOrderServiceServer( 14 | orderService ordersrv.OrderService, 15 | ) grpc.Descriptor { 16 | return grpc.Descriptor{ 17 | Server: &server{ 18 | orderService: orderService, 19 | }, 20 | GRPCRegistrar: pbv1.RegisterOrderServiceServer, 21 | GRPCGatewayRegistrar: pbv1.RegisterOrderServiceHandlerFromEndpoint, 22 | MethodDescriptors: []grpc.MethodDescriptor{ 23 | { 24 | Method: (*server).Checkout, 25 | Role: pbv1.RoleOrder, 26 | Permission: pbv1.PermissionWrite, 27 | Form: form.Checkout, 28 | }, 29 | }, 30 | } 31 | } 32 | 33 | type server struct { 34 | orderService ordersrv.OrderService 35 | } 36 | 37 | func (s *server) Checkout(ctx context.Context, request *pbv1.CheckoutOrderRequest) (*pbv1.Order, error) { 38 | return s.orderService.Checkout(ctx, request.OrderUuid, request.Params) 39 | } 40 | -------------------------------------------------------------------------------- /pkg/common/adapter/server/grpc/grpc_option/auth.go: -------------------------------------------------------------------------------- 1 | package grpc_option 2 | 3 | import ( 4 | "context" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/auth" 6 | "github.com/byorty/enterprise-application/pkg/common/adapter/ctxutil" 7 | "github.com/byorty/enterprise-application/pkg/common/adapter/log" 8 | "github.com/byorty/enterprise-application/pkg/common/adapter/server/grpc" 9 | grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth" 10 | gRPC "google.golang.org/grpc" 11 | ) 12 | 13 | func NewFxAuthOption( 14 | logger log.Logger, 15 | sessionManager auth.SessionManager, 16 | ) grpc.MiddlewareOut { 17 | return grpc.MiddlewareOut{ 18 | GrpcMiddleware: grpc.Middleware{ 19 | Priority: 99, 20 | GrpcOption: func(ctx context.Context, req interface{}, info *gRPC.UnaryServerInfo, handler gRPC.UnaryHandler) (resp interface{}, err error) { 21 | logger := logger.WithCtx(ctx, "middleware", "auth") 22 | token, err := grpc_auth.AuthFromMD(ctx, "bearer") 23 | if err != nil { 24 | logger.Error(err) 25 | } 26 | 27 | session, err := sessionManager.GetSessionByToken(ctx, token) 28 | if err != nil { 29 | logger.Error(err) 30 | return nil, err 31 | } 32 | 33 | return handler(ctxutil.Set(ctx, ctxutil.Session, session), req) 34 | }, 35 | }, 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /buf.lock: -------------------------------------------------------------------------------- 1 | # Generated by buf. DO NOT EDIT. 2 | version: v1 3 | deps: 4 | - remote: buf.build 5 | owner: cncf 6 | repository: xds 7 | commit: 0492166643854ea08814f4349286f9cb 8 | - remote: buf.build 9 | owner: envoyproxy 10 | repository: envoy 11 | commit: 14eefb0da6dc45b784fc05e55e66326d 12 | - remote: buf.build 13 | owner: envoyproxy 14 | repository: protoc-gen-validate 15 | commit: dc09a417d27241f7b069feae2cd74a0e 16 | - remote: buf.build 17 | owner: googleapis 18 | repository: googleapis 19 | commit: fdc236b6d1644b29a6161156ce08d8a2 20 | - remote: buf.build 21 | owner: grpc 22 | repository: grpc 23 | commit: 40b550c256324a8f85ba933e92479f95 24 | - remote: buf.build 25 | owner: grpc-ecosystem 26 | repository: grpc-gateway 27 | commit: 00116f302b12478b85deb33b734e026c 28 | - remote: buf.build 29 | owner: nvxx 30 | repository: protopatch 31 | commit: ef95e8420acb4e438d230a2f05895d78 32 | - remote: buf.build 33 | owner: opencensus 34 | repository: opencensus 35 | commit: d1d7ccd1281e4f42ab7ce9a7d2b29e33 36 | - remote: buf.build 37 | owner: opentelemetry 38 | repository: opentelemetry 39 | commit: 509848662be44e4d8aaf9189f6e6ab01 40 | - remote: buf.build 41 | owner: prometheus 42 | repository: client-model 43 | commit: 1d56a02d481a412a83b3c4984eb90c2e 44 | -------------------------------------------------------------------------------- /pkg/common/collection/iterator.go: -------------------------------------------------------------------------------- 1 | package collection 2 | 3 | type Iterator[T any] interface { 4 | HasNext() bool 5 | Next() T 6 | Reset() 7 | } 8 | 9 | func NewSliceIterator[T any](iterable Slice[T]) Iterator[T] { 10 | return &sliceIterator[T]{ 11 | iterable: iterable, 12 | } 13 | } 14 | 15 | type sliceIterator[T any] struct { 16 | iterable Slice[T] 17 | index int 18 | } 19 | 20 | func (i *sliceIterator[T]) HasNext() bool { 21 | return i.index < i.iterable.Len() 22 | } 23 | 24 | func (i *sliceIterator[T]) Next() T { 25 | item := i.iterable.Get(i.index) 26 | i.index++ 27 | return item 28 | } 29 | 30 | func (i *sliceIterator[T]) Reset() { 31 | i.index = 0 32 | } 33 | 34 | func NewMapIterator[K comparable, V any](iterable Map[K, V]) Iterator[V] { 35 | keys := make([]K, 0) 36 | for k, _ := range iterable.Entries() { 37 | keys = append(keys, k) 38 | } 39 | 40 | return &mapIterator[K, V]{ 41 | keys: keys, 42 | iterable: iterable, 43 | } 44 | } 45 | 46 | type mapIterator[K comparable, V any] struct { 47 | index int 48 | keys []K 49 | keysLen int 50 | iterable Map[K, V] 51 | } 52 | 53 | func (i *mapIterator[K, V]) HasNext() bool { 54 | return i.index < i.keysLen 55 | } 56 | 57 | func (i *mapIterator[K, V]) Next() V { 58 | value, _ := i.iterable.Get(i.keys[i.index]) 59 | i.index++ 60 | return value 61 | } 62 | 63 | func (i *mapIterator[K, V]) Reset() { 64 | i.index = 0 65 | } 66 | -------------------------------------------------------------------------------- /pkg/common/adapter/application/provider.go: -------------------------------------------------------------------------------- 1 | package application 2 | 3 | import ( 4 | "github.com/joho/godotenv" 5 | "go.uber.org/config" 6 | "os" 7 | ) 8 | 9 | type Provider interface { 10 | Populate(interface{}) error 11 | PopulateByKey(string, interface{}) error 12 | } 13 | 14 | func NewFxProvider(args Arguments) (Provider, error) { 15 | return NewProviderByOptions(config.File(args.ConfigFilename)) 16 | } 17 | 18 | func NewProviderByOptions(options ...config.YAMLOption) (Provider, error) { 19 | dotenvFile, _ := godotenv.Read(".env") 20 | configProvider, err := config.NewYAML(append( 21 | []config.YAMLOption{ 22 | config.Expand(expandFunc(dotenvFile)), 23 | }, 24 | options..., 25 | )...) 26 | if err != nil { 27 | return nil, err 28 | } 29 | 30 | return &provider{configProvider}, nil 31 | } 32 | 33 | func expandFunc(extraEnv map[string]string) func(key string) (val string, ok bool) { 34 | return func(key string) (val string, ok bool) { 35 | val, ok = os.LookupEnv(key) 36 | if !ok { 37 | val, ok = extraEnv[key] 38 | if !ok { 39 | val = "" 40 | ok = true 41 | } 42 | } 43 | return val, ok 44 | } 45 | } 46 | 47 | type provider struct { 48 | provider config.Provider 49 | } 50 | 51 | func (p *provider) Populate(target interface{}) error { 52 | return p.PopulateByKey("", target) 53 | } 54 | 55 | func (p *provider) PopulateByKey(key string, target interface{}) error { 56 | return p.provider.Get(key).Populate(target) 57 | } 58 | -------------------------------------------------------------------------------- /pkg/common/adapter/auth/role_enforcer.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "github.com/byorty/enterprise-application/pkg/common/adapter/application" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/log" 6 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 7 | "github.com/casbin/casbin/v2" 8 | "strings" 9 | ) 10 | 11 | type RoleEnforcer interface { 12 | Enforce(session pbv1.Session, role pbv1.Role, permission pbv1.Permission) (bool, error) 13 | } 14 | 15 | type roleEnforcer struct { 16 | enforcer *casbin.Enforcer 17 | logger log.Logger 18 | } 19 | 20 | func NewFxRoleEnforcer( 21 | logger log.Logger, 22 | configProvider application.Provider, 23 | ) (RoleEnforcer, error) { 24 | var cfg RoleEnforcerConfig 25 | err := configProvider.PopulateByKey("enforcer", &cfg) 26 | if err != nil { 27 | return nil, err 28 | } 29 | 30 | casbinEnforcer, err := casbin.NewEnforcer(cfg.ModelFile, cfg.PolicyFile) 31 | if err != nil { 32 | return nil, err 33 | } 34 | 35 | return &roleEnforcer{ 36 | enforcer: casbinEnforcer, 37 | logger: logger.Named("role_enforcer"), 38 | }, nil 39 | } 40 | 41 | func (e *roleEnforcer) Enforce(session pbv1.Session, role pbv1.Role, permission pbv1.Permission) (bool, error) { 42 | return e.enforcer.Enforce( 43 | strings.ReplaceAll(pbv1.UserGroup_name[int32(session.Group)], "USER_GROUP_", ""), 44 | pbv1.Role_name[int32(role)], 45 | pbv1.Permission_name[int32(permission)], 46 | ) 47 | } 48 | -------------------------------------------------------------------------------- /configs/ssl/crt.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIID7DCCAtQCCQDynSzj4YfxEDANBgkqhkiG9w0BAQsFADCBtzELMAkGA1UEBhMC 3 | UlUxDzANBgNVBAgMBk1vc2NvdzEPMA0GA1UEBwwGTW9zY293MR8wHQYDVQQKDBZF 4 | bnRlcnByaXNlIEFwcGxpY2F0aW9uMQswCQYDVQQLDAJJVDElMCMGA1UEAwwcZW50 5 | ZXJwcmlzZS5hcHBsaWNhdGlvbi5sb2NhbDExMC8GCSqGSIb3DQEJARYiYWRtaW5A 6 | ZW50ZXJwcmlzZS5hcHBsaWNhdGlvbi5sb2NhbDAeFw0yMjA3MDQxNzQ3MjJaFw0z 7 | MjA3MDExNzQ3MjJaMIG3MQswCQYDVQQGEwJSVTEPMA0GA1UECAwGTW9zY293MQ8w 8 | DQYDVQQHDAZNb3Njb3cxHzAdBgNVBAoMFkVudGVycHJpc2UgQXBwbGljYXRpb24x 9 | CzAJBgNVBAsMAklUMSUwIwYDVQQDDBxlbnRlcnByaXNlLmFwcGxpY2F0aW9uLmxv 10 | Y2FsMTEwLwYJKoZIhvcNAQkBFiJhZG1pbkBlbnRlcnByaXNlLmFwcGxpY2F0aW9u 11 | LmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5XA9psvNPu/m 12 | y+Hv4nPF8ESoJ2hufkylgxh5yZulxg9YcNMNpryob1ew0klEyBW7Vmkc+YHmGooN 13 | cSpjxtUZz/BZY4YJ4a4HRaddQL/ZO5nFHqHLe81PhgBOx3WAlp0ogxHrhhcTX1yw 14 | 6hT9nXsme6jyYDquzrxHN/6V/61xjJI/SUk0+YJnUUgfqqcfpicyBu4Q1YxbX8Xy 15 | UTHhPhHKa318r02FYKdAlrl0m6dPRbPnhO9JogiQ0jx4Ds032DXF36fxInIiFPIx 16 | hxHKNW1iICEfex9sJalZf3+fGNlxtzQtthVD5LvobVwDWPVZuk4uKa+KCiLh8yMe 17 | FWtSWgZ7DQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQDTuawhsCU0MpiUFELOSUKW 18 | DFBUGi+QsMD8ZMhHJhGByxPKounFf6PI/GyR1nNGCG3WYHGsdcutyfoFRLgMRWaN 19 | QHeKVkIRmayVv95+cvYxE/VJdvCKwXbj3St1dGde+TZ2pHKPnXKYfY/UdeIlTQC1 20 | 45CtwWCYw2AtqL5ybzUR3KIYwCfGVUM+/GuKyMe2KNtlB+VVE0LItCHFCM1on7uL 21 | mhTmeWi7nYZs8x0gA6/yix++SWLxBwV56QyUiuXNuRPP10TGirV7Zfb7+qVm5QJn 22 | Wpk/EdmTeIV3yv45nNIyrElU2woZ9umgSKxdYTfcICgqM5RmQ6SSLX+Hv571t7nQ 23 | -----END CERTIFICATE----- 24 | -------------------------------------------------------------------------------- /pkg/common/adapter/validator/validator_test.go: -------------------------------------------------------------------------------- 1 | package validator_test 2 | 3 | import ( 4 | "context" 5 | "github.com/Pallinder/go-randomdata" 6 | "github.com/byorty/enterprise-application/pkg/common/adapter/validator" 7 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 8 | "github.com/google/uuid" 9 | "github.com/stretchr/testify/suite" 10 | "testing" 11 | ) 12 | 13 | func TestValidatorSuite(t *testing.T) { 14 | suite.Run(t, new(ValidatorSuite)) 15 | } 16 | 17 | type ValidatorSuite struct { 18 | suite.Suite 19 | } 20 | 21 | func (s *ValidatorSuite) TestMessage() { 22 | form := validator.Form{ 23 | "uuid": validator.NewUUID(), 24 | "properties": validator.NewReqList( 25 | validator.NewMessage(validator.Form{ 26 | "name": validator.NewReqString(), 27 | "value": validator.NewReqString(), 28 | }), 29 | ), 30 | } 31 | msg := &pbv1.Product{} 32 | protoMsg := msg.ProtoReflect() 33 | 34 | s.NotNil(form.Validate(context.Background(), protoMsg)) 35 | 36 | msg.Uuid = uuid.NewString() 37 | s.NotNil(form.Validate(context.Background(), protoMsg)) 38 | 39 | msg.Properties = []*pbv1.ProductProperty{ 40 | {}, 41 | } 42 | s.NotNil(form.Validate(context.Background(), protoMsg)) 43 | 44 | msg.Properties = []*pbv1.ProductProperty{ 45 | { 46 | Name: randomdata.Alphanumeric(10), 47 | Value: randomdata.Alphanumeric(20), 48 | }, 49 | { 50 | Name: randomdata.Alphanumeric(10), 51 | Value: randomdata.Alphanumeric(20), 52 | }, 53 | } 54 | s.Nil(form.Validate(context.Background(), protoMsg)) 55 | } 56 | -------------------------------------------------------------------------------- /pkg/common/adapter/server/grpc/method.go: -------------------------------------------------------------------------------- 1 | package grpc 2 | 3 | import ( 4 | "github.com/byorty/enterprise-application/pkg/common/adapter/validator" 5 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 6 | "reflect" 7 | "runtime" 8 | "strings" 9 | ) 10 | 11 | type MethodDescriptor struct { 12 | Method interface{} 13 | Role pbv1.Role 14 | Permission pbv1.Permission 15 | Form validator.Form 16 | } 17 | 18 | func (m *MethodDescriptor) GetName() (string, error) { 19 | if m.Method == nil { 20 | return "", ErrMethodDescriptorNotFound 21 | } 22 | 23 | methodPointer := reflect.ValueOf(m.Method).Pointer() 24 | fullName := runtime.FuncForPC(methodPointer).Name() 25 | methodNameParts := strings.Split(fullName, ".") 26 | return methodNameParts[len(methodNameParts)-1], nil 27 | } 28 | 29 | func NewFxMethodDescriptorMap( 30 | serverDescriptor Descriptor, 31 | ) (MethodDescriptorMap, error) { 32 | m := make(MethodDescriptorMap) 33 | for _, methodDescriptor := range serverDescriptor.MethodDescriptors { 34 | methodName, err := methodDescriptor.GetName() 35 | if err != nil { 36 | return nil, err 37 | } 38 | 39 | m[methodName] = methodDescriptor 40 | } 41 | 42 | return m, nil 43 | } 44 | 45 | type MethodDescriptorMap map[string]MethodDescriptor 46 | 47 | func (m MethodDescriptorMap) GetByFullName(fullName string) (MethodDescriptor, bool) { 48 | methodNameParts := strings.Split(fullName, "/") 49 | methodName := methodNameParts[len(methodNameParts)-1] 50 | methodDescriptor, ok := m[methodName] 51 | return methodDescriptor, ok 52 | } 53 | -------------------------------------------------------------------------------- /api/proto/v1/product_service.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pb.v1; 4 | 5 | option go_package = "github.com/byorty/enterprise-application/pkg/common/gen/pbv1"; 6 | 7 | import "google/api/annotations.proto"; 8 | import "protoc-gen-openapiv2/options/annotations.proto"; 9 | import "api/proto/v1/common.proto"; 10 | import "api/proto/v1/product.proto"; 11 | 12 | service ProductService { 13 | rpc GetAllByFilter(ProductsRequest) returns (ProductResponse) { 14 | option (google.api.http) = { 15 | get: "/v1/products"; 16 | }; 17 | option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { 18 | summary: "Получение продуктов по фильтру"; 19 | }; 20 | }; 21 | rpc GetByUUID(GetByProductUUIDRequest) returns (Product) { 22 | option (google.api.http) = { 23 | get: "/v1/products/{product_uuid}"; 24 | }; 25 | option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { 26 | summary: "Получение продукта по UUID"; 27 | }; 28 | }; 29 | } 30 | 31 | message ProductsRequest { 32 | ProductsRequestFilter filter = 1; 33 | Paginator paginator = 2; 34 | } 35 | 36 | message ProductsRequestFilter { 37 | repeated string uuid_in = 1; 38 | string name_contains = 2; 39 | double price_gt = 3; 40 | double price_lt = 4; 41 | repeated ProductProperty properties_eq = 5; 42 | } 43 | 44 | message ProductResponse { 45 | repeated Product items = 1; 46 | uint32 count = 2; 47 | } 48 | 49 | message GetByProductUUIDRequest { 50 | string product_uuid = 1; 51 | } -------------------------------------------------------------------------------- /pkg/order/infra/middleware/order_rights_enforcer.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "context" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/auth" 6 | "github.com/byorty/enterprise-application/pkg/common/adapter/ctxutil" 7 | "github.com/byorty/enterprise-application/pkg/common/adapter/server/grpc" 8 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 9 | ordersrv "github.com/byorty/enterprise-application/pkg/order/domain/service" 10 | "google.golang.org/protobuf/reflect/protoreflect" 11 | ) 12 | 13 | func NewFxOrderRightsEnforcer( 14 | orderService ordersrv.OrderService, 15 | ) auth.RightsEnforcerDescriptorOut { 16 | return auth.RightsEnforcerDescriptorOut{ 17 | Descriptor: auth.RightsEnforcerDescriptor{ 18 | Name: "order_uuid", 19 | RightsEnforcer: NewOrderRightsEnforcer(orderService), 20 | }, 21 | } 22 | } 23 | 24 | func NewOrderRightsEnforcer( 25 | orderService ordersrv.OrderService, 26 | ) auth.RightsEnforcer { 27 | return &orderRightsEnforcer{ 28 | orderService: orderService, 29 | } 30 | } 31 | 32 | type orderRightsEnforcer struct { 33 | orderService ordersrv.OrderService 34 | } 35 | 36 | func (r orderRightsEnforcer) Enforce(ctx context.Context, session pbv1.Session, value protoreflect.Value) (context.Context, error) { 37 | order, err := r.orderService.GetByUUID(ctx, value.String()) 38 | if err != nil { 39 | return nil, grpc.ErrSessionNotOwnEntity 40 | } 41 | 42 | if order.UserUuid != session.Uuid { 43 | return nil, grpc.ErrSessionNotOwnEntity 44 | } 45 | 46 | return ctxutil.Set(ctx, ctxutil.Order, order), nil 47 | } 48 | -------------------------------------------------------------------------------- /pkg/user/infra/middleware/user_rights_enforcer.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "context" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/auth" 6 | "github.com/byorty/enterprise-application/pkg/common/adapter/ctxutil" 7 | "github.com/byorty/enterprise-application/pkg/common/adapter/server/grpc" 8 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 9 | usersrv "github.com/byorty/enterprise-application/pkg/user/domain/service" 10 | "google.golang.org/protobuf/reflect/protoreflect" 11 | ) 12 | 13 | func NewFxUserRightsEnforcer( 14 | userService usersrv.UserService, 15 | ) auth.RightsEnforcerDescriptorOut { 16 | return auth.RightsEnforcerDescriptorOut{ 17 | Descriptor: auth.RightsEnforcerDescriptor{ 18 | Name: "user_uuid", 19 | RightsEnforcer: NewUserRightsEnforcer(userService), 20 | }, 21 | } 22 | } 23 | 24 | func NewUserRightsEnforcer( 25 | userService usersrv.UserService, 26 | ) auth.RightsEnforcer { 27 | return &userRightsEnforcer{ 28 | userService: userService, 29 | } 30 | } 31 | 32 | type userRightsEnforcer struct { 33 | userService usersrv.UserService 34 | } 35 | 36 | func (r userRightsEnforcer) Enforce(ctx context.Context, session pbv1.Session, value protoreflect.Value) (context.Context, error) { 37 | user, err := r.userService.GetByUUID(ctx, value.String()) 38 | if err != nil { 39 | return nil, err 40 | } 41 | 42 | if user.Status != pbv1.UserStatusActive { 43 | return nil, grpc.ErrSessionHasNotPermissions 44 | } 45 | 46 | if session.Uuid != user.Uuid { 47 | return nil, grpc.ErrSessionNotOwnEntity 48 | } 49 | 50 | return ctxutil.Set(ctx, ctxutil.User, user), nil 51 | } 52 | -------------------------------------------------------------------------------- /pkg/common/adapter/server/grpc/errors.go: -------------------------------------------------------------------------------- 1 | package grpc 2 | 3 | import ( 4 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 5 | "github.com/pkg/errors" 6 | "google.golang.org/grpc/codes" 7 | "google.golang.org/grpc/status" 8 | ) 9 | 10 | var ( 11 | ErrMethodDescriptorNotFound = errors.New("Описание метода не найдено") 12 | ErrSessionNotFound = errors.New("Сессия не найдена") 13 | ErrSessionHasNotPermissions = errors.New("Сессия не имеет прав на метод API") 14 | ErrSessionNotOwnEntity = errors.New("Сессия не имеет прав на сущность API") 15 | ErrInternal = func(err error) error { 16 | return NewResponseError(codes.Internal, err) 17 | } 18 | ErrNotFound = func(err error) error { 19 | return NewResponseError(codes.NotFound, err) 20 | } 21 | ErrPermissionDenied = func(err error) error { 22 | return NewResponseError(codes.PermissionDenied, err) 23 | } 24 | ErrInvalidArgument = func(err error) error { 25 | return NewResponseError(codes.InvalidArgument, err) 26 | } 27 | ErrUnauthenticated = func(err error) error { 28 | return NewResponseError(codes.Unauthenticated, err) 29 | } 30 | ErrAlreadyExists = func(err error) error { 31 | return NewResponseError(codes.AlreadyExists, err) 32 | } 33 | ErrTooManyRequests = func(err error) error { 34 | return NewResponseError(codes.ResourceExhausted, err) 35 | } 36 | ) 37 | 38 | func NewResponseError(code codes.Code, err error) error { 39 | s, err := status.New(code, err.Error()).WithDetails(&pbv1.Error{ 40 | Code: uint32(code), 41 | }) 42 | 43 | if err != nil { 44 | return status.Errorf(codes.Internal, err.Error()) 45 | } 46 | 47 | return s.Err() 48 | } 49 | -------------------------------------------------------------------------------- /pkg/common/adapter/auth/jwt_helper.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "crypto/rsa" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/application" 6 | "github.com/dgrijalva/jwt-go" 7 | "io/ioutil" 8 | ) 9 | 10 | type Claims interface { 11 | jwt.Claims 12 | } 13 | 14 | type JWTHelper interface { 15 | Parse(token string, claims Claims) error 16 | CreateToken(claims Claims) (string, error) 17 | } 18 | 19 | func NewFxJWTHelper( 20 | provider application.Provider, 21 | ) (JWTHelper, error) { 22 | var cfg SslConfig 23 | err := provider.PopulateByKey("ssl", &cfg) 24 | if err != nil { 25 | return nil, err 26 | } 27 | 28 | buf, err := ioutil.ReadFile(cfg.PrivateKeyFile) 29 | if err != nil { 30 | return nil, err 31 | } 32 | 33 | privateKey, err := jwt.ParseRSAPrivateKeyFromPEM(buf) 34 | if err != nil { 35 | return nil, err 36 | } 37 | 38 | buf, err = ioutil.ReadFile(cfg.PublicKeyFile) 39 | if err != nil { 40 | return nil, err 41 | } 42 | 43 | publicKey, err := jwt.ParseRSAPublicKeyFromPEM(buf) 44 | if err != nil { 45 | return nil, err 46 | } 47 | 48 | return &jwtHelper{ 49 | publicKey: publicKey, 50 | privateKey: privateKey, 51 | }, nil 52 | } 53 | 54 | type jwtHelper struct { 55 | publicKey *rsa.PublicKey 56 | privateKey *rsa.PrivateKey 57 | } 58 | 59 | func (h *jwtHelper) Parse(token string, claims Claims) error { 60 | _, err := jwt.ParseWithClaims(token, claims, func(token *jwt.Token) (interface{}, error) { 61 | return h.publicKey, nil 62 | }) 63 | if err != nil { 64 | return err 65 | } 66 | 67 | return claims.Valid() 68 | } 69 | 70 | func (h *jwtHelper) CreateToken(claims Claims) (string, error) { 71 | token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims) 72 | return token.SignedString(h.privateKey) 73 | } 74 | -------------------------------------------------------------------------------- /pkg/user/infra/middleware/user_product_right_enforcer.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "context" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/auth" 6 | "github.com/byorty/enterprise-application/pkg/common/adapter/ctxutil" 7 | "github.com/byorty/enterprise-application/pkg/common/adapter/server/grpc" 8 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 9 | usersrv "github.com/byorty/enterprise-application/pkg/user/domain/service" 10 | "google.golang.org/protobuf/reflect/protoreflect" 11 | ) 12 | 13 | func NewFxUserProductRightsEnforcer( 14 | userProductService usersrv.UserProductService, 15 | ) auth.RightsEnforcerDescriptorOut { 16 | return auth.RightsEnforcerDescriptorOut{ 17 | Descriptor: auth.RightsEnforcerDescriptor{ 18 | Name: "user_product_uuid", 19 | RightsEnforcer: NewUserProductRightsEnforcer(userProductService), 20 | }, 21 | } 22 | } 23 | 24 | func NewUserProductRightsEnforcer( 25 | userProductService usersrv.UserProductService, 26 | ) auth.RightsEnforcer { 27 | return &userProductRightsEnforcer{ 28 | userProductService: userProductService, 29 | } 30 | } 31 | 32 | type userProductRightsEnforcer struct { 33 | userProductService usersrv.UserProductService 34 | } 35 | 36 | func (r userProductRightsEnforcer) Enforce(ctx context.Context, session pbv1.Session, value protoreflect.Value) (context.Context, error) { 37 | userProducts, err := r.userProductService.GetAllByFilter(ctx, pbv1.GetUserProductRequestParams{ 38 | UuidIn: []string{value.String()}, 39 | UserUuidIn: []string{session.Uuid}, 40 | }) 41 | if err != nil || len(userProducts) == 0 { 42 | return nil, grpc.ErrSessionNotOwnEntity 43 | } 44 | 45 | return ctxutil.Set(ctx, ctxutil.UserProduct, userProducts[0]), nil 46 | } 47 | -------------------------------------------------------------------------------- /configs/ssl/private.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDlcD2my80+7+bL 3 | 4e/ic8XwRKgnaG5+TKWDGHnJm6XGD1hw0w2mvKhvV7DSSUTIFbtWaRz5geYaig1x 4 | KmPG1RnP8FljhgnhrgdFp11Av9k7mcUeoct7zU+GAE7HdYCWnSiDEeuGFxNfXLDq 5 | FP2deyZ7qPJgOq7OvEc3/pX/rXGMkj9JSTT5gmdRSB+qpx+mJzIG7hDVjFtfxfJR 6 | MeE+EcprfXyvTYVgp0CWuXSbp09Fs+eE70miCJDSPHgOzTfYNcXfp/EiciIU8jGH 7 | Eco1bWIgIR97H2wlqVl/f58Y2XG3NC22FUPku+htXANY9Vm6Ti4pr4oKIuHzIx4V 8 | a1JaBnsNAgMBAAECggEBAJJCtOqJbPO8FxLNmxBu4TXDbraAej+FONWTWr/MuybB 9 | TY3O3Rr3lSA1dID5OCGcyOnS5CeiST+N1ffYH/b2jhfijflFzzLQr84VXPsT0bWO 10 | 1vwqA/+N6C3yMEYyf6CD2vmDCPNX7n+SJS1z6CDmCqg2ERyLDDi6CWSGpLRyqroC 11 | o7l1OzGhouvRmm0NlJ7eySjlAfOHNUZLeyWDwaXb1fMbs4T9k+4lmEfros/XyKwe 12 | X+Xpkdj9i9wE0cyyz/ow5UirB6y5ip2wrltb2U8JZj+Qtz59+GgjxtUpPPazm7xv 13 | dCy73YQU0E36v2T0NX3oj9QrVgZsDLoWCbxpQF0LxjkCgYEA+X5b9d5CcjzVwDHe 14 | UZ2vBEzl54M2i6ZYbCrEUm2Ukdlt9x6FTUyoEdZu+yGwfU+THUM6h+7t9VRT1e0x 15 | Cs+S9WfrZxv0g4kDFbV0Dycr4vcr4d3slaYEb7sUQsDvcWtsw/9HOqRE2PJFEGVb 16 | KyIdsovpQ4N6tAp6bxiyHCCzuVcCgYEA62v933YOYacKeK1GCxLgtzuLXGkWCtvl 17 | sLG6V5g3V7rZJ1GDhdCbqtarZZbe4esarLH6zyPki1Ruyu6WctVhEW98nRiVkfPy 18 | 28XJ3rmtkWPQZXw5eYeSfM/zfcavkL+YmBlcgH7qdB25AQwEZUOzisvMUO6kbzdb 19 | g2eeuTTM3DsCgYBmzzkZ4hLDfGognuwb+bxrKzz538oUVeHOAPmRdfJo/44e7QbF 20 | SbdgUlq9Ra6ylJ3syw1NgpmwJKW/W9R/vfWzBrWscYqawVTyFynSLLQa/PuqQYcC 21 | S708RX0d3N9Of5P8WC+D7LkqJPtsvDeLWK2gK6Nd3MotcrvtF+IdUSR+VQKBgQDq 22 | KTYRKHnRg7aUpbR/mz1Mw7swJY45KtPh1kWEjvCtIDqSMy/gz8emO3Orzk7O42xa 23 | zYSsuATA2TCCRKH8gmTUVNHb5/INhFnRY4AROxp6/I7yAoega8q2vphwSEmkbg43 24 | azJo1NQavt2fPva4Soiwy1jkPxnrTWKG53Amw2/otQKBgQDBJMZgEkELpLYY7358 25 | ixb8g1CM/W4y8qUs5fGqfYadL3MCnp+ezbCmLrA+RDK2StTTmDWWeUFY9enZrgFE 26 | u/yNSmeVm/j2EUh6M2Db/urYrhzus3HSqkW1/Bk00jPiBa0ODdFy9zpj260Rjaw9 27 | +46VTJI1CL49a/TSvTUqLEU9ZQ== 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /pkg/common/adapter/auth/private.key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDlcD2my80+7+bL 3 | 4e/ic8XwRKgnaG5+TKWDGHnJm6XGD1hw0w2mvKhvV7DSSUTIFbtWaRz5geYaig1x 4 | KmPG1RnP8FljhgnhrgdFp11Av9k7mcUeoct7zU+GAE7HdYCWnSiDEeuGFxNfXLDq 5 | FP2deyZ7qPJgOq7OvEc3/pX/rXGMkj9JSTT5gmdRSB+qpx+mJzIG7hDVjFtfxfJR 6 | MeE+EcprfXyvTYVgp0CWuXSbp09Fs+eE70miCJDSPHgOzTfYNcXfp/EiciIU8jGH 7 | Eco1bWIgIR97H2wlqVl/f58Y2XG3NC22FUPku+htXANY9Vm6Ti4pr4oKIuHzIx4V 8 | a1JaBnsNAgMBAAECggEBAJJCtOqJbPO8FxLNmxBu4TXDbraAej+FONWTWr/MuybB 9 | TY3O3Rr3lSA1dID5OCGcyOnS5CeiST+N1ffYH/b2jhfijflFzzLQr84VXPsT0bWO 10 | 1vwqA/+N6C3yMEYyf6CD2vmDCPNX7n+SJS1z6CDmCqg2ERyLDDi6CWSGpLRyqroC 11 | o7l1OzGhouvRmm0NlJ7eySjlAfOHNUZLeyWDwaXb1fMbs4T9k+4lmEfros/XyKwe 12 | X+Xpkdj9i9wE0cyyz/ow5UirB6y5ip2wrltb2U8JZj+Qtz59+GgjxtUpPPazm7xv 13 | dCy73YQU0E36v2T0NX3oj9QrVgZsDLoWCbxpQF0LxjkCgYEA+X5b9d5CcjzVwDHe 14 | UZ2vBEzl54M2i6ZYbCrEUm2Ukdlt9x6FTUyoEdZu+yGwfU+THUM6h+7t9VRT1e0x 15 | Cs+S9WfrZxv0g4kDFbV0Dycr4vcr4d3slaYEb7sUQsDvcWtsw/9HOqRE2PJFEGVb 16 | KyIdsovpQ4N6tAp6bxiyHCCzuVcCgYEA62v933YOYacKeK1GCxLgtzuLXGkWCtvl 17 | sLG6V5g3V7rZJ1GDhdCbqtarZZbe4esarLH6zyPki1Ruyu6WctVhEW98nRiVkfPy 18 | 28XJ3rmtkWPQZXw5eYeSfM/zfcavkL+YmBlcgH7qdB25AQwEZUOzisvMUO6kbzdb 19 | g2eeuTTM3DsCgYBmzzkZ4hLDfGognuwb+bxrKzz538oUVeHOAPmRdfJo/44e7QbF 20 | SbdgUlq9Ra6ylJ3syw1NgpmwJKW/W9R/vfWzBrWscYqawVTyFynSLLQa/PuqQYcC 21 | S708RX0d3N9Of5P8WC+D7LkqJPtsvDeLWK2gK6Nd3MotcrvtF+IdUSR+VQKBgQDq 22 | KTYRKHnRg7aUpbR/mz1Mw7swJY45KtPh1kWEjvCtIDqSMy/gz8emO3Orzk7O42xa 23 | zYSsuATA2TCCRKH8gmTUVNHb5/INhFnRY4AROxp6/I7yAoega8q2vphwSEmkbg43 24 | azJo1NQavt2fPva4Soiwy1jkPxnrTWKG53Amw2/otQKBgQDBJMZgEkELpLYY7358 25 | ixb8g1CM/W4y8qUs5fGqfYadL3MCnp+ezbCmLrA+RDK2StTTmDWWeUFY9enZrgFE 26 | u/yNSmeVm/j2EUh6M2Db/urYrhzus3HSqkW1/Bk00jPiBa0ODdFy9zpj260Rjaw9 27 | +46VTJI1CL49a/TSvTUqLEU9ZQ== 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /pkg/common/adapter/application/provider_test.go: -------------------------------------------------------------------------------- 1 | package application_test 2 | 3 | import ( 4 | "github.com/byorty/enterprise-application/pkg/common/adapter/application" 5 | "os" 6 | "strings" 7 | "testing" 8 | 9 | "github.com/stretchr/testify/suite" 10 | "go.uber.org/config" 11 | ) 12 | 13 | type Config struct { 14 | A A 15 | Partition int 16 | } 17 | 18 | type A struct { 19 | B string 20 | C struct { 21 | D bool 22 | F int 23 | } 24 | } 25 | 26 | func TestConfigProviderSuite(t *testing.T) { 27 | suite.Run(t, new(ConfigProviderSuite)) 28 | } 29 | 30 | type ConfigProviderSuite struct { 31 | suite.Suite 32 | } 33 | 34 | func (s *ConfigProviderSuite) TestPopulate() { 35 | reader := strings.NewReader("a: {b: bar, c: {d: true, f: 12}}") 36 | 37 | provider, err := application.NewProviderByOptions(config.Source(reader)) 38 | s.Nil(err) 39 | 40 | var a A 41 | s.Nil(provider.PopulateByKey("a", &a)) 42 | s.Equal("bar", a.B) 43 | s.Equal(true, a.C.D) 44 | s.Equal(12, a.C.F) 45 | 46 | var f int 47 | s.Nil(provider.PopulateByKey("a.c.f", &f)) 48 | s.Equal(12, f) 49 | 50 | var cfg Config 51 | s.Nil(provider.Populate(&cfg)) 52 | s.Equal(cfg.A, a) 53 | s.Equal(cfg.A.B, a.B) 54 | } 55 | 56 | func (s *ConfigProviderSuite) TestExpand() { 57 | var a int 58 | var b string 59 | var c string 60 | varB := "hello world" 61 | err := os.Setenv("VAR_B", varB) 62 | if err != nil { 63 | s.Error(err) 64 | } 65 | 66 | reader := strings.NewReader(` 67 | a: 1 68 | b: "$VAR_B" 69 | c: "$VAR_C" 70 | `) 71 | 72 | provider, err := application.NewProviderByOptions(config.Source(reader)) 73 | s.Nil(err) 74 | 75 | s.Nil(provider.PopulateByKey("a", &a)) 76 | s.Equal(1, a) 77 | 78 | s.Nil(provider.PopulateByKey("b", &b)) 79 | s.Equal(varB, b) 80 | 81 | s.Nil(provider.PopulateByKey("b", &b)) 82 | s.Equal("", c) 83 | } 84 | -------------------------------------------------------------------------------- /pkg/product/infra/app/server.go: -------------------------------------------------------------------------------- 1 | package productapp 2 | 3 | import ( 4 | "context" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/server/grpc" 6 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 7 | productsrv "github.com/byorty/enterprise-application/pkg/product/domain/service" 8 | "github.com/byorty/enterprise-application/pkg/product/infra/form" 9 | ) 10 | 11 | var _ pbv1.ProductServiceServer = (*server)(nil) 12 | 13 | func NewFxProductServiceServer( 14 | productService productsrv.ProductService, 15 | ) grpc.Descriptor { 16 | return grpc.Descriptor{ 17 | Server: &server{ 18 | productService: productService, 19 | }, 20 | GRPCRegistrar: pbv1.RegisterProductServiceServer, 21 | GRPCGatewayRegistrar: pbv1.RegisterProductServiceHandlerFromEndpoint, 22 | MethodDescriptors: []grpc.MethodDescriptor{ 23 | { 24 | Method: (*server).GetAllByFilter, 25 | Role: pbv1.RoleProduct, 26 | Permission: pbv1.PermissionRead, 27 | Form: form.Products, 28 | }, 29 | { 30 | Method: (*server).GetByUUID, 31 | Role: pbv1.RoleProduct, 32 | Permission: pbv1.PermissionRead, 33 | Form: form.ProductUUID, 34 | }, 35 | }, 36 | } 37 | } 38 | 39 | type server struct { 40 | productService productsrv.ProductService 41 | } 42 | 43 | func (s server) GetAllByFilter(ctx context.Context, request *pbv1.ProductsRequest) (*pbv1.ProductResponse, error) { 44 | products, count, err := s.productService.GetAllByFilter(ctx, request.Filter, request.Paginator) 45 | return &pbv1.ProductResponse{ 46 | Items: products, 47 | Count: count, 48 | }, err 49 | } 50 | 51 | func (s server) GetByUUID(ctx context.Context, request *pbv1.GetByProductUUIDRequest) (*pbv1.Product, error) { 52 | return s.productService.GetByUUID(ctx, request.ProductUuid) 53 | } 54 | -------------------------------------------------------------------------------- /pkg/common/adapter/validator/string_test.go: -------------------------------------------------------------------------------- 1 | package validator_test 2 | 3 | import ( 4 | "context" 5 | "github.com/Pallinder/go-randomdata" 6 | "github.com/byorty/enterprise-application/pkg/common/adapter/validator" 7 | "github.com/google/uuid" 8 | "github.com/stretchr/testify/suite" 9 | "google.golang.org/protobuf/reflect/protoreflect" 10 | "testing" 11 | ) 12 | 13 | func TestStringValidatorSuite(t *testing.T) { 14 | suite.Run(t, new(StringValidatorSuite)) 15 | } 16 | 17 | type StringValidatorSuite struct { 18 | suite.Suite 19 | } 20 | 21 | func (s *StringValidatorSuite) TestUUID() { 22 | v := validator.NewUUID() 23 | s.NotNil(v.Validate(context.Background(), protoreflect.ValueOf(""))) 24 | s.NotNil(v.Validate(context.Background(), protoreflect.ValueOf(randomdata.Alphanumeric(32)))) 25 | s.Nil(v.Validate(context.Background(), protoreflect.ValueOf(uuid.NewString()))) 26 | } 27 | 28 | func (s *StringValidatorSuite) TestPhoneNumber() { 29 | v := validator.NewPhoneNumber() 30 | s.NotNil(v.Validate(context.Background(), protoreflect.ValueOf(""))) 31 | s.NotNil(v.Validate(context.Background(), protoreflect.ValueOf(randomdata.Alphanumeric(32)))) 32 | s.Nil(v.Validate(context.Background(), protoreflect.ValueOf("+79008007060"))) 33 | } 34 | 35 | func (s *StringValidatorSuite) TestMaxLen() { 36 | v := validator.NewStringWithMaxLen(10) 37 | s.NotNil(v.Validate(context.Background(), protoreflect.ValueOf(""))) 38 | s.NotNil(v.Validate(context.Background(), protoreflect.ValueOf(randomdata.Alphanumeric(32)))) 39 | s.Nil(v.Validate(context.Background(), protoreflect.ValueOf(randomdata.Alphanumeric(9)))) 40 | } 41 | 42 | func (s *StringValidatorSuite) TestAlphanumeric() { 43 | v := validator.NewAlphanumeric() 44 | s.NotNil(v.Validate(context.Background(), protoreflect.ValueOf(""))) 45 | s.NotNil(v.Validate(context.Background(), protoreflect.ValueOf("qazwsx!@#%%^"))) 46 | s.Nil(v.Validate(context.Background(), protoreflect.ValueOf(randomdata.Alphanumeric(32)))) 47 | } 48 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | GO111MODULE:=on 2 | GOBIN:=$(GOPATH)/bin 3 | PATH:=$(GOBIN):$(PATH) 4 | PROJECT_NAME:=enterprise_application 5 | PROJECT_DIR:=$(shell pwd) 6 | GEN_DIR:=$(PROJECT_DIR)/pkg/common/gen 7 | BUILD_DIR:=$(PROJECT_DIR)/build 8 | VENDOR_DIR:=$(PROJECT_DIR)/vendor 9 | DOCKER_COMPOSE:=$(PROJECT_DIR)/deployments/docker-compose.yml 10 | 11 | export 12 | 13 | define build_app 14 | CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $(BUILD_DIR)/$(1)/main.go $(PROJECT_DIR)/cmd/$(1)/main.go 15 | endef 16 | 17 | clean: 18 | rm -rf $(VENDOR_DIR) 19 | 20 | install: clean 21 | go get google.golang.org/grpc 22 | go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28 23 | go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2 24 | go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v2.10.0 25 | go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2 26 | go install github.com/alta/protopatch/cmd/protoc-gen-go-patch@latest 27 | 28 | vendor: 29 | go mod vendor 30 | 31 | buf_update: 32 | buf mod update 33 | 34 | buf_generate: clean 35 | rm -rf $(GEN_DIR) 36 | buf generate 37 | make vendor 38 | 39 | build_apps: 40 | rm -rf $(BUILD_DIR) 41 | @$(foreach BUILD_APP, $(shell ls $(PROJECT_DIR)/cmd), CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o $(BUILD_DIR)/$(BUILD_APP) $(PROJECT_DIR)/cmd/$(BUILD_APP)/main.go;) 42 | 43 | up: build_apps 44 | docker-compose -p $(PROJECT_NAME) -f $(DOCKER_COMPOSE) up -d --build --force-recreate 45 | 46 | down: 47 | docker-compose -p $(PROJECT_NAME) -f $(DOCKER_COMPOSE) down --remove-orphans 48 | docker image prune -f 49 | docker volume prune -f 50 | 51 | restart: down up 52 | 53 | run: build_apps 54 | docker-compose -p $(PROJECT_NAME) -f $(DOCKER_COMPOSE) up --build --force-recreate 55 | 56 | cert_generate: 57 | openssl req -newkey rsa -x509 -sha256 -days 3650 -nodes -out ${PROJECT_DIR}/configs/ssl/crt.pem -keyout ${PROJECT_DIR}/configs/ssl/private.key.pem 58 | openssl rsa -in ${PROJECT_DIR}/configs/ssl/private.key.pem -outform PEM -pubout -out ${PROJECT_DIR}/configs/ssl/public.key.pem 59 | -------------------------------------------------------------------------------- /pkg/common/adapter/log/logger.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "context" 5 | "go.uber.org/zap" 6 | "go.uber.org/zap/zapcore" 7 | ) 8 | 9 | type Logger interface { 10 | Debug(args ...interface{}) 11 | Info(args ...interface{}) 12 | Warn(args ...interface{}) 13 | Error(args ...interface{}) 14 | Fatal(args ...interface{}) 15 | Debugf(format string, args ...interface{}) 16 | Infof(format string, args ...interface{}) 17 | Warnf(format string, args ...interface{}) 18 | Errorf(format string, args ...interface{}) 19 | Fatalf(format string, args ...interface{}) 20 | With(args ...interface{}) Logger 21 | WithCtx(ctx context.Context, args ...interface{}) Logger 22 | Infow(string, ...interface{}) 23 | Named(string) Logger 24 | } 25 | 26 | func NewFxLogger() Logger { 27 | cfg := zap.Config{ 28 | Level: zap.NewAtomicLevelAt(zap.DebugLevel), 29 | DisableCaller: false, 30 | OutputPaths: []string{"stderr"}, 31 | ErrorOutputPaths: []string{"stderr"}, 32 | Encoding: "json", 33 | EncoderConfig: zapcore.EncoderConfig{ 34 | MessageKey: "msg", 35 | LevelKey: "level", 36 | NameKey: "log", 37 | EncodeLevel: zapcore.LowercaseLevelEncoder, 38 | EncodeTime: zapcore.RFC3339NanoTimeEncoder, 39 | EncodeDuration: zapcore.SecondsDurationEncoder, 40 | CallerKey: "file", 41 | EncodeCaller: zapcore.ShortCallerEncoder, 42 | EncodeName: zapcore.FullNameEncoder, 43 | }, 44 | } 45 | l, _ := cfg.Build() 46 | sugaredLogger := l.Sugar() 47 | defer sugaredLogger.Sync() 48 | return &logger{ 49 | SugaredLogger: sugaredLogger, 50 | } 51 | } 52 | 53 | type logger struct { 54 | *zap.SugaredLogger 55 | } 56 | 57 | func (l *logger) With(args ...interface{}) Logger { 58 | return &logger{ 59 | SugaredLogger: l.SugaredLogger.With(args...), 60 | } 61 | } 62 | 63 | func (l *logger) WithCtx(ctx context.Context, args ...interface{}) Logger { 64 | return &logger{ 65 | SugaredLogger: l.SugaredLogger.With(args...), 66 | } 67 | } 68 | 69 | func (l *logger) Named(name string) Logger { 70 | return &logger{ 71 | SugaredLogger: l.SugaredLogger.Named(name), 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/byorty/enterprise-application 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/Pallinder/go-randomdata v1.2.0 7 | github.com/alta/protopatch v0.5.0 8 | github.com/casbin/casbin/v2 v2.47.2 9 | github.com/dgrijalva/jwt-go v3.2.0+incompatible 10 | github.com/go-ozzo/ozzo-validation v3.6.0+incompatible 11 | github.com/google/uuid v1.3.0 12 | github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 13 | github.com/grpc-ecosystem/grpc-gateway v1.16.0 14 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.10.3 15 | github.com/jessevdk/go-flags v1.5.0 16 | github.com/joho/godotenv v1.4.0 17 | github.com/pkg/errors v0.9.1 18 | go.uber.org/config v1.4.0 19 | go.uber.org/fx v1.17.1 20 | go.uber.org/zap v1.21.0 21 | google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd 22 | google.golang.org/grpc v1.47.0 23 | google.golang.org/protobuf v1.28.0 24 | ) 25 | 26 | require ( 27 | github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect 28 | github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 // indirect 29 | github.com/davecgh/go-spew v1.1.1 // indirect 30 | github.com/go-playground/locales v0.14.0 // indirect 31 | github.com/go-playground/universal-translator v0.18.0 // indirect 32 | github.com/go-playground/validator/v10 v10.11.1 // indirect 33 | github.com/golang/glog v1.0.0 // indirect 34 | github.com/golang/protobuf v1.5.2 // indirect 35 | github.com/leodido/go-urn v1.2.1 // indirect 36 | github.com/pmezard/go-difflib v1.0.0 // indirect 37 | github.com/stretchr/objx v0.4.0 // indirect 38 | github.com/stretchr/testify v1.8.0 // indirect 39 | go.uber.org/atomic v1.7.0 // indirect 40 | go.uber.org/dig v1.14.0 // indirect 41 | go.uber.org/multierr v1.6.0 // indirect 42 | golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect 43 | golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect 44 | golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect 45 | golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 // indirect 46 | golang.org/x/text v0.3.7 // indirect 47 | golang.org/x/tools v0.1.7 // indirect 48 | gopkg.in/yaml.v2 v2.4.0 // indirect 49 | gopkg.in/yaml.v3 v3.0.1 // indirect 50 | ) 51 | -------------------------------------------------------------------------------- /api/proto/v1/user.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pb.v1; 4 | 5 | option go_package = "github.com/byorty/enterprise-application/pkg/common/gen/pbv1"; 6 | 7 | import "google/protobuf/timestamp.proto"; 8 | import "patch/go.proto"; 9 | 10 | enum UserGroup { 11 | USER_GROUP_GUEST = 0 [(go.value) = { 12 | name: "UserGroupGuest" 13 | }]; 14 | USER_GROUP_CUSTOMER = 1 [(go.value) = { 15 | name: "UserGroupCustomer" 16 | }]; 17 | } 18 | 19 | enum UserStatus { 20 | USER_STATUS_UNSPECIFIED = 0 [(go.value) = { 21 | name: "UserStatusUnspecified" 22 | }]; 23 | USER_STATUS_UNCONFIRMED = 1 [(go.value) = { 24 | name: "UserStatusUnconfirmed" 25 | }]; 26 | USER_STATUS_ACTIVE = 2 [(go.value) = { 27 | name: "UserStatusActive" 28 | }]; 29 | USER_STATUS_BLOCKED = 3 [(go.value) = { 30 | name: "UserStatusBlocked" 31 | }]; 32 | } 33 | 34 | message User { 35 | string uuid = 1; 36 | UserGroup group = 2; 37 | UserStatus status = 3; 38 | string phone_number = 4; 39 | string lastname = 5; 40 | string firstname = 6; 41 | google.protobuf.Timestamp created_at = 7; 42 | } 43 | 44 | message Session { 45 | string uuid = 1; 46 | UserGroup group = 2; 47 | } 48 | 49 | enum Role { 50 | ROLE_UNSPECIFIED = 0 [ 51 | (go.value) = { 52 | name: "RoleUnspecified" 53 | } 54 | ]; 55 | ROLE_USER = 1 [ 56 | (go.value) = { 57 | name: "RoleUser" 58 | } 59 | ]; 60 | ROLE_PRODUCT = 2 [ 61 | (go.value) = { 62 | name: "RoleProduct" 63 | } 64 | ]; 65 | ROLE_ORDER = 3 [ 66 | (go.value) = { 67 | name: "RoleOrder" 68 | } 69 | ]; 70 | ROLE_USER_PRODUCT = 4 [ 71 | (go.value) = { 72 | name: "RoleUserProduct" 73 | } 74 | ]; 75 | } 76 | 77 | enum Permission { 78 | PERMISSION_UNSPECIFIED = 0 [ 79 | (go.value) = { 80 | name: "PermissionUnspecified" 81 | } 82 | ]; 83 | PERMISSION_READ = 1 [ 84 | (go.value) = { 85 | name: "PermissionRead" 86 | } 87 | ]; 88 | PERMISSION_WRITE = 2 [ 89 | (go.value) = { 90 | name: "PermissionWrite" 91 | } 92 | ]; 93 | } -------------------------------------------------------------------------------- /deployments/nginx.conf: -------------------------------------------------------------------------------- 1 | map $microservice $upstream { 2 | users user_server:8080; 3 | orders order_server:8080; 4 | products product_server:8080; 5 | swagger swagger_ui:8080; 6 | } 7 | 8 | server { 9 | listen 443 http2 ssl; 10 | server_name enterprise.application.local; 11 | server_tokens off; 12 | client_max_body_size 16m; 13 | root /dev/null; 14 | # this is the internal Docker DNS, cache only for 30s 15 | resolver 127.0.0.11 valid=30s; 16 | 17 | ssl_certificate /etc/nginx/ssl/crt.pem; 18 | ssl_certificate_key /etc/nginx/ssl/private.key.pem; 19 | 20 | location / { 21 | set $microservice "swagger"; 22 | proxy_pass http://$upstream; 23 | } 24 | 25 | location ~ ^/v1/(?[\w\-]+) { 26 | proxy_http_version 1.1; 27 | proxy_set_header Host $http_host; 28 | proxy_set_header X-Real-IP $remote_addr; 29 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 30 | proxy_set_header X-Forwarded-Proto http; 31 | proxy_set_header X-Frame-Options SAMEORIGIN; 32 | 33 | if ($request_method = 'OPTIONS') { 34 | add_header 'Access-Control-Allow-Origin' '*'; 35 | add_header 'Access-Control-Allow-Methods' 'GET,POST,PUT,DELETE,OPTIONS,PATCH'; 36 | add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Access-Control-Allow-Headers,Access-Control-Allow-Origin,Authorization'; 37 | add_header 'Access-Control-Max-Age' 1728000; 38 | add_header 'Content-Type' 'text/plain; charset=utf-8'; 39 | add_header 'Content-Length' 0; 40 | return 204; 41 | } 42 | 43 | add_header 'X-Microservice' '$microservice'; 44 | add_header 'X-Proxy-Pass' '$upstream'; 45 | add_header 'Access-Control-Allow-Origin' '*'; 46 | add_header 'Access-Control-Allow-Methods' 'GET,POST,PUT,DELETE,OPTIONS,PATCH'; 47 | add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Access-Control-Allow-Headers,Access-Control-Allow-Origin,Authorization'; 48 | proxy_pass http://$upstream; 49 | } 50 | } -------------------------------------------------------------------------------- /pkg/order/infra/service/order.go: -------------------------------------------------------------------------------- 1 | package ordersrvimpl 2 | 3 | import ( 4 | "context" 5 | "github.com/byorty/enterprise-application/pkg/common/collection" 6 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 7 | "github.com/byorty/enterprise-application/pkg/order/domain/service" 8 | productsrv "github.com/byorty/enterprise-application/pkg/product/domain/service" 9 | "github.com/google/uuid" 10 | "google.golang.org/protobuf/types/known/timestamppb" 11 | ) 12 | 13 | func NewFxOrderService( 14 | productService productsrv.ProductService, 15 | ) ordersrv.OrderService { 16 | return &orderService{ 17 | orders: collection.NewMap[string, *pbv1.Order](), 18 | productService: productService, 19 | } 20 | } 21 | 22 | type orderService struct { 23 | orders collection.Map[string, *pbv1.Order] 24 | productService productsrv.ProductService 25 | } 26 | 27 | func (s *orderService) Create(ctx context.Context, userUUID string, params *pbv1.CreateOrderRequestParams) (*pbv1.Order, error) { 28 | order := &pbv1.Order{ 29 | Uuid: uuid.NewString(), 30 | UserUuid: userUUID, 31 | Address: params.Address, 32 | Status: pbv1.OrderStatusCreated, 33 | Products: params.Products, 34 | CreatedAt: timestamppb.Now(), 35 | DeliveredAt: params.DeliveredAt, 36 | } 37 | 38 | for _, userProduct := range params.Products { 39 | product, err := s.productService.GetByUUID(ctx, userProduct.ProductUuid) 40 | if err != nil { 41 | return nil, err 42 | } 43 | 44 | order.Amount += product.Price * float64(userProduct.Count) 45 | } 46 | 47 | s.orders.Set(order.Uuid, order) 48 | return order, nil 49 | } 50 | 51 | func (s *orderService) Checkout(ctx context.Context, orderUUID string, params *pbv1.CheckoutOrderRequestParams) (*pbv1.Order, error) { 52 | order, ok := s.orders.Get(orderUUID) 53 | if !ok { 54 | return nil, ordersrv.ErrOrderNotFound 55 | } 56 | 57 | if order.Amount != params.Amount { 58 | return nil, ordersrv.ErrOrderAmountNotEqual 59 | } 60 | 61 | order.Status = params.Status 62 | 63 | return order, nil 64 | } 65 | 66 | func (s *orderService) GetByUUID(ctx context.Context, orderUUID string) (*pbv1.Order, error) { 67 | order, ok := s.orders.Get(orderUUID) 68 | if !ok { 69 | return nil, ordersrv.ErrOrderNotFound 70 | } 71 | 72 | return order, nil 73 | } 74 | -------------------------------------------------------------------------------- /pkg/common/collection/slice.go: -------------------------------------------------------------------------------- 1 | package collection 2 | 3 | import "sort" 4 | 5 | type SliceOption func(settings *SliceSettings) 6 | 7 | func WithSliceSize(size int) SliceOption { 8 | return func(settings *SliceSettings) { 9 | settings.size = size 10 | } 11 | } 12 | 13 | type SliceSettings struct { 14 | size int 15 | } 16 | 17 | type Slice[T any] interface { 18 | Add(items ...T) 19 | Set(i int, item T) 20 | Get(i int) T 21 | Len() int 22 | Entries() []T 23 | Iterator() Iterator[T] 24 | Remove(i int) 25 | RemoveAll() 26 | Sort(f SortFunc[T]) 27 | } 28 | 29 | type genericSlice[T any] []T 30 | 31 | func NewSlice[T any](opts ...SliceOption) Slice[T] { 32 | settings := new(SliceSettings) 33 | for _, opt := range opts { 34 | opt(settings) 35 | } 36 | 37 | l := make(genericSlice[T], settings.size) 38 | return &l 39 | } 40 | 41 | func ImportList[T any](slice ...T) Slice[T] { 42 | l := make(genericSlice[T], len(slice)) 43 | copy(l, slice) 44 | return &l 45 | } 46 | 47 | func (l *genericSlice[T]) Add(items ...T) { 48 | (*l) = append((*l), items...) 49 | } 50 | 51 | func (l *genericSlice[T]) Set(i int, item T) { 52 | (*l)[i] = item 53 | } 54 | 55 | func (l *genericSlice[T]) Get(i int) T { 56 | return (*l)[i] 57 | } 58 | 59 | func (l *genericSlice[T]) Len() int { 60 | return len(*l) 61 | } 62 | 63 | func (l *genericSlice[T]) Entries() []T { 64 | return (*l) 65 | } 66 | 67 | func (l *genericSlice[T]) Iterator() Iterator[T] { 68 | return NewSliceIterator[T](l) 69 | } 70 | 71 | func (l *genericSlice[T]) Remove(i int) { 72 | (*l) = append((*l)[:i], (*l)[i+1:]...) 73 | } 74 | 75 | func (l *genericSlice[T]) RemoveAll() { 76 | (*l) = make(genericSlice[T], 0) 77 | } 78 | 79 | func (l *genericSlice[T]) Sort(f SortFunc[T]) { 80 | sort.Sort(&sorter[T]{ 81 | list: l, 82 | f: f, 83 | }) 84 | } 85 | 86 | type SortFunc[T any] func(i, j T) bool 87 | 88 | type sorter[T any] struct { 89 | list Slice[T] 90 | f SortFunc[T] 91 | } 92 | 93 | func (s *sorter[T]) Len() int { 94 | return s.list.Len() 95 | } 96 | 97 | func (s *sorter[T]) Less(i, j int) bool { 98 | return s.f(s.list.Get(i), s.list.Get(j)) 99 | } 100 | 101 | func (s *sorter[T]) Swap(i, j int) { 102 | a := s.list.Get(i) 103 | b := s.list.Get(j) 104 | s.list.Set(i, b) 105 | s.list.Set(j, a) 106 | } 107 | -------------------------------------------------------------------------------- /pkg/user/infra/middleware/user_rights_enforcer_test.go: -------------------------------------------------------------------------------- 1 | package middleware_test 2 | 3 | import ( 4 | "context" 5 | "errors" 6 | "github.com/Pallinder/go-randomdata" 7 | "github.com/byorty/enterprise-application/pkg/common/adapter/auth" 8 | "github.com/byorty/enterprise-application/pkg/common/adapter/ctxutil" 9 | "github.com/byorty/enterprise-application/pkg/common/adapter/server/grpc" 10 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 11 | usersrv "github.com/byorty/enterprise-application/pkg/user/domain/service" 12 | "github.com/byorty/enterprise-application/pkg/user/infra/middleware" 13 | usersrvimpl "github.com/byorty/enterprise-application/pkg/user/infra/service" 14 | "github.com/stretchr/testify/suite" 15 | "google.golang.org/protobuf/reflect/protoreflect" 16 | "testing" 17 | ) 18 | 19 | func TestUserRightsEnforcerSuite(t *testing.T) { 20 | suite.Run(t, new(UserRightsEnforcerSuite)) 21 | } 22 | 23 | type UserRightsEnforcerSuite struct { 24 | suite.Suite 25 | enforcer auth.RightsEnforcer 26 | userService usersrv.UserService 27 | } 28 | 29 | func (s *UserRightsEnforcerSuite) SetupSuite() { 30 | s.userService = usersrvimpl.NewFxUserService() 31 | s.enforcer = middleware.NewUserRightsEnforcer(s.userService) 32 | } 33 | 34 | func (s *UserRightsEnforcerSuite) TestEnforce() { 35 | ctx := context.Background() 36 | userUUID := "387301f4-551c-4022-900a-80f6f76f3a10" 37 | user, err := s.userService.GetByUUID(ctx, userUUID) 38 | s.Equal(userUUID, user.Uuid) 39 | s.Nil(err) 40 | 41 | var session pbv1.Session 42 | _, err = s.enforcer.Enforce(ctx, session, protoreflect.ValueOf(randomdata.Alphanumeric(32))) 43 | s.NotNil(err) 44 | s.True(errors.Is(err, usersrv.ErrUserNotFound)) 45 | 46 | user.Status = pbv1.UserStatusBlocked 47 | _, err = s.enforcer.Enforce(ctx, session, protoreflect.ValueOf(userUUID)) 48 | s.NotNil(err) 49 | s.True(errors.Is(err, grpc.ErrSessionHasNotPermissions)) 50 | 51 | user.Status = pbv1.UserStatusActive 52 | user.Uuid = randomdata.Alphanumeric(32) 53 | _, err = s.enforcer.Enforce(ctx, session, protoreflect.ValueOf(userUUID)) 54 | s.NotNil(err) 55 | s.True(errors.Is(err, grpc.ErrSessionNotOwnEntity)) 56 | 57 | session.Uuid = userUUID 58 | user.Uuid = userUUID 59 | ctx, err = s.enforcer.Enforce(ctx, session, protoreflect.ValueOf(userUUID)) 60 | s.Nil(err) 61 | 62 | ctxUser, err := ctxutil.Get[*pbv1.User](ctx, ctxutil.User) 63 | s.Nil(err) 64 | s.Equal(userUUID, ctxUser.Uuid) 65 | } 66 | -------------------------------------------------------------------------------- /pkg/common/adapter/application/application.go: -------------------------------------------------------------------------------- 1 | package application 2 | 3 | import ( 4 | "context" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/log" 6 | "github.com/jessevdk/go-flags" 7 | "go.uber.org/fx" 8 | "os" 9 | "os/signal" 10 | "syscall" 11 | ) 12 | 13 | type Application struct { 14 | ctx context.Context 15 | cancel context.CancelFunc 16 | fxApp *fx.App 17 | logger log.Logger 18 | options []fx.Option 19 | } 20 | 21 | func New(providers ...interface{}) *Application { 22 | ctx, cancel := context.WithCancel(context.Background()) 23 | 24 | app := &Application{ 25 | options: []fx.Option{ 26 | fx.NopLogger, 27 | }, 28 | ctx: ctx, 29 | cancel: cancel, 30 | } 31 | 32 | for _, provider := range providers { 33 | switch p := provider.(type) { 34 | case fx.Option: 35 | app.options = append(app.options, p) 36 | default: 37 | app.options = append(app.options, fx.Provide(p)) 38 | } 39 | } 40 | 41 | return app 42 | } 43 | 44 | func (a *Application) Run(invoker interface{}) { 45 | var args Arguments 46 | _, err := flags.Parse(&args) 47 | if err != nil { 48 | panic(err) 49 | } 50 | 51 | a.options = append( 52 | a.options, 53 | fx.Provide(func() context.Context { 54 | return a.ctx 55 | }), 56 | fx.Provide(func() Arguments { 57 | return args 58 | }), 59 | fx.Invoke(invoker), 60 | fx.Populate(&a.logger), 61 | ) 62 | a.fxApp = fx.New(a.options...) 63 | 64 | go a.listenSignals() 65 | 66 | startCtx, cancel := context.WithTimeout(a.ctx, fx.DefaultTimeout) 67 | defer cancel() 68 | 69 | if err = a.fxApp.Start(startCtx); err != nil { 70 | if a.logger == nil { 71 | panic(err) 72 | } 73 | 74 | a.logger.Fatal(err) 75 | } 76 | } 77 | 78 | func (a *Application) Demonize(invoker interface{}) { 79 | a.Run(invoker) 80 | <-a.ctx.Done() 81 | } 82 | 83 | func (a *Application) Stop() { 84 | stopCtx, cancel := context.WithTimeout(a.ctx, fx.DefaultTimeout) 85 | defer cancel() 86 | err := a.fxApp.Stop(stopCtx) 87 | if err != nil { 88 | a.logger.Fatal(err) 89 | } 90 | a.fxApp = nil 91 | } 92 | 93 | func (a *Application) listenSignals() { 94 | signals := make(chan os.Signal, 1) 95 | signal.Notify(signals, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) 96 | for sig := range signals { 97 | a.logger.Infof("income signal %s", sig) 98 | a.Stop() 99 | a.cancel() 100 | return 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /pkg/common/adapter/auth/role_enforcer_test.go: -------------------------------------------------------------------------------- 1 | package auth_test 2 | 3 | import ( 4 | "fmt" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/application" 6 | "github.com/byorty/enterprise-application/pkg/common/adapter/auth" 7 | "github.com/byorty/enterprise-application/pkg/common/adapter/log" 8 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 9 | "github.com/stretchr/testify/suite" 10 | "go.uber.org/config" 11 | "os" 12 | "strings" 13 | "testing" 14 | ) 15 | 16 | func TestRoleEnforcerSuite(t *testing.T) { 17 | suite.Run(t, new(RoleEnforcerSuite)) 18 | } 19 | 20 | type RoleEnforcerSuite struct { 21 | suite.Suite 22 | enforcer auth.RoleEnforcer 23 | } 24 | 25 | func (s *RoleEnforcerSuite) SetupSuite() { 26 | dir, err := os.Getwd() 27 | s.Nil(err) 28 | 29 | reader := strings.NewReader(fmt.Sprintf(` 30 | enforcer: 31 | model_file: %s/model.conf 32 | policy_file: %s/policy.csv 33 | `, dir, dir)) 34 | 35 | provider, err := application.NewProviderByOptions(config.Source(reader)) 36 | s.Nil(err) 37 | 38 | s.enforcer, err = auth.NewFxRoleEnforcer( 39 | log.NewFxLogger(), 40 | provider, 41 | ) 42 | s.Nil(err) 43 | } 44 | 45 | func (s *RoleEnforcerSuite) TestConstructor() { 46 | reader := strings.NewReader(fmt.Sprintf(` 47 | enforcer: 48 | model_file: "1234" 49 | policy_file: "3455" 50 | `)) 51 | 52 | provider, err := application.NewProviderByOptions(config.Source(reader)) 53 | s.Nil(err) 54 | enf, err := auth.NewFxRoleEnforcer( 55 | log.NewFxLogger(), 56 | provider, 57 | ) 58 | s.Nil(enf) 59 | s.NotNil(err) 60 | } 61 | 62 | func (s *RoleEnforcerSuite) TestEnforce() { 63 | guestSession := pbv1.Session{ 64 | Group: pbv1.UserGroupGuest, 65 | } 66 | 67 | ok, err := s.enforcer.Enforce( 68 | guestSession, 69 | pbv1.RoleUser, 70 | pbv1.PermissionRead, 71 | ) 72 | s.Nil(err) 73 | s.True(ok) 74 | 75 | ok, err = s.enforcer.Enforce( 76 | guestSession, 77 | pbv1.RoleOrder, 78 | pbv1.PermissionRead, 79 | ) 80 | s.Nil(err) 81 | s.False(ok) 82 | 83 | customerSession := pbv1.Session{ 84 | Group: pbv1.UserGroupCustomer, 85 | } 86 | 87 | ok, err = s.enforcer.Enforce( 88 | customerSession, 89 | pbv1.RoleUser, 90 | pbv1.PermissionRead, 91 | ) 92 | s.Nil(err) 93 | s.True(ok) 94 | 95 | ok, err = s.enforcer.Enforce( 96 | customerSession, 97 | pbv1.RoleOrder, 98 | pbv1.PermissionRead, 99 | ) 100 | s.Nil(err) 101 | s.True(ok) 102 | } 103 | -------------------------------------------------------------------------------- /pkg/user/infra/middleware/user_product_right_enforcer_test.go: -------------------------------------------------------------------------------- 1 | package middleware_test 2 | 3 | import ( 4 | "context" 5 | "github.com/Pallinder/go-randomdata" 6 | "github.com/byorty/enterprise-application/pkg/common/adapter/auth" 7 | "github.com/byorty/enterprise-application/pkg/common/adapter/server/grpc" 8 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 9 | productsrcimpl "github.com/byorty/enterprise-application/pkg/product/infra/service" 10 | usersrv "github.com/byorty/enterprise-application/pkg/user/domain/service" 11 | "github.com/byorty/enterprise-application/pkg/user/infra/middleware" 12 | usersrvimpl "github.com/byorty/enterprise-application/pkg/user/infra/service" 13 | "github.com/pkg/errors" 14 | "github.com/stretchr/testify/suite" 15 | "google.golang.org/protobuf/reflect/protoreflect" 16 | "testing" 17 | ) 18 | 19 | func TestUserProductRightsEnforcerSuite(t *testing.T) { 20 | suite.Run(t, new(UserProductRightsEnforcerSuite)) 21 | } 22 | 23 | type UserProductRightsEnforcerSuite struct { 24 | suite.Suite 25 | enforcer auth.RightsEnforcer 26 | userProductService usersrv.UserProductService 27 | } 28 | 29 | func (s *UserProductRightsEnforcerSuite) SetupSuite() { 30 | productService := productsrcimpl.NewFxProductService() 31 | userService := usersrvimpl.NewFxUserService() 32 | s.userProductService = usersrvimpl.NewFxUserProductService(userService, productService) 33 | s.enforcer = middleware.NewUserProductRightsEnforcer(s.userProductService) 34 | } 35 | 36 | func (s *UserProductRightsEnforcerSuite) TestEnforce() { 37 | var session pbv1.Session 38 | ctx := context.Background() 39 | _, err := s.enforcer.Enforce(ctx, session, protoreflect.ValueOf(randomdata.Alphanumeric(32))) 40 | s.True(errors.Is(err, grpc.ErrSessionNotOwnEntity)) 41 | 42 | session.Uuid = "387301f4-551c-4022-900a-80f6f76f3a10" 43 | _, err = s.enforcer.Enforce(ctx, session, protoreflect.ValueOf(randomdata.Alphanumeric(32))) 44 | s.True(errors.Is(err, grpc.ErrSessionNotOwnEntity)) 45 | 46 | productUuid := "42d8d533-5041-4931-a8c1-f215ab69ffe7" 47 | userProducts, err := s.userProductService.Put(ctx, session.Uuid, &pbv1.PutProductRequestParams{ 48 | ProductUuid: productUuid, 49 | ProductCount: 1, 50 | }) 51 | s.NotEmpty(userProducts) 52 | s.Nil(err) 53 | 54 | _, err = s.enforcer.Enforce(ctx, session, protoreflect.ValueOf(randomdata.Alphanumeric(32))) 55 | s.True(errors.Is(err, grpc.ErrSessionNotOwnEntity)) 56 | 57 | _, err = s.enforcer.Enforce(ctx, session, protoreflect.ValueOf(userProducts[0].Uuid)) 58 | s.Nil(err) 59 | } 60 | -------------------------------------------------------------------------------- /pkg/order/infra/middleware/order_rights_enforcer_test.go: -------------------------------------------------------------------------------- 1 | package middleware_test 2 | 3 | import ( 4 | "context" 5 | "github.com/Pallinder/go-randomdata" 6 | "github.com/byorty/enterprise-application/pkg/common/adapter/auth" 7 | "github.com/byorty/enterprise-application/pkg/common/adapter/server/grpc" 8 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 9 | ordersrv "github.com/byorty/enterprise-application/pkg/order/domain/service" 10 | "github.com/byorty/enterprise-application/pkg/order/infra/middleware" 11 | ordersrvimpl "github.com/byorty/enterprise-application/pkg/order/infra/service" 12 | productsrcimpl "github.com/byorty/enterprise-application/pkg/product/infra/service" 13 | "github.com/google/uuid" 14 | "github.com/pkg/errors" 15 | "github.com/stretchr/testify/suite" 16 | "google.golang.org/protobuf/reflect/protoreflect" 17 | "google.golang.org/protobuf/types/known/timestamppb" 18 | "testing" 19 | ) 20 | 21 | func TestOrderRightsEnforcerSuite(t *testing.T) { 22 | suite.Run(t, new(OrderRightsEnforcerSuite)) 23 | } 24 | 25 | type OrderRightsEnforcerSuite struct { 26 | suite.Suite 27 | enforcer auth.RightsEnforcer 28 | orderService ordersrv.OrderService 29 | } 30 | 31 | func (s *OrderRightsEnforcerSuite) SetupSuite() { 32 | productService := productsrcimpl.NewFxProductService() 33 | s.orderService = ordersrvimpl.NewFxOrderService(productService) 34 | s.enforcer = middleware.NewOrderRightsEnforcer(s.orderService) 35 | } 36 | 37 | func (s *OrderRightsEnforcerSuite) TestEnforce() { 38 | ctx := context.Background() 39 | userUUID := "387301f4-551c-4022-900a-80f6f76f3a10" 40 | order, err := s.orderService.Create(ctx, userUUID, &pbv1.CreateOrderRequestParams{ 41 | Products: []*pbv1.UserProduct{ 42 | { 43 | Uuid: uuid.NewString(), 44 | ProductUuid: "42d8d533-5041-4931-a8c1-f215ab69ffe7", 45 | Count: 1, 46 | }, 47 | }, 48 | Address: randomdata.Address(), 49 | DeliveredAt: timestamppb.Now(), 50 | }) 51 | s.NotNil(order) 52 | s.Nil(err) 53 | 54 | var session pbv1.Session 55 | _, err = s.enforcer.Enforce(ctx, session, protoreflect.ValueOf(randomdata.Alphanumeric(32))) 56 | s.True(errors.Is(err, grpc.ErrSessionNotOwnEntity)) 57 | 58 | _, err = s.enforcer.Enforce(ctx, session, protoreflect.ValueOf(order.Uuid)) 59 | s.True(errors.Is(err, grpc.ErrSessionNotOwnEntity)) 60 | 61 | session.Uuid = userUUID 62 | _, err = s.enforcer.Enforce(ctx, session, protoreflect.ValueOf(randomdata.Alphanumeric(32))) 63 | s.True(errors.Is(err, grpc.ErrSessionNotOwnEntity)) 64 | 65 | _, err = s.enforcer.Enforce(ctx, session, protoreflect.ValueOf(order.Uuid)) 66 | s.Nil(err) 67 | } 68 | -------------------------------------------------------------------------------- /pkg/common/adapter/auth/session_manager.go: -------------------------------------------------------------------------------- 1 | package auth 2 | 3 | import ( 4 | "context" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/application" 6 | "github.com/byorty/enterprise-application/pkg/common/adapter/log" 7 | "github.com/byorty/enterprise-application/pkg/common/adapter/server/grpc" 8 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 9 | "github.com/dgrijalva/jwt-go" 10 | "time" 11 | ) 12 | 13 | type SessionManager interface { 14 | CreateTokenBySession(context.Context, pbv1.Session) (string, error) 15 | CreateToken(ctx context.Context, userUUID string, group pbv1.UserGroup) (string, error) 16 | GetSessionByToken(ctx context.Context, token string) (pbv1.Session, error) 17 | } 18 | 19 | func NewFxSessionManager( 20 | provider application.Provider, 21 | logger log.Logger, 22 | jwtHelper JWTHelper, 23 | ) (SessionManager, error) { 24 | var cfg SessionConfig 25 | err := provider.PopulateByKey("session", &cfg) 26 | if err != nil { 27 | return nil, err 28 | } 29 | 30 | return &sessionManager{ 31 | logger: logger.Named("session_manager"), 32 | cfg: cfg, 33 | jwtHelper: jwtHelper, 34 | }, nil 35 | } 36 | 37 | type sessionManager struct { 38 | logger log.Logger 39 | cfg SessionConfig 40 | jwtHelper JWTHelper 41 | } 42 | 43 | func (s *sessionManager) CreateTokenBySession(ctx context.Context, session pbv1.Session) (string, error) { 44 | claims := &SessionClaims{ 45 | StandardClaims: jwt.StandardClaims{ 46 | Audience: s.cfg.Audience, 47 | Issuer: s.cfg.Issuer, 48 | IssuedAt: time.Now().Unix(), 49 | ExpiresAt: time.Now().Add(s.cfg.Duration).Unix(), 50 | }, 51 | Session: session, 52 | } 53 | 54 | return s.jwtHelper.CreateToken(claims) 55 | } 56 | 57 | func (s *sessionManager) CreateToken(ctx context.Context, userUUID string, group pbv1.UserGroup) (string, error) { 58 | return s.CreateTokenBySession( 59 | ctx, 60 | pbv1.Session{ 61 | Uuid: userUUID, 62 | Group: group, 63 | }, 64 | ) 65 | } 66 | 67 | func (s *sessionManager) GetSessionByToken(ctx context.Context, token string) (pbv1.Session, error) { 68 | logger := s.logger.WithCtx(ctx) 69 | if len(token) == 0 { 70 | logger.Debug("guest session") 71 | return pbv1.Session{ 72 | Group: pbv1.UserGroupGuest, 73 | }, nil 74 | } 75 | 76 | claims := new(SessionClaims) 77 | err := s.jwtHelper.Parse(token, claims) 78 | if err != nil { 79 | logger.Error(err) 80 | return pbv1.Session{}, grpc.ErrUnauthenticated(grpc.ErrSessionNotFound) 81 | } 82 | 83 | logger.Debugf("b2c session=%s with group=%s", claims.Session.Uuid, claims.Session.Group) 84 | return claims.Session, nil 85 | } 86 | -------------------------------------------------------------------------------- /pkg/user/infra/service/user.go: -------------------------------------------------------------------------------- 1 | package usersrvimpl 2 | 3 | import ( 4 | "context" 5 | "github.com/Pallinder/go-randomdata" 6 | "github.com/byorty/enterprise-application/pkg/common/adapter/auth" 7 | "github.com/byorty/enterprise-application/pkg/common/collection" 8 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 9 | usersrv "github.com/byorty/enterprise-application/pkg/user/domain/service" 10 | "github.com/google/uuid" 11 | "google.golang.org/protobuf/types/known/timestamppb" 12 | ) 13 | 14 | func NewFxUserService( 15 | sessionManager auth.SessionManager, 16 | ) usersrv.UserService { 17 | return &userService{ 18 | sessionManager: sessionManager, 19 | users: collection.ImportMap[string, *pbv1.User](map[string]*pbv1.User{ 20 | "387301f4-551c-4022-900a-80f6f76f3a10": { 21 | Uuid: "387301f4-551c-4022-900a-80f6f76f3a10", 22 | Group: pbv1.UserGroupCustomer, 23 | Status: pbv1.UserStatusActive, 24 | PhoneNumber: "+79008007060", 25 | Lastname: "Иванов", 26 | Firstname: "Иван", 27 | CreatedAt: timestamppb.Now(), 28 | }, 29 | }), 30 | } 31 | } 32 | 33 | type userService struct { 34 | sessionManager auth.SessionManager 35 | users collection.Map[string, *pbv1.User] 36 | } 37 | 38 | func (s *userService) Register(ctx context.Context, phoneNumber string) (*pbv1.TokenResponse, error) { 39 | for _, user := range s.users.Entries() { 40 | if user.PhoneNumber == phoneNumber { 41 | return nil, usersrv.ErrUserAlreadyExists 42 | } 43 | } 44 | 45 | user := &pbv1.User{ 46 | Uuid: uuid.NewString(), 47 | Group: pbv1.UserGroupCustomer, 48 | Status: pbv1.UserStatusActive, 49 | PhoneNumber: phoneNumber, 50 | Lastname: randomdata.LastName(), 51 | Firstname: randomdata.FirstName(1), 52 | CreatedAt: timestamppb.Now(), 53 | } 54 | 55 | token, err := s.sessionManager.CreateToken(ctx, user.Uuid, user.Group) 56 | if err != nil { 57 | return nil, err 58 | } 59 | 60 | s.users.Set(user.Uuid, user) 61 | return &pbv1.TokenResponse{ 62 | Token: token, 63 | }, nil 64 | } 65 | 66 | func (s *userService) Authorize(ctx context.Context, phoneNumber string) (*pbv1.TokenResponse, error) { 67 | for _, user := range s.users.Entries() { 68 | if user.PhoneNumber == phoneNumber { 69 | token, err := s.sessionManager.CreateToken(ctx, user.Uuid, user.Group) 70 | if err != nil { 71 | return nil, err 72 | } 73 | 74 | return &pbv1.TokenResponse{ 75 | Token: token, 76 | }, nil 77 | } 78 | } 79 | 80 | return nil, usersrv.ErrUserNotFound 81 | } 82 | 83 | func (s *userService) GetByUUID(ctx context.Context, uuid string) (*pbv1.User, error) { 84 | user, ok := s.users.Get(uuid) 85 | if !ok { 86 | return nil, usersrv.ErrUserNotFound 87 | } 88 | 89 | return user, nil 90 | } 91 | -------------------------------------------------------------------------------- /pkg/common/adapter/server/grpc/grpc_option/enforcer.go: -------------------------------------------------------------------------------- 1 | package grpc_option 2 | 3 | import ( 4 | "context" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/auth" 6 | "github.com/byorty/enterprise-application/pkg/common/adapter/ctxutil" 7 | "github.com/byorty/enterprise-application/pkg/common/adapter/log" 8 | "github.com/byorty/enterprise-application/pkg/common/adapter/protoutil" 9 | "github.com/byorty/enterprise-application/pkg/common/adapter/server/grpc" 10 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 11 | "go.uber.org/fx" 12 | gRPC "google.golang.org/grpc" 13 | "google.golang.org/protobuf/reflect/protoreflect" 14 | ) 15 | 16 | type EnforcerOptionIn struct { 17 | fx.In 18 | Logger log.Logger 19 | RoleEnforcer auth.RoleEnforcer 20 | MethodDescriptorMap grpc.MethodDescriptorMap 21 | RightsEnforcerDescriptors []auth.RightsEnforcerDescriptor `group:"rights_enforcer"` 22 | } 23 | 24 | func NewFxEnforcerOption(in EnforcerOptionIn) grpc.MiddlewareOut { 25 | rightsEnforcers := protoutil.NewMap[auth.RightsEnforcer]() 26 | for _, descriptor := range in.RightsEnforcerDescriptors { 27 | rightsEnforcers.Set(descriptor.Name, descriptor.RightsEnforcer) 28 | } 29 | 30 | return grpc.MiddlewareOut{ 31 | GrpcMiddleware: grpc.Middleware{ 32 | Priority: 98, 33 | GrpcOption: func(ctx context.Context, req interface{}, info *gRPC.UnaryServerInfo, handler gRPC.UnaryHandler) (resp interface{}, err error) { 34 | logger := in.Logger.WithCtx(ctx, "middleware", "enforcer") 35 | methodDescriptor, ok := in.MethodDescriptorMap.GetByFullName(info.FullMethod) 36 | if !ok { 37 | return nil, grpc.ErrUnauthenticated(grpc.ErrMethodDescriptorNotFound) 38 | } 39 | 40 | session, err := ctxutil.Get[pbv1.Session](ctx, ctxutil.Session) 41 | if err != nil { 42 | return nil, grpc.ErrPermissionDenied(grpc.ErrSessionNotFound) 43 | } 44 | 45 | ok, err = in.RoleEnforcer.Enforce(session, methodDescriptor.Role, methodDescriptor.Permission) 46 | if !ok { 47 | logger.Error(err) 48 | return nil, grpc.ErrPermissionDenied(grpc.ErrSessionHasNotPermissions) 49 | } 50 | 51 | protoMessage, ok := req.(protoreflect.ProtoMessage) 52 | if ok { 53 | message := protoMessage.ProtoReflect() 54 | fields := message.Descriptor().Fields() 55 | for i := 0; i < fields.Len(); i++ { 56 | field := fields.Get(i) 57 | rightsEnforcer, err := rightsEnforcers.Get(message, field) 58 | if err != nil { 59 | logger.Error(err) 60 | continue 61 | } 62 | 63 | ctx, err = rightsEnforcer.Enforce(ctx, session, message.Get(field)) 64 | if err != nil { 65 | logger.Error(err) 66 | return nil, grpc.ErrPermissionDenied(grpc.ErrSessionNotOwnEntity) 67 | } 68 | } 69 | } 70 | 71 | return handler(ctx, req) 72 | }, 73 | }, 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /pkg/common/adapter/auth/jwt_helper_test.go: -------------------------------------------------------------------------------- 1 | package auth_test 2 | 3 | import ( 4 | "fmt" 5 | "github.com/Pallinder/go-randomdata" 6 | "github.com/byorty/enterprise-application/pkg/common/adapter/application" 7 | "github.com/byorty/enterprise-application/pkg/common/adapter/auth" 8 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 9 | "github.com/dgrijalva/jwt-go" 10 | "github.com/google/uuid" 11 | "github.com/stretchr/testify/suite" 12 | "go.uber.org/config" 13 | "os" 14 | "strings" 15 | "testing" 16 | "time" 17 | ) 18 | 19 | func TestJWTHelperSuite(t *testing.T) { 20 | suite.Run(t, new(JWTHelperSuite)) 21 | } 22 | 23 | type JWTHelperSuite struct { 24 | suite.Suite 25 | helper auth.JWTHelper 26 | } 27 | 28 | func (s *JWTHelperSuite) SetupSuite() { 29 | dir, err := os.Getwd() 30 | s.Nil(err) 31 | 32 | reader := strings.NewReader(fmt.Sprintf(` 33 | ssl: 34 | private_key_file: %s/private.key.pem 35 | public_key_file: %s/public.key.pem 36 | `, dir, dir)) 37 | 38 | provider, err := application.NewProviderByOptions(config.Source(reader)) 39 | s.Nil(err) 40 | 41 | s.helper, err = auth.NewFxJWTHelper(provider) 42 | s.Nil(err) 43 | } 44 | 45 | func (s *JWTHelperSuite) TestAll() { 46 | claims := &auth.SessionClaims{} 47 | err := s.helper.Parse(randomdata.Alphanumeric(5), claims) 48 | s.Contains(err.Error(), "token contains an invalid number of segments") 49 | 50 | claims = &auth.SessionClaims{ 51 | StandardClaims: jwt.StandardClaims{ 52 | ExpiresAt: time.Now().Add(-1 * time.Hour).Unix(), 53 | }, 54 | Session: pbv1.Session{ 55 | Uuid: "", 56 | Group: -1, 57 | }, 58 | } 59 | token, err := s.helper.CreateToken(claims) 60 | s.NotEmpty(token) 61 | s.Nil(err) 62 | 63 | err = s.helper.Parse(token, claims) 64 | s.Contains(err.Error(), "token is expired by") 65 | 66 | claims.StandardClaims.ExpiresAt = time.Now().Add(time.Hour).Unix() 67 | token, err = s.helper.CreateToken(claims) 68 | s.NotEmpty(token) 69 | s.Nil(err) 70 | 71 | err = s.helper.Parse(token, claims) 72 | s.Contains(err.Error(), "uuid is invalid") 73 | 74 | claims.Uuid = uuid.NewString() 75 | token, err = s.helper.CreateToken(claims) 76 | s.NotEmpty(token) 77 | s.Nil(err) 78 | 79 | err = s.helper.Parse(token, claims) 80 | s.Contains(err.Error(), "group is invalid") 81 | 82 | claims.Group = pbv1.UserGroupCustomer 83 | token, err = s.helper.CreateToken(claims) 84 | s.NotEmpty(token) 85 | s.Nil(err) 86 | 87 | err = s.helper.Parse(token, claims) 88 | s.Nil(err) 89 | } 90 | 91 | func (s *JWTHelperSuite) TestConstructor() { 92 | reader := strings.NewReader(fmt.Sprintf(` 93 | ssl: 94 | private_key_file: "" 95 | public_key_file: "" 96 | `)) 97 | 98 | provider, err := application.NewProviderByOptions(config.Source(reader)) 99 | s.Nil(err) 100 | 101 | s.helper, err = auth.NewFxJWTHelper(provider) 102 | s.NotNil(err) 103 | 104 | dir, err := os.Getwd() 105 | s.Nil(err) 106 | 107 | reader = strings.NewReader(fmt.Sprintf(` 108 | ssl: 109 | private_key_file: %s/private.key.pem 110 | public_key_file: "" 111 | `, dir)) 112 | 113 | provider, err = application.NewProviderByOptions(config.Source(reader)) 114 | s.Nil(err) 115 | 116 | s.helper, err = auth.NewFxJWTHelper(provider) 117 | s.NotNil(err) 118 | } 119 | -------------------------------------------------------------------------------- /pkg/user/infra/service/user_product.go: -------------------------------------------------------------------------------- 1 | package usersrvimpl 2 | 3 | import ( 4 | "context" 5 | "github.com/byorty/enterprise-application/pkg/common/collection" 6 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 7 | productsrv "github.com/byorty/enterprise-application/pkg/product/domain/service" 8 | usersrv "github.com/byorty/enterprise-application/pkg/user/domain/service" 9 | "github.com/google/uuid" 10 | "sort" 11 | ) 12 | 13 | func NewFxUserProductService( 14 | userService usersrv.UserService, 15 | productService productsrv.ProductService, 16 | ) usersrv.UserProductService { 17 | return &userProductService{ 18 | userService: userService, 19 | productService: productService, 20 | userProducts: collection.NewMap[string, collection.Slice[*pbv1.UserProduct]](), 21 | } 22 | } 23 | 24 | type userProductService struct { 25 | userService usersrv.UserService 26 | productService productsrv.ProductService 27 | userProducts collection.Map[string, collection.Slice[*pbv1.UserProduct]] 28 | } 29 | 30 | func (s *userProductService) GetAllByFilter(ctx context.Context, params pbv1.GetUserProductRequestParams) ([]*pbv1.UserProduct, error) { 31 | userProducts := collection.NewSlice[*pbv1.UserProduct]() 32 | for userUUID, products := range s.userProducts.Entries() { 33 | if len(params.UserUuidIn) > 0 { 34 | x := sort.SearchStrings(params.UserUuidIn, userUUID) 35 | if (len(params.UserUuidIn) > x && params.UserUuidIn[x] == userUUID) == false { 36 | continue 37 | } 38 | } 39 | 40 | for _, product := range products.Entries() { 41 | if len(params.UuidIn) > 0 { 42 | y := sort.SearchStrings(params.UuidIn, product.Uuid) 43 | if len(params.UuidIn) > y && params.UuidIn[y] == product.Uuid { 44 | userProducts.Add(product) 45 | } 46 | } else { 47 | userProducts.Add(product) 48 | } 49 | } 50 | } 51 | 52 | if userProducts.Len() == 0 { 53 | return nil, usersrv.ErrUserProductNotFound 54 | } 55 | 56 | return userProducts.Entries(), nil 57 | } 58 | 59 | func (s *userProductService) Put(ctx context.Context, userUUID string, params *pbv1.PutProductRequestParams) ([]*pbv1.UserProduct, error) { 60 | _, err := s.userService.GetByUUID(ctx, userUUID) 61 | if err != nil { 62 | return nil, err 63 | } 64 | 65 | userProducts, ok := s.userProducts.Get(userUUID) 66 | if !ok { 67 | userProducts = collection.NewSlice[*pbv1.UserProduct]() 68 | s.userProducts.Set(userUUID, userProducts) 69 | } 70 | 71 | _, err = s.productService.GetByUUID(ctx, params.ProductUuid) 72 | if err != nil { 73 | return nil, err 74 | } 75 | 76 | userProducts.Add(&pbv1.UserProduct{ 77 | Uuid: uuid.NewString(), 78 | ProductUuid: params.ProductUuid, 79 | Count: params.ProductCount, 80 | }) 81 | 82 | return userProducts.Entries(), nil 83 | } 84 | 85 | func (s *userProductService) Change(ctx context.Context, userUUID string, userProductUUID string, params *pbv1.ChangeProductRequestParams) ([]*pbv1.UserProduct, error) { 86 | _, err := s.userService.GetByUUID(ctx, userUUID) 87 | if err != nil { 88 | return nil, err 89 | } 90 | 91 | userProducts, ok := s.userProducts.Get(userUUID) 92 | if !ok { 93 | return nil, usersrv.ErrUserProductNotFound 94 | } 95 | 96 | for i, userProduct := range userProducts.Entries() { 97 | if userProduct.Uuid == userProductUUID { 98 | userProduct.Count = params.Count 99 | 100 | if userProduct.Count <= 0 { 101 | userProducts.Remove(i) 102 | } 103 | } 104 | } 105 | 106 | return userProducts.Entries(), nil 107 | } 108 | -------------------------------------------------------------------------------- /pkg/product/infra/service/product.go: -------------------------------------------------------------------------------- 1 | package productsrcimpl 2 | 3 | import ( 4 | "context" 5 | "github.com/byorty/enterprise-application/pkg/common/collection" 6 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 7 | productsrv "github.com/byorty/enterprise-application/pkg/product/domain/service" 8 | "google.golang.org/protobuf/types/known/timestamppb" 9 | "strings" 10 | ) 11 | 12 | func NewFxProductService() productsrv.ProductService { 13 | return &productService{ 14 | products: collection.ImportMap[string, *pbv1.Product](map[string]*pbv1.Product{ 15 | "42d8d533-5041-4931-a8c1-f215ab69ffe7": { 16 | Uuid: "42d8d533-5041-4931-a8c1-f215ab69ffe7", 17 | Status: pbv1.ProductStatusActive, 18 | Name: "iPhone 13 Pro 256GB", 19 | Price: 107000, 20 | Availability: true, 21 | CreatedAt: timestamppb.Now(), 22 | Properties: []*pbv1.ProductProperty{ 23 | { 24 | Name: "Цвет товара", 25 | Value: "Графитовый", 26 | }, 27 | { 28 | Name: "Процессор", 29 | Value: "Apple A15 Bionic", 30 | }, 31 | { 32 | Name: "Встроенная память", 33 | Value: "256 ГБ", 34 | }, 35 | }, 36 | }, 37 | "d51fcd7e-3899-4592-a7cf-06a04a623ed3": { 38 | Uuid: "d51fcd7e-3899-4592-a7cf-06a04a623ed3", 39 | Status: pbv1.ProductStatusActive, 40 | Name: "iPhone 13 128GB", 41 | Price: 98000, 42 | Availability: true, 43 | CreatedAt: timestamppb.Now(), 44 | Properties: []*pbv1.ProductProperty{ 45 | { 46 | Name: "Цвет товара", 47 | Value: "Сияющая звезда", 48 | }, 49 | { 50 | Name: "Процессор", 51 | Value: "Apple A15 Bionic", 52 | }, 53 | { 54 | Name: "Встроенная память", 55 | Value: "128 ГБ", 56 | }, 57 | }, 58 | }, 59 | "9dcd0f0b-79c8-4649-b91f-9a216260c36f": { 60 | Uuid: "9dcd0f0b-79c8-4649-b91f-9a216260c36f", 61 | Status: pbv1.ProductStatusActive, 62 | Name: "Apple Watch Series 7 45 мм Aluminium Case", 63 | Price: 42490, 64 | Availability: true, 65 | CreatedAt: timestamppb.Now(), 66 | Properties: []*pbv1.ProductProperty{ 67 | { 68 | Name: "Цвет товара", 69 | Value: "Темная ночь", 70 | }, 71 | { 72 | Name: "Материал корпуса", 73 | Value: "Алюминий", 74 | }, 75 | { 76 | Name: "Размер корпуса", 77 | Value: "45 мм", 78 | }, 79 | }, 80 | }, 81 | }), 82 | } 83 | } 84 | 85 | type productService struct { 86 | products collection.Map[string, *pbv1.Product] 87 | } 88 | 89 | func (s *productService) GetAllByFilter(ctx context.Context, params *pbv1.ProductsRequestFilter, paginator *pbv1.Paginator) ([]*pbv1.Product, uint32, error) { 90 | products := collection.NewSlice[*pbv1.Product]() 91 | for _, product := range s.products.Entries() { 92 | if params != nil { 93 | if params.PriceLt > 0 && product.Price > params.PriceLt { 94 | continue 95 | } 96 | 97 | if params.PriceGt > 0 && product.Price < params.PriceGt { 98 | continue 99 | } 100 | 101 | if len(params.NameContains) > 0 && !strings.Contains(product.Name, params.NameContains) { 102 | continue 103 | } 104 | } 105 | 106 | products.Add(product) 107 | } 108 | 109 | return products.Entries(), uint32(products.Len()), nil 110 | } 111 | 112 | func (s *productService) GetByUUID(ctx context.Context, uuid string) (*pbv1.Product, error) { 113 | product, ok := s.products.Get(uuid) 114 | if !ok { 115 | return nil, productsrv.ErrProductNotFound 116 | } 117 | 118 | return product, nil 119 | } 120 | -------------------------------------------------------------------------------- /pkg/common/gen/api/proto/v1/header.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.28.0 4 | // protoc (unknown) 5 | // source: api/proto/v1/header.proto 6 | 7 | package pbv1 8 | 9 | import ( 10 | _ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options" 11 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 12 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 13 | reflect "reflect" 14 | ) 15 | 16 | const ( 17 | // Verify that this generated code is sufficiently up-to-date. 18 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 19 | // Verify that runtime/protoimpl is sufficiently up-to-date. 20 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 21 | ) 22 | 23 | var File_api_proto_v1_header_proto protoreflect.FileDescriptor 24 | 25 | var file_api_proto_v1_header_proto_rawDesc = []byte{ 26 | 0x0a, 0x19, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x2f, 0x68, 27 | 0x65, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x62, 0x2e, 28 | 0x76, 0x31, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x6f, 29 | 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 30 | 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 31 | 0x74, 0x6f, 0x42, 0xcb, 0x01, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 32 | 0x6d, 0x2f, 0x62, 0x79, 0x6f, 0x72, 0x74, 0x79, 0x2f, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 33 | 0x69, 0x73, 0x65, 0x2d, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 34 | 0x70, 0x6b, 0x67, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 35 | 0x62, 0x76, 0x31, 0x92, 0x41, 0x89, 0x01, 0x12, 0x21, 0x0a, 0x1a, 0x45, 0x6e, 0x74, 0x65, 0x72, 36 | 0x70, 0x72, 0x69, 0x73, 0x65, 0x20, 0x41, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 37 | 0x6e, 0x20, 0x41, 0x50, 0x49, 0x32, 0x03, 0x31, 0x2e, 0x30, 0x1a, 0x1c, 0x65, 0x6e, 0x74, 0x65, 38 | 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 39 | 0x6f, 0x6e, 0x2e, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2a, 0x01, 0x02, 0x32, 0x10, 0x61, 0x70, 0x70, 40 | 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x3a, 0x10, 0x61, 41 | 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x5a, 42 | 0x1f, 0x0a, 0x1d, 0x0a, 0x06, 0x42, 0x65, 0x61, 0x72, 0x65, 0x72, 0x12, 0x13, 0x08, 0x02, 0x1a, 43 | 0x0d, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x02, 44 | 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 45 | } 46 | 47 | var file_api_proto_v1_header_proto_goTypes = []interface{}{} 48 | var file_api_proto_v1_header_proto_depIdxs = []int32{ 49 | 0, // [0:0] is the sub-list for method output_type 50 | 0, // [0:0] is the sub-list for method input_type 51 | 0, // [0:0] is the sub-list for extension type_name 52 | 0, // [0:0] is the sub-list for extension extendee 53 | 0, // [0:0] is the sub-list for field type_name 54 | } 55 | 56 | func init() { file_api_proto_v1_header_proto_init() } 57 | func file_api_proto_v1_header_proto_init() { 58 | if File_api_proto_v1_header_proto != nil { 59 | return 60 | } 61 | type x struct{} 62 | out := protoimpl.TypeBuilder{ 63 | File: protoimpl.DescBuilder{ 64 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 65 | RawDescriptor: file_api_proto_v1_header_proto_rawDesc, 66 | NumEnums: 0, 67 | NumMessages: 0, 68 | NumExtensions: 0, 69 | NumServices: 0, 70 | }, 71 | GoTypes: file_api_proto_v1_header_proto_goTypes, 72 | DependencyIndexes: file_api_proto_v1_header_proto_depIdxs, 73 | }.Build() 74 | File_api_proto_v1_header_proto = out.File 75 | file_api_proto_v1_header_proto_rawDesc = nil 76 | file_api_proto_v1_header_proto_goTypes = nil 77 | file_api_proto_v1_header_proto_depIdxs = nil 78 | } 79 | -------------------------------------------------------------------------------- /pkg/common/gen/api/proto/v1/order_service_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.2.0 4 | // - protoc (unknown) 5 | // source: api/proto/v1/order_service.proto 6 | 7 | package pbv1 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | ) 15 | 16 | // This is a compile-time assertion to ensure that this generated file 17 | // is compatible with the grpc package it is being compiled against. 18 | // Requires gRPC-Go v1.32.0 or later. 19 | const _ = grpc.SupportPackageIsVersion7 20 | 21 | // OrderServiceClient is the client API for OrderService service. 22 | // 23 | // 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. 24 | type OrderServiceClient interface { 25 | Checkout(ctx context.Context, in *CheckoutOrderRequest, opts ...grpc.CallOption) (*Order, error) 26 | } 27 | 28 | type orderServiceClient struct { 29 | cc grpc.ClientConnInterface 30 | } 31 | 32 | func NewOrderServiceClient(cc grpc.ClientConnInterface) OrderServiceClient { 33 | return &orderServiceClient{cc} 34 | } 35 | 36 | func (c *orderServiceClient) Checkout(ctx context.Context, in *CheckoutOrderRequest, opts ...grpc.CallOption) (*Order, error) { 37 | out := new(Order) 38 | err := c.cc.Invoke(ctx, "/pb.v1.OrderService/Checkout", in, out, opts...) 39 | if err != nil { 40 | return nil, err 41 | } 42 | return out, nil 43 | } 44 | 45 | // OrderServiceServer is the server API for OrderService service. 46 | // All implementations should embed UnimplementedOrderServiceServer 47 | // for forward compatibility 48 | type OrderServiceServer interface { 49 | Checkout(context.Context, *CheckoutOrderRequest) (*Order, error) 50 | } 51 | 52 | // UnimplementedOrderServiceServer should be embedded to have forward compatible implementations. 53 | type UnimplementedOrderServiceServer struct { 54 | } 55 | 56 | func (UnimplementedOrderServiceServer) Checkout(context.Context, *CheckoutOrderRequest) (*Order, error) { 57 | return nil, status.Errorf(codes.Unimplemented, "method Checkout not implemented") 58 | } 59 | 60 | // UnsafeOrderServiceServer may be embedded to opt out of forward compatibility for this service. 61 | // Use of this interface is not recommended, as added methods to OrderServiceServer will 62 | // result in compilation errors. 63 | type UnsafeOrderServiceServer interface { 64 | mustEmbedUnimplementedOrderServiceServer() 65 | } 66 | 67 | func RegisterOrderServiceServer(s grpc.ServiceRegistrar, srv OrderServiceServer) { 68 | s.RegisterService(&OrderService_ServiceDesc, srv) 69 | } 70 | 71 | func _OrderService_Checkout_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 72 | in := new(CheckoutOrderRequest) 73 | if err := dec(in); err != nil { 74 | return nil, err 75 | } 76 | if interceptor == nil { 77 | return srv.(OrderServiceServer).Checkout(ctx, in) 78 | } 79 | info := &grpc.UnaryServerInfo{ 80 | Server: srv, 81 | FullMethod: "/pb.v1.OrderService/Checkout", 82 | } 83 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 84 | return srv.(OrderServiceServer).Checkout(ctx, req.(*CheckoutOrderRequest)) 85 | } 86 | return interceptor(ctx, in, info, handler) 87 | } 88 | 89 | // OrderService_ServiceDesc is the grpc.ServiceDesc for OrderService service. 90 | // It's only intended for direct use with grpc.RegisterService, 91 | // and not to be introspected or modified (even as a copy) 92 | var OrderService_ServiceDesc = grpc.ServiceDesc{ 93 | ServiceName: "pb.v1.OrderService", 94 | HandlerType: (*OrderServiceServer)(nil), 95 | Methods: []grpc.MethodDesc{ 96 | { 97 | MethodName: "Checkout", 98 | Handler: _OrderService_Checkout_Handler, 99 | }, 100 | }, 101 | Streams: []grpc.StreamDesc{}, 102 | Metadata: "api/proto/v1/order_service.proto", 103 | } 104 | -------------------------------------------------------------------------------- /pkg/user/infra/app/server.go: -------------------------------------------------------------------------------- 1 | package userapp 2 | 3 | import ( 4 | "context" 5 | "github.com/byorty/enterprise-application/pkg/common/adapter/server/grpc" 6 | pbv1 "github.com/byorty/enterprise-application/pkg/common/gen/api/proto/v1" 7 | ordersrv "github.com/byorty/enterprise-application/pkg/order/domain/service" 8 | usersrv "github.com/byorty/enterprise-application/pkg/user/domain/service" 9 | "github.com/byorty/enterprise-application/pkg/user/infra/form" 10 | ) 11 | 12 | var _ pbv1.UserServiceServer = (*server)(nil) 13 | 14 | func NewFxUserServiceServer( 15 | userService usersrv.UserService, 16 | userProductService usersrv.UserProductService, 17 | orderService ordersrv.OrderService, 18 | ) grpc.Descriptor { 19 | return grpc.Descriptor{ 20 | Server: &server{ 21 | userService: userService, 22 | userProductService: userProductService, 23 | orderService: orderService, 24 | }, 25 | GRPCRegistrar: pbv1.RegisterUserServiceServer, 26 | GRPCGatewayRegistrar: pbv1.RegisterUserServiceHandlerFromEndpoint, 27 | MethodDescriptors: []grpc.MethodDescriptor{ 28 | { 29 | Method: (*server).Register, 30 | Role: pbv1.RoleUser, 31 | Permission: pbv1.PermissionWrite, 32 | Form: form.PhoneNumber, 33 | }, 34 | { 35 | Method: (*server).Authorize, 36 | Role: pbv1.RoleUser, 37 | Permission: pbv1.PermissionWrite, 38 | Form: form.PhoneNumber, 39 | }, 40 | { 41 | Method: (*server).GetByUUID, 42 | Role: pbv1.RoleUser, 43 | Permission: pbv1.PermissionRead, 44 | Form: form.UserUUID, 45 | }, 46 | { 47 | Method: (*server).GetUserProducts, 48 | Role: pbv1.RoleUser, 49 | Permission: pbv1.PermissionRead, 50 | Form: form.UserUUID, 51 | }, 52 | { 53 | Method: (*server).PutProduct, 54 | Role: pbv1.RoleUserProduct, 55 | Permission: pbv1.PermissionRead, 56 | Form: form.PutProduct, 57 | }, 58 | { 59 | Method: (*server).ChangeProduct, 60 | Role: pbv1.RoleUserProduct, 61 | Permission: pbv1.PermissionRead, 62 | Form: form.ChangeProduct, 63 | }, 64 | { 65 | Method: (*server).CreateOrder, 66 | Role: pbv1.RoleOrder, 67 | Permission: pbv1.PermissionWrite, 68 | Form: form.CreateOrder, 69 | }, 70 | }, 71 | } 72 | } 73 | 74 | type server struct { 75 | userService usersrv.UserService 76 | userProductService usersrv.UserProductService 77 | orderService ordersrv.OrderService 78 | } 79 | 80 | func (s server) Register(ctx context.Context, request *pbv1.RegisterRequest) (*pbv1.TokenResponse, error) { 81 | return s.userService.Register(ctx, request.PhoneNumber) 82 | } 83 | 84 | func (s server) Authorize(ctx context.Context, request *pbv1.AuthorizeRequest) (*pbv1.TokenResponse, error) { 85 | return s.userService.Authorize(ctx, request.PhoneNumber) 86 | } 87 | 88 | func (s server) GetByUUID(ctx context.Context, request *pbv1.GetByUserUUIDRequest) (*pbv1.User, error) { 89 | return s.userService.GetByUUID(ctx, request.UserUuid) 90 | } 91 | 92 | func (s server) GetUserProducts(ctx context.Context, request *pbv1.GetByUserUUIDRequest) (*pbv1.UserProductsResponse, error) { 93 | userProducts, err := s.userProductService.GetAllByFilter( 94 | ctx, 95 | pbv1.GetUserProductRequestParams{ 96 | UserUuidIn: []string{request.UserUuid}, 97 | }) 98 | return &pbv1.UserProductsResponse{ 99 | Products: userProducts, 100 | }, err 101 | } 102 | 103 | func (s server) PutProduct(ctx context.Context, request *pbv1.PutProductRequest) (*pbv1.UserProductsResponse, error) { 104 | userProducts, err := s.userProductService.Put(ctx, request.UserUuid, request.Params) 105 | return &pbv1.UserProductsResponse{ 106 | Products: userProducts, 107 | }, err 108 | } 109 | 110 | func (s server) ChangeProduct(ctx context.Context, request *pbv1.ChangeProductRequest) (*pbv1.UserProductsResponse, error) { 111 | userProducts, err := s.userProductService.Change(ctx, request.UserUuid, request.UserProductUuid, request.Params) 112 | return &pbv1.UserProductsResponse{ 113 | Products: userProducts, 114 | }, err 115 | } 116 | 117 | func (s *server) CreateOrder(ctx context.Context, request *pbv1.CreateOrderRequest) (*pbv1.Order, error) { 118 | return s.orderService.Create(ctx, request.UserUuid, request.Params) 119 | } 120 | -------------------------------------------------------------------------------- /pkg/common/adapter/server/grpc/server.go: -------------------------------------------------------------------------------- 1 | package grpc 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "github.com/byorty/enterprise-application/pkg/common/adapter/application" 7 | "github.com/byorty/enterprise-application/pkg/common/adapter/log" 8 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 9 | "go.uber.org/fx" 10 | "google.golang.org/grpc" 11 | "google.golang.org/grpc/credentials/insecure" 12 | "net" 13 | "net/http" 14 | "reflect" 15 | "sort" 16 | ) 17 | 18 | type Middleware struct { 19 | Priority int 20 | GrpcOption grpc.UnaryServerInterceptor 21 | MuxOption runtime.ServeMuxOption 22 | } 23 | 24 | type ByPriority []Middleware 25 | 26 | func (b ByPriority) Len() int { 27 | return len(b) 28 | } 29 | 30 | func (b ByPriority) Swap(i, j int) { 31 | b[i], b[j] = b[j], b[i] 32 | } 33 | 34 | func (b ByPriority) Less(i, j int) bool { 35 | return b[i].Priority > b[j].Priority 36 | } 37 | 38 | type MiddlewareOut struct { 39 | fx.Out 40 | GrpcMiddleware Middleware `group:"grpc_middleware"` 41 | MuxMiddleware Middleware `group:"mux_middleware"` 42 | } 43 | 44 | type Server interface { 45 | Register(descriptor Descriptor) error 46 | Start() error 47 | } 48 | 49 | type Descriptor struct { 50 | Server interface{} 51 | GRPCRegistrar interface{} 52 | GRPCGatewayRegistrar func(context.Context, *runtime.ServeMux, string, []grpc.DialOption) error 53 | MethodDescriptors []MethodDescriptor 54 | } 55 | 56 | type FxServerIn struct { 57 | fx.In 58 | Ctx context.Context 59 | Logger log.Logger 60 | ConfigProvider application.Provider 61 | GrpcMiddlewares []Middleware `group:"grpc_middleware"` 62 | MuxMiddlewares []Middleware `group:"mux_middleware"` 63 | } 64 | 65 | func NewFxServer( 66 | in FxServerIn, 67 | ) (Server, error) { 68 | var cfg Config 69 | err := in.ConfigProvider.PopulateByKey("server", &cfg) 70 | if err != nil { 71 | return nil, err 72 | } 73 | 74 | sort.Sort(ByPriority(in.MuxMiddlewares)) 75 | sort.Sort(ByPriority(in.GrpcMiddlewares)) 76 | 77 | interceptors := make([]grpc.UnaryServerInterceptor, 0) 78 | for _, middleware := range in.GrpcMiddlewares { 79 | if middleware.GrpcOption != nil { 80 | interceptors = append(interceptors, middleware.GrpcOption) 81 | } 82 | } 83 | 84 | serverMuxOptions := make([]runtime.ServeMuxOption, 0) 85 | for _, middleware := range in.MuxMiddlewares { 86 | if middleware.MuxOption != nil { 87 | serverMuxOptions = append(serverMuxOptions, middleware.MuxOption) 88 | } 89 | } 90 | 91 | srv := &server{ 92 | ctx: in.Ctx, 93 | cfg: cfg, 94 | logger: in.Logger.Named("grpc"), 95 | grpcServer: grpc.NewServer( 96 | grpc.MaxRecvMsgSize(cfg.MaxReceiveMessageLength), 97 | grpc.MaxSendMsgSize(cfg.MaxSendMessageLength), 98 | grpc.ChainUnaryInterceptor(interceptors...), 99 | ), 100 | mux: runtime.NewServeMux( 101 | serverMuxOptions..., 102 | ), 103 | opts: []grpc.DialOption{ 104 | grpc.WithTransportCredentials(insecure.NewCredentials()), 105 | grpc.WithDefaultCallOptions( 106 | grpc.MaxCallRecvMsgSize(cfg.MaxReceiveMessageLength), 107 | grpc.MaxCallSendMsgSize(cfg.MaxSendMessageLength), 108 | ), 109 | }, 110 | errors: make(chan error, 1), 111 | } 112 | 113 | return srv, nil 114 | } 115 | 116 | type server struct { 117 | ctx context.Context 118 | logger log.Logger 119 | cfg Config 120 | grpcServer *grpc.Server 121 | gatewayServer *http.Server 122 | mux *runtime.ServeMux 123 | opts []grpc.DialOption 124 | errors chan error 125 | } 126 | 127 | func (s *server) Register(descriptor Descriptor) error { 128 | reflect.ValueOf(descriptor.GRPCRegistrar).Call([]reflect.Value{ 129 | reflect.ValueOf(s.grpcServer), 130 | reflect.ValueOf(descriptor.Server), 131 | }) 132 | if descriptor.GRPCGatewayRegistrar != nil { 133 | return descriptor.GRPCGatewayRegistrar(s.ctx, s.mux, fmt.Sprintf("%s:%d", s.cfg.Host, s.cfg.GrpcPort), s.opts) 134 | } 135 | 136 | return nil 137 | } 138 | 139 | func (s *server) Start() error { 140 | go func(logger log.Logger) { 141 | netAddress := fmt.Sprintf("%s:%d", s.cfg.Host, s.cfg.GrpcPort) 142 | 143 | logger.Infof("start server at %s", netAddress) 144 | socket, err := net.Listen("tcp", netAddress) 145 | if err != nil { 146 | s.errors <- err 147 | return 148 | } 149 | 150 | s.errors <- s.grpcServer.Serve(socket) 151 | }(s.logger.Named("grpc_server")) 152 | 153 | go func(logger log.Logger) { 154 | netAddress := fmt.Sprintf("%s:%d", s.cfg.Host, s.cfg.HttpPort) 155 | 156 | s.gatewayServer = &http.Server{ 157 | Addr: netAddress, 158 | Handler: s.mux, 159 | } 160 | 161 | logger.Infof("start gateway at %s", netAddress) 162 | 163 | s.errors <- s.gatewayServer.ListenAndServe() 164 | }(s.logger.Named("http_server")) 165 | 166 | return <-s.errors 167 | } 168 | -------------------------------------------------------------------------------- /api/proto/v1/user_service.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package pb.v1; 4 | 5 | option go_package = "github.com/byorty/enterprise-application/pkg/common/gen/pbv1"; 6 | 7 | import "google/api/annotations.proto"; 8 | import "protoc-gen-openapiv2/options/annotations.proto"; 9 | import "google/protobuf/timestamp.proto"; 10 | import "api/proto/v1/common.proto"; 11 | import "api/proto/v1/order.proto"; 12 | import "api/proto/v1/user.proto"; 13 | 14 | service UserService { 15 | rpc Register(RegisterRequest) returns (TokenResponse) { 16 | option (google.api.http) = { 17 | post: "/v1/users/register"; 18 | body: "*"; 19 | }; 20 | option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { 21 | summary: "Регистрация пользователя"; 22 | }; 23 | }; 24 | rpc Authorize(AuthorizeRequest) returns (TokenResponse) { 25 | option (google.api.http) = { 26 | post: "/v1/users/authorize"; 27 | body: "*"; 28 | }; 29 | option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { 30 | summary: "Авторизация пользователя"; 31 | }; 32 | }; 33 | rpc GetByUUID(GetByUserUUIDRequest) returns (User) { 34 | option (google.api.http) = { 35 | get: "/v1/users/{user_uuid}"; 36 | }; 37 | option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { 38 | summary: "Получение пользователя по UUID"; 39 | security: { 40 | security_requirement: { 41 | key: "Bearer" 42 | value: {} 43 | } 44 | }; 45 | }; 46 | }; 47 | rpc GetUserProducts(GetByUserUUIDRequest) returns (UserProductsResponse) { 48 | option (google.api.http) = { 49 | get: "/v1/users/{user_uuid}/products"; 50 | }; 51 | option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { 52 | summary: "Получение товаров в корзине"; 53 | security: { 54 | security_requirement: { 55 | key: "Bearer" 56 | value: {} 57 | } 58 | }; 59 | }; 60 | }; 61 | rpc PutProduct(PutProductRequest) returns (UserProductsResponse) { 62 | option (google.api.http) = { 63 | post: "/v1/users/{user_uuid}/products"; 64 | body: "params"; 65 | }; 66 | option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { 67 | summary: "Добавление товара в корзину"; 68 | security: { 69 | security_requirement: { 70 | key: "Bearer" 71 | value: {} 72 | } 73 | }; 74 | }; 75 | }; 76 | rpc ChangeProduct(ChangeProductRequest) returns (UserProductsResponse) { 77 | option (google.api.http) = { 78 | patch: "/v1/users/{user_uuid}/products/{user_product_uuid}"; 79 | body: "params"; 80 | }; 81 | option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { 82 | summary: "Изменение количества товара в корзине"; 83 | security: { 84 | security_requirement: { 85 | key: "Bearer" 86 | value: {} 87 | } 88 | }; 89 | }; 90 | }; 91 | rpc CreateOrder(CreateOrderRequest) returns (Order) { 92 | option (google.api.http) = { 93 | post: "/v1/users/{user_uuid}/orders"; 94 | body: "params"; 95 | }; 96 | option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { 97 | summary: "Создание заказа"; 98 | security: { 99 | security_requirement: { 100 | key: "Bearer" 101 | value: {} 102 | } 103 | }; 104 | }; 105 | }; 106 | } 107 | 108 | message RegisterRequest { 109 | option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = { 110 | json_schema: { 111 | required: ["phone_number"] 112 | } 113 | }; 114 | string phone_number = 1; 115 | } 116 | 117 | message TokenResponse { 118 | string token = 1; 119 | } 120 | 121 | message AuthorizeRequest { 122 | option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_schema) = { 123 | json_schema: { 124 | required: ["phone_number"] 125 | } 126 | }; 127 | string phone_number = 1; 128 | } 129 | 130 | message GetByUserUUIDRequest { 131 | string user_uuid = 1; 132 | } 133 | 134 | message UserProductsResponse { 135 | repeated UserProduct products = 1; 136 | uint32 count = 2; 137 | } 138 | 139 | message GetUserProductRequestParams { 140 | repeated string uuid_in = 1; 141 | repeated string user_uuid_in = 2; 142 | repeated string product_uuid_in = 3; 143 | } 144 | 145 | message PutProductRequest { 146 | string user_uuid = 1; 147 | PutProductRequestParams params = 2; 148 | } 149 | 150 | message PutProductRequestParams { 151 | string product_uuid = 1; 152 | uint32 product_count = 2; 153 | } 154 | 155 | message ChangeProductRequest { 156 | string user_uuid = 1; 157 | string user_product_uuid = 2; 158 | ChangeProductRequestParams params = 3; 159 | } 160 | 161 | message ChangeProductRequestParams { 162 | uint32 count = 1; 163 | } 164 | 165 | message CreateOrderRequest { 166 | string user_uuid = 1; 167 | CreateOrderRequestParams params = 3; 168 | } 169 | 170 | message CreateOrderRequestParams { 171 | repeated UserProduct products = 1; 172 | string address = 2; 173 | google.protobuf.Timestamp delivered_at = 3; 174 | } -------------------------------------------------------------------------------- /pkg/common/gen/api/proto/v1/product_service_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.2.0 4 | // - protoc (unknown) 5 | // source: api/proto/v1/product_service.proto 6 | 7 | package pbv1 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | ) 15 | 16 | // This is a compile-time assertion to ensure that this generated file 17 | // is compatible with the grpc package it is being compiled against. 18 | // Requires gRPC-Go v1.32.0 or later. 19 | const _ = grpc.SupportPackageIsVersion7 20 | 21 | // ProductServiceClient is the client API for ProductService service. 22 | // 23 | // 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. 24 | type ProductServiceClient interface { 25 | GetAllByFilter(ctx context.Context, in *ProductsRequest, opts ...grpc.CallOption) (*ProductResponse, error) 26 | GetByUUID(ctx context.Context, in *GetByProductUUIDRequest, opts ...grpc.CallOption) (*Product, error) 27 | } 28 | 29 | type productServiceClient struct { 30 | cc grpc.ClientConnInterface 31 | } 32 | 33 | func NewProductServiceClient(cc grpc.ClientConnInterface) ProductServiceClient { 34 | return &productServiceClient{cc} 35 | } 36 | 37 | func (c *productServiceClient) GetAllByFilter(ctx context.Context, in *ProductsRequest, opts ...grpc.CallOption) (*ProductResponse, error) { 38 | out := new(ProductResponse) 39 | err := c.cc.Invoke(ctx, "/pb.v1.ProductService/GetAllByFilter", in, out, opts...) 40 | if err != nil { 41 | return nil, err 42 | } 43 | return out, nil 44 | } 45 | 46 | func (c *productServiceClient) GetByUUID(ctx context.Context, in *GetByProductUUIDRequest, opts ...grpc.CallOption) (*Product, error) { 47 | out := new(Product) 48 | err := c.cc.Invoke(ctx, "/pb.v1.ProductService/GetByUUID", in, out, opts...) 49 | if err != nil { 50 | return nil, err 51 | } 52 | return out, nil 53 | } 54 | 55 | // ProductServiceServer is the server API for ProductService service. 56 | // All implementations should embed UnimplementedProductServiceServer 57 | // for forward compatibility 58 | type ProductServiceServer interface { 59 | GetAllByFilter(context.Context, *ProductsRequest) (*ProductResponse, error) 60 | GetByUUID(context.Context, *GetByProductUUIDRequest) (*Product, error) 61 | } 62 | 63 | // UnimplementedProductServiceServer should be embedded to have forward compatible implementations. 64 | type UnimplementedProductServiceServer struct { 65 | } 66 | 67 | func (UnimplementedProductServiceServer) GetAllByFilter(context.Context, *ProductsRequest) (*ProductResponse, error) { 68 | return nil, status.Errorf(codes.Unimplemented, "method GetAllByFilter not implemented") 69 | } 70 | func (UnimplementedProductServiceServer) GetByUUID(context.Context, *GetByProductUUIDRequest) (*Product, error) { 71 | return nil, status.Errorf(codes.Unimplemented, "method GetByUUID not implemented") 72 | } 73 | 74 | // UnsafeProductServiceServer may be embedded to opt out of forward compatibility for this service. 75 | // Use of this interface is not recommended, as added methods to ProductServiceServer will 76 | // result in compilation errors. 77 | type UnsafeProductServiceServer interface { 78 | mustEmbedUnimplementedProductServiceServer() 79 | } 80 | 81 | func RegisterProductServiceServer(s grpc.ServiceRegistrar, srv ProductServiceServer) { 82 | s.RegisterService(&ProductService_ServiceDesc, srv) 83 | } 84 | 85 | func _ProductService_GetAllByFilter_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 86 | in := new(ProductsRequest) 87 | if err := dec(in); err != nil { 88 | return nil, err 89 | } 90 | if interceptor == nil { 91 | return srv.(ProductServiceServer).GetAllByFilter(ctx, in) 92 | } 93 | info := &grpc.UnaryServerInfo{ 94 | Server: srv, 95 | FullMethod: "/pb.v1.ProductService/GetAllByFilter", 96 | } 97 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 98 | return srv.(ProductServiceServer).GetAllByFilter(ctx, req.(*ProductsRequest)) 99 | } 100 | return interceptor(ctx, in, info, handler) 101 | } 102 | 103 | func _ProductService_GetByUUID_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 104 | in := new(GetByProductUUIDRequest) 105 | if err := dec(in); err != nil { 106 | return nil, err 107 | } 108 | if interceptor == nil { 109 | return srv.(ProductServiceServer).GetByUUID(ctx, in) 110 | } 111 | info := &grpc.UnaryServerInfo{ 112 | Server: srv, 113 | FullMethod: "/pb.v1.ProductService/GetByUUID", 114 | } 115 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 116 | return srv.(ProductServiceServer).GetByUUID(ctx, req.(*GetByProductUUIDRequest)) 117 | } 118 | return interceptor(ctx, in, info, handler) 119 | } 120 | 121 | // ProductService_ServiceDesc is the grpc.ServiceDesc for ProductService service. 122 | // It's only intended for direct use with grpc.RegisterService, 123 | // and not to be introspected or modified (even as a copy) 124 | var ProductService_ServiceDesc = grpc.ServiceDesc{ 125 | ServiceName: "pb.v1.ProductService", 126 | HandlerType: (*ProductServiceServer)(nil), 127 | Methods: []grpc.MethodDesc{ 128 | { 129 | MethodName: "GetAllByFilter", 130 | Handler: _ProductService_GetAllByFilter_Handler, 131 | }, 132 | { 133 | MethodName: "GetByUUID", 134 | Handler: _ProductService_GetByUUID_Handler, 135 | }, 136 | }, 137 | Streams: []grpc.StreamDesc{}, 138 | Metadata: "api/proto/v1/product_service.proto", 139 | } 140 | -------------------------------------------------------------------------------- /pkg/common/gen/api/proto/v1/order_service.pb.gw.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. 2 | // source: api/proto/v1/order_service.proto 3 | 4 | /* 5 | Package pbv1 is a reverse proxy. 6 | 7 | It translates gRPC into RESTful JSON APIs. 8 | */ 9 | package pbv1 10 | 11 | import ( 12 | "context" 13 | "io" 14 | "net/http" 15 | 16 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 17 | "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" 18 | "google.golang.org/grpc" 19 | "google.golang.org/grpc/codes" 20 | "google.golang.org/grpc/grpclog" 21 | "google.golang.org/grpc/metadata" 22 | "google.golang.org/grpc/status" 23 | "google.golang.org/protobuf/proto" 24 | ) 25 | 26 | // Suppress "imported and not used" errors 27 | var _ codes.Code 28 | var _ io.Reader 29 | var _ status.Status 30 | var _ = runtime.String 31 | var _ = utilities.NewDoubleArray 32 | var _ = metadata.Join 33 | 34 | func request_OrderService_Checkout_0(ctx context.Context, marshaler runtime.Marshaler, client OrderServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { 35 | var protoReq CheckoutOrderRequest 36 | var metadata runtime.ServerMetadata 37 | 38 | newReader, berr := utilities.IOReaderFactory(req.Body) 39 | if berr != nil { 40 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) 41 | } 42 | if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Params); err != nil && err != io.EOF { 43 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 44 | } 45 | 46 | var ( 47 | val string 48 | ok bool 49 | err error 50 | _ = err 51 | ) 52 | 53 | val, ok = pathParams["order_uuid"] 54 | if !ok { 55 | return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "order_uuid") 56 | } 57 | 58 | protoReq.OrderUuid, err = runtime.String(val) 59 | if err != nil { 60 | return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "order_uuid", err) 61 | } 62 | 63 | msg, err := client.Checkout(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) 64 | return msg, metadata, err 65 | 66 | } 67 | 68 | func local_request_OrderService_Checkout_0(ctx context.Context, marshaler runtime.Marshaler, server OrderServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { 69 | var protoReq CheckoutOrderRequest 70 | var metadata runtime.ServerMetadata 71 | 72 | newReader, berr := utilities.IOReaderFactory(req.Body) 73 | if berr != nil { 74 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) 75 | } 76 | if err := marshaler.NewDecoder(newReader()).Decode(&protoReq.Params); err != nil && err != io.EOF { 77 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 78 | } 79 | 80 | var ( 81 | val string 82 | ok bool 83 | err error 84 | _ = err 85 | ) 86 | 87 | val, ok = pathParams["order_uuid"] 88 | if !ok { 89 | return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "order_uuid") 90 | } 91 | 92 | protoReq.OrderUuid, err = runtime.String(val) 93 | if err != nil { 94 | return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "order_uuid", err) 95 | } 96 | 97 | msg, err := server.Checkout(ctx, &protoReq) 98 | return msg, metadata, err 99 | 100 | } 101 | 102 | // RegisterOrderServiceHandlerServer registers the http handlers for service OrderService to "mux". 103 | // UnaryRPC :call OrderServiceServer directly. 104 | // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. 105 | // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterOrderServiceHandlerFromEndpoint instead. 106 | func RegisterOrderServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server OrderServiceServer) error { 107 | 108 | mux.Handle("POST", pattern_OrderService_Checkout_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 109 | ctx, cancel := context.WithCancel(req.Context()) 110 | defer cancel() 111 | var stream runtime.ServerTransportStream 112 | ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) 113 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 114 | var err error 115 | ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/pb.v1.OrderService/Checkout", runtime.WithHTTPPathPattern("/v1/orders/{order_uuid}")) 116 | if err != nil { 117 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 118 | return 119 | } 120 | resp, md, err := local_request_OrderService_Checkout_0(ctx, inboundMarshaler, server, req, pathParams) 121 | md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) 122 | ctx = runtime.NewServerMetadataContext(ctx, md) 123 | if err != nil { 124 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 125 | return 126 | } 127 | 128 | forward_OrderService_Checkout_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) 129 | 130 | }) 131 | 132 | return nil 133 | } 134 | 135 | // RegisterOrderServiceHandlerFromEndpoint is same as RegisterOrderServiceHandler but 136 | // automatically dials to "endpoint" and closes the connection when "ctx" gets done. 137 | func RegisterOrderServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { 138 | conn, err := grpc.Dial(endpoint, opts...) 139 | if err != nil { 140 | return err 141 | } 142 | defer func() { 143 | if err != nil { 144 | if cerr := conn.Close(); cerr != nil { 145 | grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) 146 | } 147 | return 148 | } 149 | go func() { 150 | <-ctx.Done() 151 | if cerr := conn.Close(); cerr != nil { 152 | grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) 153 | } 154 | }() 155 | }() 156 | 157 | return RegisterOrderServiceHandler(ctx, mux, conn) 158 | } 159 | 160 | // RegisterOrderServiceHandler registers the http handlers for service OrderService to "mux". 161 | // The handlers forward requests to the grpc endpoint over "conn". 162 | func RegisterOrderServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { 163 | return RegisterOrderServiceHandlerClient(ctx, mux, NewOrderServiceClient(conn)) 164 | } 165 | 166 | // RegisterOrderServiceHandlerClient registers the http handlers for service OrderService 167 | // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "OrderServiceClient". 168 | // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "OrderServiceClient" 169 | // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in 170 | // "OrderServiceClient" to call the correct interceptors. 171 | func RegisterOrderServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client OrderServiceClient) error { 172 | 173 | mux.Handle("POST", pattern_OrderService_Checkout_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 174 | ctx, cancel := context.WithCancel(req.Context()) 175 | defer cancel() 176 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 177 | var err error 178 | ctx, err = runtime.AnnotateContext(ctx, mux, req, "/pb.v1.OrderService/Checkout", runtime.WithHTTPPathPattern("/v1/orders/{order_uuid}")) 179 | if err != nil { 180 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 181 | return 182 | } 183 | resp, md, err := request_OrderService_Checkout_0(ctx, inboundMarshaler, client, req, pathParams) 184 | ctx = runtime.NewServerMetadataContext(ctx, md) 185 | if err != nil { 186 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 187 | return 188 | } 189 | 190 | forward_OrderService_Checkout_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) 191 | 192 | }) 193 | 194 | return nil 195 | } 196 | 197 | var ( 198 | pattern_OrderService_Checkout_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "orders", "order_uuid"}, "")) 199 | ) 200 | 201 | var ( 202 | forward_OrderService_Checkout_0 = runtime.ForwardResponseMessage 203 | ) 204 | -------------------------------------------------------------------------------- /pkg/common/gen/api/proto/v1/order_service.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.28.0 4 | // protoc (unknown) 5 | // source: api/proto/v1/order_service.proto 6 | 7 | package pbv1 8 | 9 | import ( 10 | _ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options" 11 | _ "google.golang.org/genproto/googleapis/api/annotations" 12 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 13 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 14 | reflect "reflect" 15 | sync "sync" 16 | ) 17 | 18 | const ( 19 | // Verify that this generated code is sufficiently up-to-date. 20 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 21 | // Verify that runtime/protoimpl is sufficiently up-to-date. 22 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 23 | ) 24 | 25 | type CheckoutOrderRequest struct { 26 | state protoimpl.MessageState 27 | sizeCache protoimpl.SizeCache 28 | unknownFields protoimpl.UnknownFields 29 | 30 | OrderUuid string `protobuf:"bytes,1,opt,name=order_uuid,json=orderUuid,proto3" json:"order_uuid,omitempty"` 31 | Params *CheckoutOrderRequestParams `protobuf:"bytes,2,opt,name=params,proto3" json:"params,omitempty"` 32 | } 33 | 34 | func (x *CheckoutOrderRequest) Reset() { 35 | *x = CheckoutOrderRequest{} 36 | if protoimpl.UnsafeEnabled { 37 | mi := &file_api_proto_v1_order_service_proto_msgTypes[0] 38 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 39 | ms.StoreMessageInfo(mi) 40 | } 41 | } 42 | 43 | func (x *CheckoutOrderRequest) String() string { 44 | return protoimpl.X.MessageStringOf(x) 45 | } 46 | 47 | func (*CheckoutOrderRequest) ProtoMessage() {} 48 | 49 | func (x *CheckoutOrderRequest) ProtoReflect() protoreflect.Message { 50 | mi := &file_api_proto_v1_order_service_proto_msgTypes[0] 51 | if protoimpl.UnsafeEnabled && x != nil { 52 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 53 | if ms.LoadMessageInfo() == nil { 54 | ms.StoreMessageInfo(mi) 55 | } 56 | return ms 57 | } 58 | return mi.MessageOf(x) 59 | } 60 | 61 | // Deprecated: Use CheckoutOrderRequest.ProtoReflect.Descriptor instead. 62 | func (*CheckoutOrderRequest) Descriptor() ([]byte, []int) { 63 | return file_api_proto_v1_order_service_proto_rawDescGZIP(), []int{0} 64 | } 65 | 66 | func (x *CheckoutOrderRequest) GetOrderUuid() string { 67 | if x != nil { 68 | return x.OrderUuid 69 | } 70 | return "" 71 | } 72 | 73 | func (x *CheckoutOrderRequest) GetParams() *CheckoutOrderRequestParams { 74 | if x != nil { 75 | return x.Params 76 | } 77 | return nil 78 | } 79 | 80 | type CheckoutOrderRequestParams struct { 81 | state protoimpl.MessageState 82 | sizeCache protoimpl.SizeCache 83 | unknownFields protoimpl.UnknownFields 84 | 85 | Amount float64 `protobuf:"fixed64,1,opt,name=amount,proto3" json:"amount,omitempty"` 86 | Status OrderStatus `protobuf:"varint,2,opt,name=status,proto3,enum=pb.v1.OrderStatus" json:"status,omitempty"` 87 | } 88 | 89 | func (x *CheckoutOrderRequestParams) Reset() { 90 | *x = CheckoutOrderRequestParams{} 91 | if protoimpl.UnsafeEnabled { 92 | mi := &file_api_proto_v1_order_service_proto_msgTypes[1] 93 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 94 | ms.StoreMessageInfo(mi) 95 | } 96 | } 97 | 98 | func (x *CheckoutOrderRequestParams) String() string { 99 | return protoimpl.X.MessageStringOf(x) 100 | } 101 | 102 | func (*CheckoutOrderRequestParams) ProtoMessage() {} 103 | 104 | func (x *CheckoutOrderRequestParams) ProtoReflect() protoreflect.Message { 105 | mi := &file_api_proto_v1_order_service_proto_msgTypes[1] 106 | if protoimpl.UnsafeEnabled && x != nil { 107 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 108 | if ms.LoadMessageInfo() == nil { 109 | ms.StoreMessageInfo(mi) 110 | } 111 | return ms 112 | } 113 | return mi.MessageOf(x) 114 | } 115 | 116 | // Deprecated: Use CheckoutOrderRequestParams.ProtoReflect.Descriptor instead. 117 | func (*CheckoutOrderRequestParams) Descriptor() ([]byte, []int) { 118 | return file_api_proto_v1_order_service_proto_rawDescGZIP(), []int{1} 119 | } 120 | 121 | func (x *CheckoutOrderRequestParams) GetAmount() float64 { 122 | if x != nil { 123 | return x.Amount 124 | } 125 | return 0 126 | } 127 | 128 | func (x *CheckoutOrderRequestParams) GetStatus() OrderStatus { 129 | if x != nil { 130 | return x.Status 131 | } 132 | return OrderStatusUnspecified 133 | } 134 | 135 | var File_api_proto_v1_order_service_proto protoreflect.FileDescriptor 136 | 137 | var file_api_proto_v1_order_service_proto_rawDesc = []byte{ 138 | 0x0a, 0x20, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 139 | 0x72, 0x64, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 140 | 0x74, 0x6f, 0x12, 0x05, 0x70, 0x62, 0x2e, 0x76, 0x31, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 141 | 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 142 | 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 143 | 0x67, 0x65, 0x6e, 0x2d, 0x6f, 0x70, 0x65, 0x6e, 0x61, 0x70, 0x69, 0x76, 0x32, 0x2f, 0x6f, 0x70, 144 | 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 145 | 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 146 | 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 147 | 0x74, 0x6f, 0x1a, 0x18, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 148 | 0x2f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x70, 0x0a, 0x14, 149 | 0x43, 0x68, 0x65, 0x63, 0x6b, 0x6f, 0x75, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 150 | 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x75, 151 | 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x55, 152 | 0x75, 0x69, 0x64, 0x12, 0x39, 0x0a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x02, 0x20, 153 | 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 154 | 0x6b, 0x6f, 0x75, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 155 | 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x22, 0x60, 156 | 0x0a, 0x1a, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x6f, 0x75, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 157 | 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x16, 0x0a, 0x06, 158 | 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x61, 0x6d, 159 | 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 160 | 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x70, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x64, 161 | 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 162 | 0x32, 0x8c, 0x01, 0x0a, 0x0c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 163 | 0x65, 0x12, 0x7c, 0x0a, 0x08, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x6f, 0x75, 0x74, 0x12, 0x1b, 0x2e, 164 | 0x70, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x6f, 0x75, 0x74, 0x4f, 0x72, 165 | 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 166 | 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x22, 0x45, 0x92, 0x41, 0x1b, 0x12, 0x19, 0xd0, 167 | 0x9e, 0xd0, 0xbf, 0xd0, 0xbb, 0xd0, 0xb0, 0xd1, 0x82, 0xd0, 0xb0, 0x20, 0xd0, 0xb7, 0xd0, 0xb0, 168 | 0xd0, 0xba, 0xd0, 0xb0, 0xd0, 0xb7, 0xd0, 0xb0, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x22, 0x17, 169 | 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x6f, 0x72, 0x64, 0x65, 170 | 0x72, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x7d, 0x3a, 0x06, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x42, 171 | 0x3e, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x62, 0x79, 172 | 0x6f, 0x72, 0x74, 0x79, 0x2f, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x2d, 173 | 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 174 | 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x62, 0x76, 0x31, 0x62, 175 | 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 176 | } 177 | 178 | var ( 179 | file_api_proto_v1_order_service_proto_rawDescOnce sync.Once 180 | file_api_proto_v1_order_service_proto_rawDescData = file_api_proto_v1_order_service_proto_rawDesc 181 | ) 182 | 183 | func file_api_proto_v1_order_service_proto_rawDescGZIP() []byte { 184 | file_api_proto_v1_order_service_proto_rawDescOnce.Do(func() { 185 | file_api_proto_v1_order_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_api_proto_v1_order_service_proto_rawDescData) 186 | }) 187 | return file_api_proto_v1_order_service_proto_rawDescData 188 | } 189 | 190 | var file_api_proto_v1_order_service_proto_msgTypes = make([]protoimpl.MessageInfo, 2) 191 | var file_api_proto_v1_order_service_proto_goTypes = []interface{}{ 192 | (*CheckoutOrderRequest)(nil), // 0: pb.v1.CheckoutOrderRequest 193 | (*CheckoutOrderRequestParams)(nil), // 1: pb.v1.CheckoutOrderRequestParams 194 | (OrderStatus)(0), // 2: pb.v1.OrderStatus 195 | (*Order)(nil), // 3: pb.v1.Order 196 | } 197 | var file_api_proto_v1_order_service_proto_depIdxs = []int32{ 198 | 1, // 0: pb.v1.CheckoutOrderRequest.params:type_name -> pb.v1.CheckoutOrderRequestParams 199 | 2, // 1: pb.v1.CheckoutOrderRequestParams.status:type_name -> pb.v1.OrderStatus 200 | 0, // 2: pb.v1.OrderService.Checkout:input_type -> pb.v1.CheckoutOrderRequest 201 | 3, // 3: pb.v1.OrderService.Checkout:output_type -> pb.v1.Order 202 | 3, // [3:4] is the sub-list for method output_type 203 | 2, // [2:3] is the sub-list for method input_type 204 | 2, // [2:2] is the sub-list for extension type_name 205 | 2, // [2:2] is the sub-list for extension extendee 206 | 0, // [0:2] is the sub-list for field type_name 207 | } 208 | 209 | func init() { file_api_proto_v1_order_service_proto_init() } 210 | func file_api_proto_v1_order_service_proto_init() { 211 | if File_api_proto_v1_order_service_proto != nil { 212 | return 213 | } 214 | file_api_proto_v1_common_proto_init() 215 | file_api_proto_v1_order_proto_init() 216 | if !protoimpl.UnsafeEnabled { 217 | file_api_proto_v1_order_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 218 | switch v := v.(*CheckoutOrderRequest); i { 219 | case 0: 220 | return &v.state 221 | case 1: 222 | return &v.sizeCache 223 | case 2: 224 | return &v.unknownFields 225 | default: 226 | return nil 227 | } 228 | } 229 | file_api_proto_v1_order_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 230 | switch v := v.(*CheckoutOrderRequestParams); i { 231 | case 0: 232 | return &v.state 233 | case 1: 234 | return &v.sizeCache 235 | case 2: 236 | return &v.unknownFields 237 | default: 238 | return nil 239 | } 240 | } 241 | } 242 | type x struct{} 243 | out := protoimpl.TypeBuilder{ 244 | File: protoimpl.DescBuilder{ 245 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 246 | RawDescriptor: file_api_proto_v1_order_service_proto_rawDesc, 247 | NumEnums: 0, 248 | NumMessages: 2, 249 | NumExtensions: 0, 250 | NumServices: 1, 251 | }, 252 | GoTypes: file_api_proto_v1_order_service_proto_goTypes, 253 | DependencyIndexes: file_api_proto_v1_order_service_proto_depIdxs, 254 | MessageInfos: file_api_proto_v1_order_service_proto_msgTypes, 255 | }.Build() 256 | File_api_proto_v1_order_service_proto = out.File 257 | file_api_proto_v1_order_service_proto_rawDesc = nil 258 | file_api_proto_v1_order_service_proto_goTypes = nil 259 | file_api_proto_v1_order_service_proto_depIdxs = nil 260 | } 261 | -------------------------------------------------------------------------------- /pkg/common/gen/api/proto/v1/common.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.28.0 4 | // protoc (unknown) 5 | // source: api/proto/v1/common.proto 6 | 7 | package pbv1 8 | 9 | import ( 10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 12 | reflect "reflect" 13 | sync "sync" 14 | ) 15 | 16 | const ( 17 | // Verify that this generated code is sufficiently up-to-date. 18 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 19 | // Verify that runtime/protoimpl is sufficiently up-to-date. 20 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 21 | ) 22 | 23 | type Paginator struct { 24 | state protoimpl.MessageState 25 | sizeCache protoimpl.SizeCache 26 | unknownFields protoimpl.UnknownFields 27 | 28 | Offset uint32 `protobuf:"varint,1,opt,name=offset,proto3" json:"offset,omitempty"` 29 | Limit uint32 `protobuf:"varint,2,opt,name=limit,proto3" json:"limit,omitempty"` 30 | } 31 | 32 | func (x *Paginator) Reset() { 33 | *x = Paginator{} 34 | if protoimpl.UnsafeEnabled { 35 | mi := &file_api_proto_v1_common_proto_msgTypes[0] 36 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 37 | ms.StoreMessageInfo(mi) 38 | } 39 | } 40 | 41 | func (x *Paginator) String() string { 42 | return protoimpl.X.MessageStringOf(x) 43 | } 44 | 45 | func (*Paginator) ProtoMessage() {} 46 | 47 | func (x *Paginator) ProtoReflect() protoreflect.Message { 48 | mi := &file_api_proto_v1_common_proto_msgTypes[0] 49 | if protoimpl.UnsafeEnabled && x != nil { 50 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 51 | if ms.LoadMessageInfo() == nil { 52 | ms.StoreMessageInfo(mi) 53 | } 54 | return ms 55 | } 56 | return mi.MessageOf(x) 57 | } 58 | 59 | // Deprecated: Use Paginator.ProtoReflect.Descriptor instead. 60 | func (*Paginator) Descriptor() ([]byte, []int) { 61 | return file_api_proto_v1_common_proto_rawDescGZIP(), []int{0} 62 | } 63 | 64 | func (x *Paginator) GetOffset() uint32 { 65 | if x != nil { 66 | return x.Offset 67 | } 68 | return 0 69 | } 70 | 71 | func (x *Paginator) GetLimit() uint32 { 72 | if x != nil { 73 | return x.Limit 74 | } 75 | return 0 76 | } 77 | 78 | type UserProduct struct { 79 | state protoimpl.MessageState 80 | sizeCache protoimpl.SizeCache 81 | unknownFields protoimpl.UnknownFields 82 | 83 | Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` 84 | ProductUuid string `protobuf:"bytes,2,opt,name=product_uuid,json=productUuid,proto3" json:"product_uuid,omitempty"` 85 | Count uint32 `protobuf:"varint,3,opt,name=count,proto3" json:"count,omitempty"` 86 | } 87 | 88 | func (x *UserProduct) Reset() { 89 | *x = UserProduct{} 90 | if protoimpl.UnsafeEnabled { 91 | mi := &file_api_proto_v1_common_proto_msgTypes[1] 92 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 93 | ms.StoreMessageInfo(mi) 94 | } 95 | } 96 | 97 | func (x *UserProduct) String() string { 98 | return protoimpl.X.MessageStringOf(x) 99 | } 100 | 101 | func (*UserProduct) ProtoMessage() {} 102 | 103 | func (x *UserProduct) ProtoReflect() protoreflect.Message { 104 | mi := &file_api_proto_v1_common_proto_msgTypes[1] 105 | if protoimpl.UnsafeEnabled && x != nil { 106 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 107 | if ms.LoadMessageInfo() == nil { 108 | ms.StoreMessageInfo(mi) 109 | } 110 | return ms 111 | } 112 | return mi.MessageOf(x) 113 | } 114 | 115 | // Deprecated: Use UserProduct.ProtoReflect.Descriptor instead. 116 | func (*UserProduct) Descriptor() ([]byte, []int) { 117 | return file_api_proto_v1_common_proto_rawDescGZIP(), []int{1} 118 | } 119 | 120 | func (x *UserProduct) GetUuid() string { 121 | if x != nil { 122 | return x.Uuid 123 | } 124 | return "" 125 | } 126 | 127 | func (x *UserProduct) GetProductUuid() string { 128 | if x != nil { 129 | return x.ProductUuid 130 | } 131 | return "" 132 | } 133 | 134 | func (x *UserProduct) GetCount() uint32 { 135 | if x != nil { 136 | return x.Count 137 | } 138 | return 0 139 | } 140 | 141 | type Error struct { 142 | state protoimpl.MessageState 143 | sizeCache protoimpl.SizeCache 144 | unknownFields protoimpl.UnknownFields 145 | 146 | Code uint32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"` 147 | Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` 148 | Details map[string]string `protobuf:"bytes,3,rep,name=details,proto3" json:"details,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` 149 | } 150 | 151 | func (x *Error) Reset() { 152 | *x = Error{} 153 | if protoimpl.UnsafeEnabled { 154 | mi := &file_api_proto_v1_common_proto_msgTypes[2] 155 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 156 | ms.StoreMessageInfo(mi) 157 | } 158 | } 159 | 160 | func (x *Error) String() string { 161 | return protoimpl.X.MessageStringOf(x) 162 | } 163 | 164 | func (*Error) ProtoMessage() {} 165 | 166 | func (x *Error) ProtoReflect() protoreflect.Message { 167 | mi := &file_api_proto_v1_common_proto_msgTypes[2] 168 | if protoimpl.UnsafeEnabled && x != nil { 169 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 170 | if ms.LoadMessageInfo() == nil { 171 | ms.StoreMessageInfo(mi) 172 | } 173 | return ms 174 | } 175 | return mi.MessageOf(x) 176 | } 177 | 178 | // Deprecated: Use Error.ProtoReflect.Descriptor instead. 179 | func (*Error) Descriptor() ([]byte, []int) { 180 | return file_api_proto_v1_common_proto_rawDescGZIP(), []int{2} 181 | } 182 | 183 | func (x *Error) GetCode() uint32 { 184 | if x != nil { 185 | return x.Code 186 | } 187 | return 0 188 | } 189 | 190 | func (x *Error) GetMessage() string { 191 | if x != nil { 192 | return x.Message 193 | } 194 | return "" 195 | } 196 | 197 | func (x *Error) GetDetails() map[string]string { 198 | if x != nil { 199 | return x.Details 200 | } 201 | return nil 202 | } 203 | 204 | var File_api_proto_v1_common_proto protoreflect.FileDescriptor 205 | 206 | var file_api_proto_v1_common_proto_rawDesc = []byte{ 207 | 0x0a, 0x19, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x2f, 0x63, 208 | 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x62, 0x2e, 209 | 0x76, 0x31, 0x22, 0x39, 0x0a, 0x09, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x6f, 0x72, 0x12, 210 | 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 211 | 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 212 | 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0x5a, 0x0a, 213 | 0x0b, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x12, 0x12, 0x0a, 0x04, 214 | 0x75, 0x75, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 215 | 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x5f, 0x75, 0x75, 0x69, 0x64, 216 | 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x55, 217 | 0x75, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 218 | 0x28, 0x0d, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xa6, 0x01, 0x0a, 0x05, 0x45, 0x72, 219 | 0x72, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 220 | 0x0d, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 221 | 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 222 | 0x65, 0x12, 0x33, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x03, 0x20, 0x03, 223 | 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x62, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 224 | 0x2e, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x64, 225 | 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x1a, 0x3a, 0x0a, 0x0c, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 226 | 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 227 | 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 228 | 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 229 | 0x38, 0x01, 0x42, 0x3e, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 230 | 0x2f, 0x62, 0x79, 0x6f, 0x72, 0x74, 0x79, 0x2f, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 231 | 0x73, 0x65, 0x2d, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x70, 232 | 0x6b, 0x67, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x62, 233 | 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 234 | } 235 | 236 | var ( 237 | file_api_proto_v1_common_proto_rawDescOnce sync.Once 238 | file_api_proto_v1_common_proto_rawDescData = file_api_proto_v1_common_proto_rawDesc 239 | ) 240 | 241 | func file_api_proto_v1_common_proto_rawDescGZIP() []byte { 242 | file_api_proto_v1_common_proto_rawDescOnce.Do(func() { 243 | file_api_proto_v1_common_proto_rawDescData = protoimpl.X.CompressGZIP(file_api_proto_v1_common_proto_rawDescData) 244 | }) 245 | return file_api_proto_v1_common_proto_rawDescData 246 | } 247 | 248 | var file_api_proto_v1_common_proto_msgTypes = make([]protoimpl.MessageInfo, 4) 249 | var file_api_proto_v1_common_proto_goTypes = []interface{}{ 250 | (*Paginator)(nil), // 0: pb.v1.Paginator 251 | (*UserProduct)(nil), // 1: pb.v1.UserProduct 252 | (*Error)(nil), // 2: pb.v1.Error 253 | nil, // 3: pb.v1.Error.DetailsEntry 254 | } 255 | var file_api_proto_v1_common_proto_depIdxs = []int32{ 256 | 3, // 0: pb.v1.Error.details:type_name -> pb.v1.Error.DetailsEntry 257 | 1, // [1:1] is the sub-list for method output_type 258 | 1, // [1:1] is the sub-list for method input_type 259 | 1, // [1:1] is the sub-list for extension type_name 260 | 1, // [1:1] is the sub-list for extension extendee 261 | 0, // [0:1] is the sub-list for field type_name 262 | } 263 | 264 | func init() { file_api_proto_v1_common_proto_init() } 265 | func file_api_proto_v1_common_proto_init() { 266 | if File_api_proto_v1_common_proto != nil { 267 | return 268 | } 269 | if !protoimpl.UnsafeEnabled { 270 | file_api_proto_v1_common_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 271 | switch v := v.(*Paginator); i { 272 | case 0: 273 | return &v.state 274 | case 1: 275 | return &v.sizeCache 276 | case 2: 277 | return &v.unknownFields 278 | default: 279 | return nil 280 | } 281 | } 282 | file_api_proto_v1_common_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 283 | switch v := v.(*UserProduct); i { 284 | case 0: 285 | return &v.state 286 | case 1: 287 | return &v.sizeCache 288 | case 2: 289 | return &v.unknownFields 290 | default: 291 | return nil 292 | } 293 | } 294 | file_api_proto_v1_common_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { 295 | switch v := v.(*Error); i { 296 | case 0: 297 | return &v.state 298 | case 1: 299 | return &v.sizeCache 300 | case 2: 301 | return &v.unknownFields 302 | default: 303 | return nil 304 | } 305 | } 306 | } 307 | type x struct{} 308 | out := protoimpl.TypeBuilder{ 309 | File: protoimpl.DescBuilder{ 310 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 311 | RawDescriptor: file_api_proto_v1_common_proto_rawDesc, 312 | NumEnums: 0, 313 | NumMessages: 4, 314 | NumExtensions: 0, 315 | NumServices: 0, 316 | }, 317 | GoTypes: file_api_proto_v1_common_proto_goTypes, 318 | DependencyIndexes: file_api_proto_v1_common_proto_depIdxs, 319 | MessageInfos: file_api_proto_v1_common_proto_msgTypes, 320 | }.Build() 321 | File_api_proto_v1_common_proto = out.File 322 | file_api_proto_v1_common_proto_rawDesc = nil 323 | file_api_proto_v1_common_proto_goTypes = nil 324 | file_api_proto_v1_common_proto_depIdxs = nil 325 | } 326 | -------------------------------------------------------------------------------- /pkg/common/gen/api/proto/v1/product_service.pb.gw.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. 2 | // source: api/proto/v1/product_service.proto 3 | 4 | /* 5 | Package pbv1 is a reverse proxy. 6 | 7 | It translates gRPC into RESTful JSON APIs. 8 | */ 9 | package pbv1 10 | 11 | import ( 12 | "context" 13 | "io" 14 | "net/http" 15 | 16 | "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 17 | "github.com/grpc-ecosystem/grpc-gateway/v2/utilities" 18 | "google.golang.org/grpc" 19 | "google.golang.org/grpc/codes" 20 | "google.golang.org/grpc/grpclog" 21 | "google.golang.org/grpc/metadata" 22 | "google.golang.org/grpc/status" 23 | "google.golang.org/protobuf/proto" 24 | ) 25 | 26 | // Suppress "imported and not used" errors 27 | var _ codes.Code 28 | var _ io.Reader 29 | var _ status.Status 30 | var _ = runtime.String 31 | var _ = utilities.NewDoubleArray 32 | var _ = metadata.Join 33 | 34 | var ( 35 | filter_ProductService_GetAllByFilter_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} 36 | ) 37 | 38 | func request_ProductService_GetAllByFilter_0(ctx context.Context, marshaler runtime.Marshaler, client ProductServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { 39 | var protoReq ProductsRequest 40 | var metadata runtime.ServerMetadata 41 | 42 | if err := req.ParseForm(); err != nil { 43 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 44 | } 45 | if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ProductService_GetAllByFilter_0); err != nil { 46 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 47 | } 48 | 49 | msg, err := client.GetAllByFilter(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) 50 | return msg, metadata, err 51 | 52 | } 53 | 54 | func local_request_ProductService_GetAllByFilter_0(ctx context.Context, marshaler runtime.Marshaler, server ProductServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { 55 | var protoReq ProductsRequest 56 | var metadata runtime.ServerMetadata 57 | 58 | if err := req.ParseForm(); err != nil { 59 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 60 | } 61 | if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ProductService_GetAllByFilter_0); err != nil { 62 | return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) 63 | } 64 | 65 | msg, err := server.GetAllByFilter(ctx, &protoReq) 66 | return msg, metadata, err 67 | 68 | } 69 | 70 | func request_ProductService_GetByUUID_0(ctx context.Context, marshaler runtime.Marshaler, client ProductServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { 71 | var protoReq GetByProductUUIDRequest 72 | var metadata runtime.ServerMetadata 73 | 74 | var ( 75 | val string 76 | ok bool 77 | err error 78 | _ = err 79 | ) 80 | 81 | val, ok = pathParams["product_uuid"] 82 | if !ok { 83 | return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "product_uuid") 84 | } 85 | 86 | protoReq.ProductUuid, err = runtime.String(val) 87 | if err != nil { 88 | return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "product_uuid", err) 89 | } 90 | 91 | msg, err := client.GetByUUID(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) 92 | return msg, metadata, err 93 | 94 | } 95 | 96 | func local_request_ProductService_GetByUUID_0(ctx context.Context, marshaler runtime.Marshaler, server ProductServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { 97 | var protoReq GetByProductUUIDRequest 98 | var metadata runtime.ServerMetadata 99 | 100 | var ( 101 | val string 102 | ok bool 103 | err error 104 | _ = err 105 | ) 106 | 107 | val, ok = pathParams["product_uuid"] 108 | if !ok { 109 | return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "product_uuid") 110 | } 111 | 112 | protoReq.ProductUuid, err = runtime.String(val) 113 | if err != nil { 114 | return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "product_uuid", err) 115 | } 116 | 117 | msg, err := server.GetByUUID(ctx, &protoReq) 118 | return msg, metadata, err 119 | 120 | } 121 | 122 | // RegisterProductServiceHandlerServer registers the http handlers for service ProductService to "mux". 123 | // UnaryRPC :call ProductServiceServer directly. 124 | // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. 125 | // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterProductServiceHandlerFromEndpoint instead. 126 | func RegisterProductServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server ProductServiceServer) error { 127 | 128 | mux.Handle("GET", pattern_ProductService_GetAllByFilter_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 129 | ctx, cancel := context.WithCancel(req.Context()) 130 | defer cancel() 131 | var stream runtime.ServerTransportStream 132 | ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) 133 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 134 | var err error 135 | ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/pb.v1.ProductService/GetAllByFilter", runtime.WithHTTPPathPattern("/v1/products")) 136 | if err != nil { 137 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 138 | return 139 | } 140 | resp, md, err := local_request_ProductService_GetAllByFilter_0(ctx, inboundMarshaler, server, req, pathParams) 141 | md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) 142 | ctx = runtime.NewServerMetadataContext(ctx, md) 143 | if err != nil { 144 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 145 | return 146 | } 147 | 148 | forward_ProductService_GetAllByFilter_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) 149 | 150 | }) 151 | 152 | mux.Handle("GET", pattern_ProductService_GetByUUID_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 153 | ctx, cancel := context.WithCancel(req.Context()) 154 | defer cancel() 155 | var stream runtime.ServerTransportStream 156 | ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) 157 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 158 | var err error 159 | ctx, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/pb.v1.ProductService/GetByUUID", runtime.WithHTTPPathPattern("/v1/products/{product_uuid}")) 160 | if err != nil { 161 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 162 | return 163 | } 164 | resp, md, err := local_request_ProductService_GetByUUID_0(ctx, inboundMarshaler, server, req, pathParams) 165 | md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) 166 | ctx = runtime.NewServerMetadataContext(ctx, md) 167 | if err != nil { 168 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 169 | return 170 | } 171 | 172 | forward_ProductService_GetByUUID_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) 173 | 174 | }) 175 | 176 | return nil 177 | } 178 | 179 | // RegisterProductServiceHandlerFromEndpoint is same as RegisterProductServiceHandler but 180 | // automatically dials to "endpoint" and closes the connection when "ctx" gets done. 181 | func RegisterProductServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { 182 | conn, err := grpc.Dial(endpoint, opts...) 183 | if err != nil { 184 | return err 185 | } 186 | defer func() { 187 | if err != nil { 188 | if cerr := conn.Close(); cerr != nil { 189 | grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) 190 | } 191 | return 192 | } 193 | go func() { 194 | <-ctx.Done() 195 | if cerr := conn.Close(); cerr != nil { 196 | grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) 197 | } 198 | }() 199 | }() 200 | 201 | return RegisterProductServiceHandler(ctx, mux, conn) 202 | } 203 | 204 | // RegisterProductServiceHandler registers the http handlers for service ProductService to "mux". 205 | // The handlers forward requests to the grpc endpoint over "conn". 206 | func RegisterProductServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { 207 | return RegisterProductServiceHandlerClient(ctx, mux, NewProductServiceClient(conn)) 208 | } 209 | 210 | // RegisterProductServiceHandlerClient registers the http handlers for service ProductService 211 | // to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "ProductServiceClient". 212 | // Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "ProductServiceClient" 213 | // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in 214 | // "ProductServiceClient" to call the correct interceptors. 215 | func RegisterProductServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client ProductServiceClient) error { 216 | 217 | mux.Handle("GET", pattern_ProductService_GetAllByFilter_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 218 | ctx, cancel := context.WithCancel(req.Context()) 219 | defer cancel() 220 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 221 | var err error 222 | ctx, err = runtime.AnnotateContext(ctx, mux, req, "/pb.v1.ProductService/GetAllByFilter", runtime.WithHTTPPathPattern("/v1/products")) 223 | if err != nil { 224 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 225 | return 226 | } 227 | resp, md, err := request_ProductService_GetAllByFilter_0(ctx, inboundMarshaler, client, req, pathParams) 228 | ctx = runtime.NewServerMetadataContext(ctx, md) 229 | if err != nil { 230 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 231 | return 232 | } 233 | 234 | forward_ProductService_GetAllByFilter_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) 235 | 236 | }) 237 | 238 | mux.Handle("GET", pattern_ProductService_GetByUUID_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { 239 | ctx, cancel := context.WithCancel(req.Context()) 240 | defer cancel() 241 | inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) 242 | var err error 243 | ctx, err = runtime.AnnotateContext(ctx, mux, req, "/pb.v1.ProductService/GetByUUID", runtime.WithHTTPPathPattern("/v1/products/{product_uuid}")) 244 | if err != nil { 245 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 246 | return 247 | } 248 | resp, md, err := request_ProductService_GetByUUID_0(ctx, inboundMarshaler, client, req, pathParams) 249 | ctx = runtime.NewServerMetadataContext(ctx, md) 250 | if err != nil { 251 | runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) 252 | return 253 | } 254 | 255 | forward_ProductService_GetByUUID_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) 256 | 257 | }) 258 | 259 | return nil 260 | } 261 | 262 | var ( 263 | pattern_ProductService_GetAllByFilter_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "products"}, "")) 264 | 265 | pattern_ProductService_GetByUUID_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "products", "product_uuid"}, "")) 266 | ) 267 | 268 | var ( 269 | forward_ProductService_GetAllByFilter_0 = runtime.ForwardResponseMessage 270 | 271 | forward_ProductService_GetByUUID_0 = runtime.ForwardResponseMessage 272 | ) 273 | -------------------------------------------------------------------------------- /pkg/common/gen/api/proto/v1/order.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.28.0 4 | // protoc (unknown) 5 | // source: api/proto/v1/order.proto 6 | 7 | package pbv1 8 | 9 | import ( 10 | _ "github.com/alta/protopatch/patch/gopb" 11 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 12 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 13 | timestamppb "google.golang.org/protobuf/types/known/timestamppb" 14 | reflect "reflect" 15 | sync "sync" 16 | ) 17 | 18 | const ( 19 | // Verify that this generated code is sufficiently up-to-date. 20 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 21 | // Verify that runtime/protoimpl is sufficiently up-to-date. 22 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 23 | ) 24 | 25 | type OrderStatus int32 26 | 27 | const ( 28 | OrderStatusUnspecified OrderStatus = 0 29 | OrderStatusCreated OrderStatus = 1 30 | OrderStatusPaid OrderStatus = 2 31 | OrderStatusDelivered OrderStatus = 3 32 | ) 33 | 34 | // Enum value maps for OrderStatus. 35 | var ( 36 | OrderStatus_name = map[int32]string{ 37 | 0: "ORDER_STATUS_UNSPECIFIED", 38 | 1: "ORDER_STATUS_CREATED", 39 | 2: "ORDER_STATUS_PAID", 40 | 3: "ORDER_STATUS_DELIVERED", 41 | } 42 | OrderStatus_value = map[string]int32{ 43 | "ORDER_STATUS_UNSPECIFIED": 0, 44 | "ORDER_STATUS_CREATED": 1, 45 | "ORDER_STATUS_PAID": 2, 46 | "ORDER_STATUS_DELIVERED": 3, 47 | } 48 | ) 49 | 50 | func (x OrderStatus) Enum() *OrderStatus { 51 | p := new(OrderStatus) 52 | *p = x 53 | return p 54 | } 55 | 56 | func (x OrderStatus) String() string { 57 | return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) 58 | } 59 | 60 | func (OrderStatus) Descriptor() protoreflect.EnumDescriptor { 61 | return file_api_proto_v1_order_proto_enumTypes[0].Descriptor() 62 | } 63 | 64 | func (OrderStatus) Type() protoreflect.EnumType { 65 | return &file_api_proto_v1_order_proto_enumTypes[0] 66 | } 67 | 68 | func (x OrderStatus) Number() protoreflect.EnumNumber { 69 | return protoreflect.EnumNumber(x) 70 | } 71 | 72 | // Deprecated: Use OrderStatus.Descriptor instead. 73 | func (OrderStatus) EnumDescriptor() ([]byte, []int) { 74 | return file_api_proto_v1_order_proto_rawDescGZIP(), []int{0} 75 | } 76 | 77 | type Order struct { 78 | state protoimpl.MessageState 79 | sizeCache protoimpl.SizeCache 80 | unknownFields protoimpl.UnknownFields 81 | 82 | Uuid string `protobuf:"bytes,1,opt,name=uuid,proto3" json:"uuid,omitempty"` 83 | UserUuid string `protobuf:"bytes,2,opt,name=user_uuid,json=userUuid,proto3" json:"user_uuid,omitempty"` 84 | Amount float64 `protobuf:"fixed64,3,opt,name=amount,proto3" json:"amount,omitempty"` 85 | Address string `protobuf:"bytes,4,opt,name=address,proto3" json:"address,omitempty"` 86 | Status OrderStatus `protobuf:"varint,5,opt,name=status,proto3,enum=pb.v1.OrderStatus" json:"status,omitempty"` 87 | Products []*UserProduct `protobuf:"bytes,6,rep,name=products,proto3" json:"products,omitempty"` 88 | CreatedAt *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` 89 | DeliveredAt *timestamppb.Timestamp `protobuf:"bytes,8,opt,name=delivered_at,json=deliveredAt,proto3" json:"delivered_at,omitempty"` 90 | } 91 | 92 | func (x *Order) Reset() { 93 | *x = Order{} 94 | if protoimpl.UnsafeEnabled { 95 | mi := &file_api_proto_v1_order_proto_msgTypes[0] 96 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 97 | ms.StoreMessageInfo(mi) 98 | } 99 | } 100 | 101 | func (x *Order) String() string { 102 | return protoimpl.X.MessageStringOf(x) 103 | } 104 | 105 | func (*Order) ProtoMessage() {} 106 | 107 | func (x *Order) ProtoReflect() protoreflect.Message { 108 | mi := &file_api_proto_v1_order_proto_msgTypes[0] 109 | if protoimpl.UnsafeEnabled && x != nil { 110 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 111 | if ms.LoadMessageInfo() == nil { 112 | ms.StoreMessageInfo(mi) 113 | } 114 | return ms 115 | } 116 | return mi.MessageOf(x) 117 | } 118 | 119 | // Deprecated: Use Order.ProtoReflect.Descriptor instead. 120 | func (*Order) Descriptor() ([]byte, []int) { 121 | return file_api_proto_v1_order_proto_rawDescGZIP(), []int{0} 122 | } 123 | 124 | func (x *Order) GetUuid() string { 125 | if x != nil { 126 | return x.Uuid 127 | } 128 | return "" 129 | } 130 | 131 | func (x *Order) GetUserUuid() string { 132 | if x != nil { 133 | return x.UserUuid 134 | } 135 | return "" 136 | } 137 | 138 | func (x *Order) GetAmount() float64 { 139 | if x != nil { 140 | return x.Amount 141 | } 142 | return 0 143 | } 144 | 145 | func (x *Order) GetAddress() string { 146 | if x != nil { 147 | return x.Address 148 | } 149 | return "" 150 | } 151 | 152 | func (x *Order) GetStatus() OrderStatus { 153 | if x != nil { 154 | return x.Status 155 | } 156 | return OrderStatusUnspecified 157 | } 158 | 159 | func (x *Order) GetProducts() []*UserProduct { 160 | if x != nil { 161 | return x.Products 162 | } 163 | return nil 164 | } 165 | 166 | func (x *Order) GetCreatedAt() *timestamppb.Timestamp { 167 | if x != nil { 168 | return x.CreatedAt 169 | } 170 | return nil 171 | } 172 | 173 | func (x *Order) GetDeliveredAt() *timestamppb.Timestamp { 174 | if x != nil { 175 | return x.DeliveredAt 176 | } 177 | return nil 178 | } 179 | 180 | var File_api_proto_v1_order_proto protoreflect.FileDescriptor 181 | 182 | var file_api_proto_v1_order_proto_rawDesc = []byte{ 183 | 0x0a, 0x18, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 184 | 0x72, 0x64, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x62, 0x2e, 0x76, 185 | 0x31, 0x1a, 0x0e, 0x70, 0x61, 0x74, 0x63, 0x68, 0x2f, 0x67, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 186 | 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 187 | 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 188 | 0x74, 0x6f, 0x1a, 0x19, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x76, 0x31, 189 | 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc0, 0x02, 190 | 0x0a, 0x05, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x75, 0x69, 0x64, 0x18, 191 | 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x75, 0x69, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x75, 192 | 0x73, 0x65, 0x72, 0x5f, 0x75, 0x75, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 193 | 0x75, 0x73, 0x65, 0x72, 0x55, 0x75, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 194 | 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 195 | 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 196 | 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2a, 0x0a, 0x06, 0x73, 0x74, 197 | 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x12, 0x2e, 0x70, 0x62, 0x2e, 198 | 0x76, 0x31, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 199 | 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2e, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x64, 0x75, 0x63, 200 | 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x62, 0x2e, 0x76, 0x31, 201 | 0x2e, 0x55, 0x73, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x64, 0x75, 0x63, 0x74, 0x52, 0x08, 0x70, 0x72, 202 | 0x6f, 0x64, 0x75, 0x63, 0x74, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 203 | 0x64, 0x5f, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 204 | 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 205 | 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 206 | 0x74, 0x12, 0x3d, 0x0a, 0x0c, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x61, 207 | 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 208 | 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 209 | 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x64, 0x65, 0x6c, 0x69, 0x76, 0x65, 0x72, 0x65, 0x64, 0x41, 0x74, 210 | 0x2a, 0xe3, 0x01, 0x0a, 0x0b, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 211 | 0x12, 0x3a, 0x0a, 0x18, 0x4f, 0x52, 0x44, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 212 | 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x1a, 0x1c, 213 | 0xca, 0xb5, 0x03, 0x18, 0x0a, 0x16, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 214 | 0x73, 0x55, 0x6e, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x32, 0x0a, 0x14, 215 | 0x4f, 0x52, 0x44, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x43, 0x52, 0x45, 216 | 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, 0x1a, 0x18, 0xca, 0xb5, 0x03, 0x14, 0x0a, 0x12, 0x4f, 0x72, 217 | 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 218 | 0x12, 0x2c, 0x0a, 0x11, 0x4f, 0x52, 0x44, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 219 | 0x5f, 0x50, 0x41, 0x49, 0x44, 0x10, 0x02, 0x1a, 0x15, 0xca, 0xb5, 0x03, 0x11, 0x0a, 0x0f, 0x4f, 220 | 0x72, 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x50, 0x61, 0x69, 0x64, 0x12, 0x36, 221 | 0x0a, 0x16, 0x4f, 0x52, 0x44, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x44, 222 | 0x45, 0x4c, 0x49, 0x56, 0x45, 0x52, 0x45, 0x44, 0x10, 0x03, 0x1a, 0x1a, 0xca, 0xb5, 0x03, 0x16, 223 | 0x0a, 0x14, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x44, 0x65, 0x6c, 224 | 0x69, 0x76, 0x65, 0x72, 0x65, 0x64, 0x42, 0x3e, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 225 | 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x62, 0x79, 0x6f, 0x72, 0x74, 0x79, 0x2f, 0x65, 0x6e, 0x74, 0x65, 226 | 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x2d, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 227 | 0x6f, 0x6e, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x67, 0x65, 228 | 0x6e, 0x2f, 0x70, 0x62, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 229 | } 230 | 231 | var ( 232 | file_api_proto_v1_order_proto_rawDescOnce sync.Once 233 | file_api_proto_v1_order_proto_rawDescData = file_api_proto_v1_order_proto_rawDesc 234 | ) 235 | 236 | func file_api_proto_v1_order_proto_rawDescGZIP() []byte { 237 | file_api_proto_v1_order_proto_rawDescOnce.Do(func() { 238 | file_api_proto_v1_order_proto_rawDescData = protoimpl.X.CompressGZIP(file_api_proto_v1_order_proto_rawDescData) 239 | }) 240 | return file_api_proto_v1_order_proto_rawDescData 241 | } 242 | 243 | var file_api_proto_v1_order_proto_enumTypes = make([]protoimpl.EnumInfo, 1) 244 | var file_api_proto_v1_order_proto_msgTypes = make([]protoimpl.MessageInfo, 1) 245 | var file_api_proto_v1_order_proto_goTypes = []interface{}{ 246 | (OrderStatus)(0), // 0: pb.v1.OrderStatus 247 | (*Order)(nil), // 1: pb.v1.Order 248 | (*UserProduct)(nil), // 2: pb.v1.UserProduct 249 | (*timestamppb.Timestamp)(nil), // 3: google.protobuf.Timestamp 250 | } 251 | var file_api_proto_v1_order_proto_depIdxs = []int32{ 252 | 0, // 0: pb.v1.Order.status:type_name -> pb.v1.OrderStatus 253 | 2, // 1: pb.v1.Order.products:type_name -> pb.v1.UserProduct 254 | 3, // 2: pb.v1.Order.created_at:type_name -> google.protobuf.Timestamp 255 | 3, // 3: pb.v1.Order.delivered_at:type_name -> google.protobuf.Timestamp 256 | 4, // [4:4] is the sub-list for method output_type 257 | 4, // [4:4] is the sub-list for method input_type 258 | 4, // [4:4] is the sub-list for extension type_name 259 | 4, // [4:4] is the sub-list for extension extendee 260 | 0, // [0:4] is the sub-list for field type_name 261 | } 262 | 263 | func init() { file_api_proto_v1_order_proto_init() } 264 | func file_api_proto_v1_order_proto_init() { 265 | if File_api_proto_v1_order_proto != nil { 266 | return 267 | } 268 | file_api_proto_v1_common_proto_init() 269 | if !protoimpl.UnsafeEnabled { 270 | file_api_proto_v1_order_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 271 | switch v := v.(*Order); i { 272 | case 0: 273 | return &v.state 274 | case 1: 275 | return &v.sizeCache 276 | case 2: 277 | return &v.unknownFields 278 | default: 279 | return nil 280 | } 281 | } 282 | } 283 | type x struct{} 284 | out := protoimpl.TypeBuilder{ 285 | File: protoimpl.DescBuilder{ 286 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 287 | RawDescriptor: file_api_proto_v1_order_proto_rawDesc, 288 | NumEnums: 1, 289 | NumMessages: 1, 290 | NumExtensions: 0, 291 | NumServices: 0, 292 | }, 293 | GoTypes: file_api_proto_v1_order_proto_goTypes, 294 | DependencyIndexes: file_api_proto_v1_order_proto_depIdxs, 295 | EnumInfos: file_api_proto_v1_order_proto_enumTypes, 296 | MessageInfos: file_api_proto_v1_order_proto_msgTypes, 297 | }.Build() 298 | File_api_proto_v1_order_proto = out.File 299 | file_api_proto_v1_order_proto_rawDesc = nil 300 | file_api_proto_v1_order_proto_goTypes = nil 301 | file_api_proto_v1_order_proto_depIdxs = nil 302 | } 303 | -------------------------------------------------------------------------------- /pkg/common/gen/api/proto/v1/user_service_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.2.0 4 | // - protoc (unknown) 5 | // source: api/proto/v1/user_service.proto 6 | 7 | package pbv1 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | ) 15 | 16 | // This is a compile-time assertion to ensure that this generated file 17 | // is compatible with the grpc package it is being compiled against. 18 | // Requires gRPC-Go v1.32.0 or later. 19 | const _ = grpc.SupportPackageIsVersion7 20 | 21 | // UserServiceClient is the client API for UserService service. 22 | // 23 | // 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. 24 | type UserServiceClient interface { 25 | Register(ctx context.Context, in *RegisterRequest, opts ...grpc.CallOption) (*TokenResponse, error) 26 | Authorize(ctx context.Context, in *AuthorizeRequest, opts ...grpc.CallOption) (*TokenResponse, error) 27 | GetByUUID(ctx context.Context, in *GetByUserUUIDRequest, opts ...grpc.CallOption) (*User, error) 28 | GetUserProducts(ctx context.Context, in *GetByUserUUIDRequest, opts ...grpc.CallOption) (*UserProductsResponse, error) 29 | PutProduct(ctx context.Context, in *PutProductRequest, opts ...grpc.CallOption) (*UserProductsResponse, error) 30 | ChangeProduct(ctx context.Context, in *ChangeProductRequest, opts ...grpc.CallOption) (*UserProductsResponse, error) 31 | CreateOrder(ctx context.Context, in *CreateOrderRequest, opts ...grpc.CallOption) (*Order, error) 32 | } 33 | 34 | type userServiceClient struct { 35 | cc grpc.ClientConnInterface 36 | } 37 | 38 | func NewUserServiceClient(cc grpc.ClientConnInterface) UserServiceClient { 39 | return &userServiceClient{cc} 40 | } 41 | 42 | func (c *userServiceClient) Register(ctx context.Context, in *RegisterRequest, opts ...grpc.CallOption) (*TokenResponse, error) { 43 | out := new(TokenResponse) 44 | err := c.cc.Invoke(ctx, "/pb.v1.UserService/Register", in, out, opts...) 45 | if err != nil { 46 | return nil, err 47 | } 48 | return out, nil 49 | } 50 | 51 | func (c *userServiceClient) Authorize(ctx context.Context, in *AuthorizeRequest, opts ...grpc.CallOption) (*TokenResponse, error) { 52 | out := new(TokenResponse) 53 | err := c.cc.Invoke(ctx, "/pb.v1.UserService/Authorize", in, out, opts...) 54 | if err != nil { 55 | return nil, err 56 | } 57 | return out, nil 58 | } 59 | 60 | func (c *userServiceClient) GetByUUID(ctx context.Context, in *GetByUserUUIDRequest, opts ...grpc.CallOption) (*User, error) { 61 | out := new(User) 62 | err := c.cc.Invoke(ctx, "/pb.v1.UserService/GetByUUID", in, out, opts...) 63 | if err != nil { 64 | return nil, err 65 | } 66 | return out, nil 67 | } 68 | 69 | func (c *userServiceClient) GetUserProducts(ctx context.Context, in *GetByUserUUIDRequest, opts ...grpc.CallOption) (*UserProductsResponse, error) { 70 | out := new(UserProductsResponse) 71 | err := c.cc.Invoke(ctx, "/pb.v1.UserService/GetUserProducts", in, out, opts...) 72 | if err != nil { 73 | return nil, err 74 | } 75 | return out, nil 76 | } 77 | 78 | func (c *userServiceClient) PutProduct(ctx context.Context, in *PutProductRequest, opts ...grpc.CallOption) (*UserProductsResponse, error) { 79 | out := new(UserProductsResponse) 80 | err := c.cc.Invoke(ctx, "/pb.v1.UserService/PutProduct", in, out, opts...) 81 | if err != nil { 82 | return nil, err 83 | } 84 | return out, nil 85 | } 86 | 87 | func (c *userServiceClient) ChangeProduct(ctx context.Context, in *ChangeProductRequest, opts ...grpc.CallOption) (*UserProductsResponse, error) { 88 | out := new(UserProductsResponse) 89 | err := c.cc.Invoke(ctx, "/pb.v1.UserService/ChangeProduct", in, out, opts...) 90 | if err != nil { 91 | return nil, err 92 | } 93 | return out, nil 94 | } 95 | 96 | func (c *userServiceClient) CreateOrder(ctx context.Context, in *CreateOrderRequest, opts ...grpc.CallOption) (*Order, error) { 97 | out := new(Order) 98 | err := c.cc.Invoke(ctx, "/pb.v1.UserService/CreateOrder", in, out, opts...) 99 | if err != nil { 100 | return nil, err 101 | } 102 | return out, nil 103 | } 104 | 105 | // UserServiceServer is the server API for UserService service. 106 | // All implementations should embed UnimplementedUserServiceServer 107 | // for forward compatibility 108 | type UserServiceServer interface { 109 | Register(context.Context, *RegisterRequest) (*TokenResponse, error) 110 | Authorize(context.Context, *AuthorizeRequest) (*TokenResponse, error) 111 | GetByUUID(context.Context, *GetByUserUUIDRequest) (*User, error) 112 | GetUserProducts(context.Context, *GetByUserUUIDRequest) (*UserProductsResponse, error) 113 | PutProduct(context.Context, *PutProductRequest) (*UserProductsResponse, error) 114 | ChangeProduct(context.Context, *ChangeProductRequest) (*UserProductsResponse, error) 115 | CreateOrder(context.Context, *CreateOrderRequest) (*Order, error) 116 | } 117 | 118 | // UnimplementedUserServiceServer should be embedded to have forward compatible implementations. 119 | type UnimplementedUserServiceServer struct { 120 | } 121 | 122 | func (UnimplementedUserServiceServer) Register(context.Context, *RegisterRequest) (*TokenResponse, error) { 123 | return nil, status.Errorf(codes.Unimplemented, "method Register not implemented") 124 | } 125 | func (UnimplementedUserServiceServer) Authorize(context.Context, *AuthorizeRequest) (*TokenResponse, error) { 126 | return nil, status.Errorf(codes.Unimplemented, "method Authorize not implemented") 127 | } 128 | func (UnimplementedUserServiceServer) GetByUUID(context.Context, *GetByUserUUIDRequest) (*User, error) { 129 | return nil, status.Errorf(codes.Unimplemented, "method GetByUUID not implemented") 130 | } 131 | func (UnimplementedUserServiceServer) GetUserProducts(context.Context, *GetByUserUUIDRequest) (*UserProductsResponse, error) { 132 | return nil, status.Errorf(codes.Unimplemented, "method GetUserProducts not implemented") 133 | } 134 | func (UnimplementedUserServiceServer) PutProduct(context.Context, *PutProductRequest) (*UserProductsResponse, error) { 135 | return nil, status.Errorf(codes.Unimplemented, "method PutProduct not implemented") 136 | } 137 | func (UnimplementedUserServiceServer) ChangeProduct(context.Context, *ChangeProductRequest) (*UserProductsResponse, error) { 138 | return nil, status.Errorf(codes.Unimplemented, "method ChangeProduct not implemented") 139 | } 140 | func (UnimplementedUserServiceServer) CreateOrder(context.Context, *CreateOrderRequest) (*Order, error) { 141 | return nil, status.Errorf(codes.Unimplemented, "method CreateOrder not implemented") 142 | } 143 | 144 | // UnsafeUserServiceServer may be embedded to opt out of forward compatibility for this service. 145 | // Use of this interface is not recommended, as added methods to UserServiceServer will 146 | // result in compilation errors. 147 | type UnsafeUserServiceServer interface { 148 | mustEmbedUnimplementedUserServiceServer() 149 | } 150 | 151 | func RegisterUserServiceServer(s grpc.ServiceRegistrar, srv UserServiceServer) { 152 | s.RegisterService(&UserService_ServiceDesc, srv) 153 | } 154 | 155 | func _UserService_Register_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 156 | in := new(RegisterRequest) 157 | if err := dec(in); err != nil { 158 | return nil, err 159 | } 160 | if interceptor == nil { 161 | return srv.(UserServiceServer).Register(ctx, in) 162 | } 163 | info := &grpc.UnaryServerInfo{ 164 | Server: srv, 165 | FullMethod: "/pb.v1.UserService/Register", 166 | } 167 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 168 | return srv.(UserServiceServer).Register(ctx, req.(*RegisterRequest)) 169 | } 170 | return interceptor(ctx, in, info, handler) 171 | } 172 | 173 | func _UserService_Authorize_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 174 | in := new(AuthorizeRequest) 175 | if err := dec(in); err != nil { 176 | return nil, err 177 | } 178 | if interceptor == nil { 179 | return srv.(UserServiceServer).Authorize(ctx, in) 180 | } 181 | info := &grpc.UnaryServerInfo{ 182 | Server: srv, 183 | FullMethod: "/pb.v1.UserService/Authorize", 184 | } 185 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 186 | return srv.(UserServiceServer).Authorize(ctx, req.(*AuthorizeRequest)) 187 | } 188 | return interceptor(ctx, in, info, handler) 189 | } 190 | 191 | func _UserService_GetByUUID_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 192 | in := new(GetByUserUUIDRequest) 193 | if err := dec(in); err != nil { 194 | return nil, err 195 | } 196 | if interceptor == nil { 197 | return srv.(UserServiceServer).GetByUUID(ctx, in) 198 | } 199 | info := &grpc.UnaryServerInfo{ 200 | Server: srv, 201 | FullMethod: "/pb.v1.UserService/GetByUUID", 202 | } 203 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 204 | return srv.(UserServiceServer).GetByUUID(ctx, req.(*GetByUserUUIDRequest)) 205 | } 206 | return interceptor(ctx, in, info, handler) 207 | } 208 | 209 | func _UserService_GetUserProducts_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 210 | in := new(GetByUserUUIDRequest) 211 | if err := dec(in); err != nil { 212 | return nil, err 213 | } 214 | if interceptor == nil { 215 | return srv.(UserServiceServer).GetUserProducts(ctx, in) 216 | } 217 | info := &grpc.UnaryServerInfo{ 218 | Server: srv, 219 | FullMethod: "/pb.v1.UserService/GetUserProducts", 220 | } 221 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 222 | return srv.(UserServiceServer).GetUserProducts(ctx, req.(*GetByUserUUIDRequest)) 223 | } 224 | return interceptor(ctx, in, info, handler) 225 | } 226 | 227 | func _UserService_PutProduct_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 228 | in := new(PutProductRequest) 229 | if err := dec(in); err != nil { 230 | return nil, err 231 | } 232 | if interceptor == nil { 233 | return srv.(UserServiceServer).PutProduct(ctx, in) 234 | } 235 | info := &grpc.UnaryServerInfo{ 236 | Server: srv, 237 | FullMethod: "/pb.v1.UserService/PutProduct", 238 | } 239 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 240 | return srv.(UserServiceServer).PutProduct(ctx, req.(*PutProductRequest)) 241 | } 242 | return interceptor(ctx, in, info, handler) 243 | } 244 | 245 | func _UserService_ChangeProduct_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 246 | in := new(ChangeProductRequest) 247 | if err := dec(in); err != nil { 248 | return nil, err 249 | } 250 | if interceptor == nil { 251 | return srv.(UserServiceServer).ChangeProduct(ctx, in) 252 | } 253 | info := &grpc.UnaryServerInfo{ 254 | Server: srv, 255 | FullMethod: "/pb.v1.UserService/ChangeProduct", 256 | } 257 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 258 | return srv.(UserServiceServer).ChangeProduct(ctx, req.(*ChangeProductRequest)) 259 | } 260 | return interceptor(ctx, in, info, handler) 261 | } 262 | 263 | func _UserService_CreateOrder_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 264 | in := new(CreateOrderRequest) 265 | if err := dec(in); err != nil { 266 | return nil, err 267 | } 268 | if interceptor == nil { 269 | return srv.(UserServiceServer).CreateOrder(ctx, in) 270 | } 271 | info := &grpc.UnaryServerInfo{ 272 | Server: srv, 273 | FullMethod: "/pb.v1.UserService/CreateOrder", 274 | } 275 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 276 | return srv.(UserServiceServer).CreateOrder(ctx, req.(*CreateOrderRequest)) 277 | } 278 | return interceptor(ctx, in, info, handler) 279 | } 280 | 281 | // UserService_ServiceDesc is the grpc.ServiceDesc for UserService service. 282 | // It's only intended for direct use with grpc.RegisterService, 283 | // and not to be introspected or modified (even as a copy) 284 | var UserService_ServiceDesc = grpc.ServiceDesc{ 285 | ServiceName: "pb.v1.UserService", 286 | HandlerType: (*UserServiceServer)(nil), 287 | Methods: []grpc.MethodDesc{ 288 | { 289 | MethodName: "Register", 290 | Handler: _UserService_Register_Handler, 291 | }, 292 | { 293 | MethodName: "Authorize", 294 | Handler: _UserService_Authorize_Handler, 295 | }, 296 | { 297 | MethodName: "GetByUUID", 298 | Handler: _UserService_GetByUUID_Handler, 299 | }, 300 | { 301 | MethodName: "GetUserProducts", 302 | Handler: _UserService_GetUserProducts_Handler, 303 | }, 304 | { 305 | MethodName: "PutProduct", 306 | Handler: _UserService_PutProduct_Handler, 307 | }, 308 | { 309 | MethodName: "ChangeProduct", 310 | Handler: _UserService_ChangeProduct_Handler, 311 | }, 312 | { 313 | MethodName: "CreateOrder", 314 | Handler: _UserService_CreateOrder_Handler, 315 | }, 316 | }, 317 | Streams: []grpc.StreamDesc{}, 318 | Metadata: "api/proto/v1/user_service.proto", 319 | } 320 | --------------------------------------------------------------------------------