diff --git a/api/main.proto b/api/main.proto index 3706e6c..94ec482 100644 --- a/api/main.proto +++ b/api/main.proto @@ -38,6 +38,13 @@ service EveningDetectiveServer { body: "*" }; } + + rpc Refresh(RefreshReq) returns (RefreshRsp) { + option (google.api.http) = { + post: "/api/refresh" + body: "*" + }; + } } message PingReq {} @@ -79,3 +86,13 @@ message LoginRsp { string accessToken = 2; string refreshToken = 3; } + +message RefreshReq { + string refreshToken = 1; +} + +message RefreshRsp { + string error = 1; + string accessToken = 2; + string refreshToken = 3; +} diff --git a/cmd/evening_detective_server/main.swagger.json b/cmd/evening_detective_server/main.swagger.json index bcd372e..a6d1394 100644 --- a/cmd/evening_detective_server/main.swagger.json +++ b/cmd/evening_detective_server/main.swagger.json @@ -100,6 +100,38 @@ ] } }, + "/api/refresh": { + "post": { + "operationId": "EveningDetectiveServer_Refresh", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/evening_detective_serverRefreshRsp" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/evening_detective_serverRefreshReq" + } + } + ], + "tags": [ + "EveningDetectiveServer" + ] + } + }, "/api/refresh-password": { "post": { "operationId": "EveningDetectiveServer_RefreshPassword", @@ -218,6 +250,28 @@ } } }, + "evening_detective_serverRefreshReq": { + "type": "object", + "properties": { + "refreshToken": { + "type": "string" + } + } + }, + "evening_detective_serverRefreshRsp": { + "type": "object", + "properties": { + "error": { + "type": "string" + }, + "accessToken": { + "type": "string" + }, + "refreshToken": { + "type": "string" + } + } + }, "evening_detective_serverSignupReq": { "type": "object", "properties": { diff --git a/docker-compose-db.yml b/docker-compose-db.yml index a707661..3dd23ed 100644 --- a/docker-compose-db.yml +++ b/docker-compose-db.yml @@ -8,6 +8,8 @@ services: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: evening_detective_server + TZ: Asia/Barnaul # Для системного времени контейнера + PGTZ: Asia/Barnaul # Специфичная для PostgreSQL переменная ports: - "5432:5432" volumes: diff --git a/go.mod b/go.mod index 2e12f11..fa734c9 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require github.com/vearutop/statigz v1.4.0 // indirect require ( github.com/golang-jwt/jwt/v5 v5.3.1 + github.com/google/uuid v1.6.0 github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/pgx/v5 v5.10.0 diff --git a/internal/app/server.go b/internal/app/server.go index 03a7982..b0ec964 100644 --- a/internal/app/server.go +++ b/internal/app/server.go @@ -60,3 +60,16 @@ func (s *server) Login(ctx context.Context, req *proto.LoginReq) (*proto.LoginRs RefreshToken: refreshToken, }, nil } + +func (s *server) Refresh(ctx context.Context, req *proto.RefreshReq) (*proto.RefreshRsp, error) { + accessToken, refreshToken, err := s.usersService.Refresh(ctx, req.RefreshToken) + if err != nil { + return &proto.RefreshRsp{ + Error: err.Error(), + }, nil + } + return &proto.RefreshRsp{ + AccessToken: accessToken, + RefreshToken: refreshToken, + }, nil +} diff --git a/internal/modules/processor_jwt/processor.go b/internal/modules/processor_jwt/processor.go index 01d3514..bb291af 100644 --- a/internal/modules/processor_jwt/processor.go +++ b/internal/modules/processor_jwt/processor.go @@ -5,15 +5,16 @@ import ( "time" "github.com/golang-jwt/jwt/v5" + "github.com/google/uuid" ) type processor struct { - secret string + secret []byte } func NewProcessor(secret string) IProcessorJWT { return &processor{ - secret: secret, + secret: []byte(secret), } } @@ -32,7 +33,7 @@ func (p *processor) GenerateAccessToken(userId int, userEmail string, userRoles } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - return token.SignedString([]byte(p.secret)) + return token.SignedString(p.secret) } func (p *processor) GenerateRefreshToken(userId int) (string, error) { @@ -44,11 +45,12 @@ func (p *processor) GenerateRefreshToken(userId int) (string, error) { ExpiresAt: jwt.NewNumericDate(now.Add(7 * 24 * time.Hour)), IssuedAt: jwt.NewNumericDate(now), NotBefore: jwt.NewNumericDate(now), + ID: uuid.New().String(), }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - return token.SignedString([]byte(p.secret)) + return token.SignedString(p.secret) } func (p *processor) GetClaims(token string) (*JWTClaims, error) { diff --git a/internal/repos/refresh_tokens_repo/repo.go b/internal/repos/refresh_tokens_repo/repo.go index 3b0959c..7aab81a 100644 --- a/internal/repos/refresh_tokens_repo/repo.go +++ b/internal/repos/refresh_tokens_repo/repo.go @@ -2,6 +2,7 @@ package refresh_tokens_repo import ( "context" + "time" "github.com/jackc/pgx/v5/pgxpool" ) @@ -19,25 +20,57 @@ func NewRefreshTokensRepo(pool *pgxpool.Pool) *RefreshTokensRepo { func (s *RefreshTokensRepo) AddRefreshToken( ctx context.Context, userId int, - refreshToken string, + expiresAt time.Time, + jti string, ) error { _, err := s.pool.Exec( ctx, - `INSERT INTO refresh_tokens (user_id, refresh_token) VALUES ($1, $2)`, + `INSERT INTO refresh_tokens (user_id, expires_at, jti) + VALUES ($1, $2, $3)`, userId, - refreshToken, + expiresAt, + jti, ) return err } -func (s *RefreshTokensRepo) DeleteRefreshTokensByUserId( +func (s *RefreshTokensRepo) ExistsRefreshToken( ctx context.Context, userId int, + jti string, + now time.Time, +) (bool, error) { + var exists bool + + err := s.pool.QueryRow( + ctx, + `SELECT EXISTS( + SELECT 1 + FROM refresh_tokens + WHERE user_id = $1 + AND jti = $2 + AND expires_at > $3 + )`, + userId, + jti, + now, + ).Scan(&exists) + if err != nil { + return false, err + } + + return exists, nil +} + +func (s *RefreshTokensRepo) DeleteRefreshTokenByJti( + ctx context.Context, + jti string, ) error { _, err := s.pool.Exec( ctx, - `DELETE FROM refresh_tokens WHERE user_id = $1`, - userId, + `DELETE FROM refresh_tokens + WHERE jti = $1`, + jti, ) return err } diff --git a/internal/repos/user.go b/internal/repos/user.go index 9743fc9..38ba16a 100644 --- a/internal/repos/user.go +++ b/internal/repos/user.go @@ -5,6 +5,6 @@ type User struct { Username string Email string PasswordHash string - Role string + Roles []string IsActive bool } diff --git a/internal/repos/users_repo/repo.go b/internal/repos/users_repo/repo.go index dd2a39d..19b4311 100644 --- a/internal/repos/users_repo/repo.go +++ b/internal/repos/users_repo/repo.go @@ -28,11 +28,11 @@ func (s *UsersRepo) AddUser( username string, email string, passwordHash string, - role string, + roles []string, ) error { tag, err := s.pool.Exec( ctx, - `INSERT INTO users (username, email, password_hash, role) + `INSERT INTO users (username, email, password_hash, roles) SELECT $1, $2, $3, $4 WHERE NOT EXISTS ( SELECT 1 FROM users @@ -41,7 +41,7 @@ func (s *UsersRepo) AddUser( username, email, passwordHash, - role, + roles, username, email, @@ -85,7 +85,7 @@ func (s *UsersRepo) GetUserByEmail( user := &repos.User{} row := s.pool.QueryRow( ctx, - `SELECT id, username, email, password_hash, role, is_active + `SELECT id, username, email, password_hash, roles, is_active FROM users WHERE email = $1`, email, @@ -95,7 +95,37 @@ func (s *UsersRepo) GetUserByEmail( &user.Username, &user.Email, &user.PasswordHash, - &user.Role, + &user.Roles, + &user.IsActive, + ) + if err != nil { + if errors.Is(err, pgx.ErrNoRows) { + return nil, ErrUserNotFound + } + return nil, err + } + + return user, nil +} + +func (s *UsersRepo) GetUserByID( + ctx context.Context, + id int, +) (*repos.User, error) { + user := &repos.User{} + row := s.pool.QueryRow( + ctx, + `SELECT id, username, email, password_hash, roles, is_active + FROM users + WHERE id = $1`, + id, + ) + err := row.Scan( + &user.ID, + &user.Username, + &user.Email, + &user.PasswordHash, + &user.Roles, &user.IsActive, ) if err != nil { diff --git a/internal/services/users_service/service.go b/internal/services/users_service/service.go index 9c5fc1b..20f37cf 100644 --- a/internal/services/users_service/service.go +++ b/internal/services/users_service/service.go @@ -9,7 +9,7 @@ import ( "evening_detective_server/internal/repos/refresh_tokens_repo" "evening_detective_server/internal/repos/users_repo" "fmt" - "strings" + "time" "golang.org/x/crypto/bcrypt" ) @@ -56,7 +56,7 @@ func (s *UsersService) AddUser( username, email, string(hashedPassword), - "user", + []string{"user"}, ) if err != nil { return err @@ -119,26 +119,67 @@ func (s *UsersService) Login( return "", "", errors.New("Не верен email или пароль") } - roles := strings.Split(user.Role, " ") - accessToken, err := s.processorJWT.GenerateAccessToken(user.ID, user.Email, roles) + accessToken, err := s.processorJWT.GenerateAccessToken(user.ID, user.Email, user.Roles) if err != nil { - fmt.Println(err) return "", "", errors.New("Не получилось получить доступ") } refreshToken, err := s.processorJWT.GenerateRefreshToken(user.ID) if err != nil { - fmt.Println(err) + return "", "", errors.New("Не получилось получить доступ") + } + refreshTokenClaims, err := s.processorJWT.GetClaims(refreshToken) + if err != nil { return "", "", errors.New("Не получилось получить доступ") } - fmt.Println(accessToken, refreshToken) - - if err := s.refreshTokensRepo.DeleteRefreshTokensByUserId(ctx, user.ID); err != nil { - return "", "", err - } - - if err := s.refreshTokensRepo.AddRefreshToken(ctx, user.ID, refreshToken); err != nil { + if err := s.refreshTokensRepo.AddRefreshToken(ctx, user.ID, refreshTokenClaims.ExpiresAt.Time, refreshTokenClaims.ID); err != nil { + return "", "", err + } + + return accessToken, refreshToken, nil +} + +func (s *UsersService) Refresh( + ctx context.Context, + token string, +) (string, string, error) { + claims, err := s.processorJWT.GetClaims(token) + if err != nil { + return "", "", err + } + + ok, err := s.refreshTokensRepo.ExistsRefreshToken(ctx, claims.UserID, claims.ID, time.Now()) + if err != nil { + return "", "", err + } + if !ok { + return "", "", errors.New("Пользователь не найден") + } + if err := s.refreshTokensRepo.DeleteRefreshTokenByJti(ctx, claims.ID); err != nil { + return "", "", err + } + + user, err := s.usersRepo.GetUserByID(ctx, claims.UserID) + if err != nil { + return "", "", err + } + + accessToken, err := s.processorJWT.GenerateAccessToken(user.ID, user.Email, user.Roles) + if err != nil { + return "", "", errors.New("Не получилось получить доступ") + } + + refreshToken, err := s.processorJWT.GenerateRefreshToken(user.ID) + if err != nil { + return "", "", errors.New("Не получилось получить доступ") + } + refreshTokenClaims, err := s.processorJWT.GetClaims(refreshToken) + if err != nil { + return "", "", errors.New("Не получилось получить доступ") + } + + if err := s.refreshTokensRepo.AddRefreshToken(ctx, user.ID, refreshTokenClaims.ExpiresAt.Time, refreshTokenClaims.ID); err != nil { return "", "", err } diff --git a/migrations/20260628175120_create_users_table.sql b/migrations/20260628175120_create_users_table.sql index 485f0dd..005cceb 100644 --- a/migrations/20260628175120_create_users_table.sql +++ b/migrations/20260628175120_create_users_table.sql @@ -1,13 +1,14 @@ -- +goose Up -CREATE TABLE IF NOT EXISTS users ( - id SERIAL PRIMARY KEY, - username VARCHAR(50) NOT NULL UNIQUE, - email VARCHAR(100) NOT NULL UNIQUE, - password_hash VARCHAR(255) NOT NULL, - role VARCHAR(20) CHECK (role IN ('admin', 'author', 'organizer', 'user')), - is_active BOOLEAN DEFAULT TRUE, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -); +CREATE TABLE + IF NOT EXISTS users ( + id SERIAL PRIMARY KEY, + username VARCHAR(50) NOT NULL UNIQUE, + email VARCHAR(100) NOT NULL UNIQUE, + password_hash VARCHAR(255) NOT NULL, + roles jsonb NOT NULL DEFAULT '[]'::jsonb, + is_active BOOLEAN DEFAULT TRUE, + created_at TIMESTAMP NOT NULL DEFAULT NOW () + ); -- +goose Down -DROP TABLE IF EXISTS users; +DROP TABLE IF EXISTS users; \ No newline at end of file diff --git a/migrations/20260704192907_refresh_tokens_table.sql b/migrations/20260704192907_refresh_tokens_table.sql index 4e6ec7a..1ee3e1c 100644 --- a/migrations/20260704192907_refresh_tokens_table.sql +++ b/migrations/20260704192907_refresh_tokens_table.sql @@ -1,11 +1,13 @@ -- +goose Up -CREATE TABLE IF NOT EXISTS refresh_tokens ( - id UUID PRIMARY KEY DEFAULT gen_random_uuid(), - user_id INT NOT NULL, - refresh_token TEXT NOT NULL, - - CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE -); +CREATE TABLE + IF NOT EXISTS refresh_tokens ( + id SERIAL PRIMARY KEY, + user_id INT NOT NULL, + expires_at TIMESTAMP NOT NULL, + jti VARCHAR(255) NOT NULL UNIQUE, + created_at TIMESTAMP NOT NULL DEFAULT NOW (), + CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE + ); -- +goose Down -DROP TABLE IF EXISTS refresh_tokens; +DROP TABLE IF EXISTS refresh_tokens; \ No newline at end of file diff --git a/proto/main.pb.go b/proto/main.pb.go index a189556..19a3197 100644 --- a/proto/main.pb.go +++ b/proto/main.pb.go @@ -478,6 +478,110 @@ func (x *LoginRsp) GetRefreshToken() string { return "" } +type RefreshReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + RefreshToken string `protobuf:"bytes,1,opt,name=refreshToken,proto3" json:"refreshToken,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RefreshReq) Reset() { + *x = RefreshReq{} + mi := &file_main_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RefreshReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RefreshReq) ProtoMessage() {} + +func (x *RefreshReq) ProtoReflect() protoreflect.Message { + mi := &file_main_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RefreshReq.ProtoReflect.Descriptor instead. +func (*RefreshReq) Descriptor() ([]byte, []int) { + return file_main_proto_rawDescGZIP(), []int{10} +} + +func (x *RefreshReq) GetRefreshToken() string { + if x != nil { + return x.RefreshToken + } + return "" +} + +type RefreshRsp struct { + state protoimpl.MessageState `protogen:"open.v1"` + Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` + AccessToken string `protobuf:"bytes,2,opt,name=accessToken,proto3" json:"accessToken,omitempty"` + RefreshToken string `protobuf:"bytes,3,opt,name=refreshToken,proto3" json:"refreshToken,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *RefreshRsp) Reset() { + *x = RefreshRsp{} + mi := &file_main_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *RefreshRsp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RefreshRsp) ProtoMessage() {} + +func (x *RefreshRsp) ProtoReflect() protoreflect.Message { + mi := &file_main_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RefreshRsp.ProtoReflect.Descriptor instead. +func (*RefreshRsp) Descriptor() ([]byte, []int) { + return file_main_proto_rawDescGZIP(), []int{11} +} + +func (x *RefreshRsp) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +func (x *RefreshRsp) GetAccessToken() string { + if x != nil { + return x.AccessToken + } + return "" +} + +func (x *RefreshRsp) GetRefreshToken() string { + if x != nil { + return x.RefreshToken + } + return "" +} + var File_main_proto protoreflect.FileDescriptor const file_main_proto_rawDesc = "" + @@ -505,14 +609,23 @@ const file_main_proto_rawDesc = "" + "\bLoginRsp\x12\x14\n" + "\x05error\x18\x01 \x01(\tR\x05error\x12 \n" + "\vaccessToken\x18\x02 \x01(\tR\vaccessToken\x12\"\n" + - "\frefreshToken\x18\x03 \x01(\tR\frefreshToken2\xfc\x04\n" + + "\frefreshToken\x18\x03 \x01(\tR\frefreshToken\"0\n" + + "\n" + + "RefreshReq\x12\"\n" + + "\frefreshToken\x18\x01 \x01(\tR\frefreshToken\"h\n" + + "\n" + + "RefreshRsp\x12\x14\n" + + "\x05error\x18\x01 \x01(\tR\x05error\x12 \n" + + "\vaccessToken\x18\x02 \x01(\tR\vaccessToken\x12\"\n" + + "\frefreshToken\x18\x03 \x01(\tR\frefreshToken2\xf8\x05\n" + "\x16EveningDetectiveServer\x12k\n" + "\x04Ping\x12'.crabs.evening_detective_server.PingReq\x1a'.crabs.evening_detective_server.PingRsp\"\x11\x82\xd3\xe4\x93\x02\v\x12\t/api/ping\x12k\n" + "\x04Echo\x12'.crabs.evening_detective_server.EchoReq\x1a'.crabs.evening_detective_server.EchoRsp\"\x11\x82\xd3\xe4\x93\x02\v\"\t/api/echo\x12v\n" + "\x06Signup\x12).crabs.evening_detective_server.SignupReq\x1a).crabs.evening_detective_server.SignupRsp\"\x16\x82\xd3\xe4\x93\x02\x10:\x01*\"\v/api/signup\x12\x9b\x01\n" + "\x0fRefreshPassword\x122.crabs.evening_detective_server.RefreshPasswordReq\x1a2.crabs.evening_detective_server.RefreshPasswordRsp\" \x82\xd3\xe4\x93\x02\x1a:\x01*\"\x15/api/refresh-password\x12r\n" + "\x05Login\x12(.crabs.evening_detective_server.LoginReq\x1a(.crabs.evening_detective_server.LoginRsp\"\x15\x82\xd3\xe4\x93\x02\x0f:\x01*\"\n" + - "/api/loginB\vZ\tpkg/protob\x06proto3" + "/api/login\x12z\n" + + "\aRefresh\x12*.crabs.evening_detective_server.RefreshReq\x1a*.crabs.evening_detective_server.RefreshRsp\"\x17\x82\xd3\xe4\x93\x02\x11:\x01*\"\f/api/refreshB\vZ\tpkg/protob\x06proto3" var ( file_main_proto_rawDescOnce sync.Once @@ -526,7 +639,7 @@ func file_main_proto_rawDescGZIP() []byte { return file_main_proto_rawDescData } -var file_main_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_main_proto_msgTypes = make([]protoimpl.MessageInfo, 12) var file_main_proto_goTypes = []any{ (*PingReq)(nil), // 0: crabs.evening_detective_server.PingReq (*PingRsp)(nil), // 1: crabs.evening_detective_server.PingRsp @@ -538,23 +651,27 @@ var file_main_proto_goTypes = []any{ (*RefreshPasswordRsp)(nil), // 7: crabs.evening_detective_server.RefreshPasswordRsp (*LoginReq)(nil), // 8: crabs.evening_detective_server.LoginReq (*LoginRsp)(nil), // 9: crabs.evening_detective_server.LoginRsp + (*RefreshReq)(nil), // 10: crabs.evening_detective_server.RefreshReq + (*RefreshRsp)(nil), // 11: crabs.evening_detective_server.RefreshRsp } var file_main_proto_depIdxs = []int32{ - 0, // 0: crabs.evening_detective_server.EveningDetectiveServer.Ping:input_type -> crabs.evening_detective_server.PingReq - 2, // 1: crabs.evening_detective_server.EveningDetectiveServer.Echo:input_type -> crabs.evening_detective_server.EchoReq - 4, // 2: crabs.evening_detective_server.EveningDetectiveServer.Signup:input_type -> crabs.evening_detective_server.SignupReq - 6, // 3: crabs.evening_detective_server.EveningDetectiveServer.RefreshPassword:input_type -> crabs.evening_detective_server.RefreshPasswordReq - 8, // 4: crabs.evening_detective_server.EveningDetectiveServer.Login:input_type -> crabs.evening_detective_server.LoginReq - 1, // 5: crabs.evening_detective_server.EveningDetectiveServer.Ping:output_type -> crabs.evening_detective_server.PingRsp - 3, // 6: crabs.evening_detective_server.EveningDetectiveServer.Echo:output_type -> crabs.evening_detective_server.EchoRsp - 5, // 7: crabs.evening_detective_server.EveningDetectiveServer.Signup:output_type -> crabs.evening_detective_server.SignupRsp - 7, // 8: crabs.evening_detective_server.EveningDetectiveServer.RefreshPassword:output_type -> crabs.evening_detective_server.RefreshPasswordRsp - 9, // 9: crabs.evening_detective_server.EveningDetectiveServer.Login:output_type -> crabs.evening_detective_server.LoginRsp - 5, // [5:10] is the sub-list for method output_type - 0, // [0:5] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name + 0, // 0: crabs.evening_detective_server.EveningDetectiveServer.Ping:input_type -> crabs.evening_detective_server.PingReq + 2, // 1: crabs.evening_detective_server.EveningDetectiveServer.Echo:input_type -> crabs.evening_detective_server.EchoReq + 4, // 2: crabs.evening_detective_server.EveningDetectiveServer.Signup:input_type -> crabs.evening_detective_server.SignupReq + 6, // 3: crabs.evening_detective_server.EveningDetectiveServer.RefreshPassword:input_type -> crabs.evening_detective_server.RefreshPasswordReq + 8, // 4: crabs.evening_detective_server.EveningDetectiveServer.Login:input_type -> crabs.evening_detective_server.LoginReq + 10, // 5: crabs.evening_detective_server.EveningDetectiveServer.Refresh:input_type -> crabs.evening_detective_server.RefreshReq + 1, // 6: crabs.evening_detective_server.EveningDetectiveServer.Ping:output_type -> crabs.evening_detective_server.PingRsp + 3, // 7: crabs.evening_detective_server.EveningDetectiveServer.Echo:output_type -> crabs.evening_detective_server.EchoRsp + 5, // 8: crabs.evening_detective_server.EveningDetectiveServer.Signup:output_type -> crabs.evening_detective_server.SignupRsp + 7, // 9: crabs.evening_detective_server.EveningDetectiveServer.RefreshPassword:output_type -> crabs.evening_detective_server.RefreshPasswordRsp + 9, // 10: crabs.evening_detective_server.EveningDetectiveServer.Login:output_type -> crabs.evening_detective_server.LoginRsp + 11, // 11: crabs.evening_detective_server.EveningDetectiveServer.Refresh:output_type -> crabs.evening_detective_server.RefreshRsp + 6, // [6:12] is the sub-list for method output_type + 0, // [0:6] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name } func init() { file_main_proto_init() } @@ -568,7 +685,7 @@ func file_main_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_main_proto_rawDesc), len(file_main_proto_rawDesc)), NumEnums: 0, - NumMessages: 10, + NumMessages: 12, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/main.pb.gw.go b/proto/main.pb.gw.go index e6991cc..4af4d16 100644 --- a/proto/main.pb.gw.go +++ b/proto/main.pb.gw.go @@ -172,6 +172,33 @@ func local_request_EveningDetectiveServer_Login_0(ctx context.Context, marshaler return msg, metadata, err } +func request_EveningDetectiveServer_Refresh_0(ctx context.Context, marshaler runtime.Marshaler, client EveningDetectiveServerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq RefreshReq + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + msg, err := client.Refresh(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_EveningDetectiveServer_Refresh_0(ctx context.Context, marshaler runtime.Marshaler, server EveningDetectiveServerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq RefreshReq + metadata runtime.ServerMetadata + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.Refresh(ctx, &protoReq) + return msg, metadata, err +} + // RegisterEveningDetectiveServerHandlerServer registers the http handlers for service EveningDetectiveServer to "mux". // UnaryRPC :call EveningDetectiveServerServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -278,6 +305,26 @@ func RegisterEveningDetectiveServerHandlerServer(ctx context.Context, mux *runti } forward_EveningDetectiveServer_Login_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) + mux.Handle(http.MethodPost, pattern_EveningDetectiveServer_Refresh_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/crabs.evening_detective_server.EveningDetectiveServer/Refresh", runtime.WithHTTPPathPattern("/api/refresh")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_EveningDetectiveServer_Refresh_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_EveningDetectiveServer_Refresh_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) return nil } @@ -403,6 +450,23 @@ func RegisterEveningDetectiveServerHandlerClient(ctx context.Context, mux *runti } forward_EveningDetectiveServer_Login_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) + mux.Handle(http.MethodPost, pattern_EveningDetectiveServer_Refresh_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/crabs.evening_detective_server.EveningDetectiveServer/Refresh", runtime.WithHTTPPathPattern("/api/refresh")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_EveningDetectiveServer_Refresh_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + forward_EveningDetectiveServer_Refresh_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) return nil } @@ -412,6 +476,7 @@ var ( pattern_EveningDetectiveServer_Signup_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"api", "signup"}, "")) pattern_EveningDetectiveServer_RefreshPassword_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"api", "refresh-password"}, "")) pattern_EveningDetectiveServer_Login_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"api", "login"}, "")) + pattern_EveningDetectiveServer_Refresh_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"api", "refresh"}, "")) ) var ( @@ -420,4 +485,5 @@ var ( forward_EveningDetectiveServer_Signup_0 = runtime.ForwardResponseMessage forward_EveningDetectiveServer_RefreshPassword_0 = runtime.ForwardResponseMessage forward_EveningDetectiveServer_Login_0 = runtime.ForwardResponseMessage + forward_EveningDetectiveServer_Refresh_0 = runtime.ForwardResponseMessage ) diff --git a/proto/main_grpc.pb.go b/proto/main_grpc.pb.go index 3add31c..2e31ac0 100644 --- a/proto/main_grpc.pb.go +++ b/proto/main_grpc.pb.go @@ -24,6 +24,7 @@ const ( EveningDetectiveServer_Signup_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/Signup" EveningDetectiveServer_RefreshPassword_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/RefreshPassword" EveningDetectiveServer_Login_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/Login" + EveningDetectiveServer_Refresh_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/Refresh" ) // EveningDetectiveServerClient is the client API for EveningDetectiveServer service. @@ -35,6 +36,7 @@ type EveningDetectiveServerClient interface { Signup(ctx context.Context, in *SignupReq, opts ...grpc.CallOption) (*SignupRsp, error) RefreshPassword(ctx context.Context, in *RefreshPasswordReq, opts ...grpc.CallOption) (*RefreshPasswordRsp, error) Login(ctx context.Context, in *LoginReq, opts ...grpc.CallOption) (*LoginRsp, error) + Refresh(ctx context.Context, in *RefreshReq, opts ...grpc.CallOption) (*RefreshRsp, error) } type eveningDetectiveServerClient struct { @@ -95,6 +97,16 @@ func (c *eveningDetectiveServerClient) Login(ctx context.Context, in *LoginReq, return out, nil } +func (c *eveningDetectiveServerClient) Refresh(ctx context.Context, in *RefreshReq, opts ...grpc.CallOption) (*RefreshRsp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(RefreshRsp) + err := c.cc.Invoke(ctx, EveningDetectiveServer_Refresh_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + // EveningDetectiveServerServer is the server API for EveningDetectiveServer service. // All implementations must embed UnimplementedEveningDetectiveServerServer // for forward compatibility. @@ -104,6 +116,7 @@ type EveningDetectiveServerServer interface { Signup(context.Context, *SignupReq) (*SignupRsp, error) RefreshPassword(context.Context, *RefreshPasswordReq) (*RefreshPasswordRsp, error) Login(context.Context, *LoginReq) (*LoginRsp, error) + Refresh(context.Context, *RefreshReq) (*RefreshRsp, error) mustEmbedUnimplementedEveningDetectiveServerServer() } @@ -129,6 +142,9 @@ func (UnimplementedEveningDetectiveServerServer) RefreshPassword(context.Context func (UnimplementedEveningDetectiveServerServer) Login(context.Context, *LoginReq) (*LoginRsp, error) { return nil, status.Error(codes.Unimplemented, "method Login not implemented") } +func (UnimplementedEveningDetectiveServerServer) Refresh(context.Context, *RefreshReq) (*RefreshRsp, error) { + return nil, status.Error(codes.Unimplemented, "method Refresh not implemented") +} func (UnimplementedEveningDetectiveServerServer) mustEmbedUnimplementedEveningDetectiveServerServer() { } func (UnimplementedEveningDetectiveServerServer) testEmbeddedByValue() {} @@ -241,6 +257,24 @@ func _EveningDetectiveServer_Login_Handler(srv interface{}, ctx context.Context, return interceptor(ctx, in, info, handler) } +func _EveningDetectiveServer_Refresh_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(RefreshReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EveningDetectiveServerServer).Refresh(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EveningDetectiveServer_Refresh_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EveningDetectiveServerServer).Refresh(ctx, req.(*RefreshReq)) + } + return interceptor(ctx, in, info, handler) +} + // EveningDetectiveServer_ServiceDesc is the grpc.ServiceDesc for EveningDetectiveServer service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -268,6 +302,10 @@ var EveningDetectiveServer_ServiceDesc = grpc.ServiceDesc{ MethodName: "Login", Handler: _EveningDetectiveServer_Login_Handler, }, + { + MethodName: "Refresh", + Handler: _EveningDetectiveServer_Refresh_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "main.proto",