diff --git a/api/main.proto b/api/main.proto index c91f4bf..20b4be2 100644 --- a/api/main.proto +++ b/api/main.proto @@ -41,6 +41,54 @@ option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = { }; service EveningDetectiveServer { + rpc GetTasks(GetTasksReq) returns (GetTasksRsp) { + option (google.api.http) = { get: "/api/tasks" }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + tags: "Задачи"; + summary: "Получить общую доску задач"; + description: "Доступно разработчикам и администратору."; + }; + } + rpc GetTaskAssignees(GetTaskAssigneesReq) returns (GetTaskAssigneesRsp) { + option (google.api.http) = { get: "/api/tasks/assignees" }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + tags: "Задачи"; + summary: "Получить разработчиков для назначения"; + description: "Доступно разработчикам и администратору."; + }; + } + rpc CreateTask(CreateTaskReq) returns (TaskRsp) { + option (google.api.http) = { post: "/api/tasks" body: "*" }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + tags: "Задачи"; + summary: "Создать задачу"; + description: "Доступно разработчикам и администратору."; + }; + } + rpc UpdateTask(UpdateTaskReq) returns (TaskRsp) { + option (google.api.http) = { put: "/api/tasks/{ID}" body: "*" }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + tags: "Задачи"; + summary: "Редактировать задачу"; + description: "Доступно разработчикам и администратору."; + }; + } + rpc SetTaskStatus(SetTaskStatusReq) returns (TaskRsp) { + option (google.api.http) = { post: "/api/tasks/{ID}/status" body: "*" }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + tags: "Задачи"; + summary: "Изменить статус задачи"; + description: "Доступно разработчикам и администратору."; + }; + } + rpc DeleteTask(DeleteTaskReq) returns (DeleteTaskRsp) { + option (google.api.http) = { post: "/api/tasks/{ID}/delete" body: "*" }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + tags: "Задачи"; + summary: "Удалить задачу"; + description: "Доступно разработчикам и администратору."; + }; + } rpc GetParticipation(GetParticipationReq) returns (ParticipationRsp) { option (google.api.http) = { post: "/api/participation/get" body: "*" }; option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { @@ -2188,3 +2236,56 @@ message TicketPage { optional google.protobuf.Timestamp used_at = 7; string used_by = 8; } + +// Developer tasks use new, in_progress, review and done statuses. +message DeveloperTask { + int32 ID = 1; + string title = 2; + string description = 3; + string status = 4; + // Omitted assignee means the task is unassigned. + optional int32 assigneeID = 5; + string assigneeName = 6; + optional int32 authorID = 7; + // Calendar deadline in YYYY-MM-DD format; empty means no deadline. + string dueDate = 8; + google.protobuf.Timestamp createdAt = 9; + google.protobuf.Timestamp updatedAt = 10; + // Required for updates and deletion to detect concurrent edits. + int32 version = 11; +} +message TaskAssignee { + int32 ID = 1; + string name = 2; +} +message GetTasksReq {} +message GetTasksRsp { repeated DeveloperTask tasks = 1; } +message GetTaskAssigneesReq {} +message GetTaskAssigneesRsp { repeated TaskAssignee assignees = 1; } +message CreateTaskReq { + string title = 1; + string description = 2; + string status = 3; + optional int32 assigneeID = 4; + string dueDate = 5; +} +message UpdateTaskReq { + int32 ID = 1; + string title = 2; + string description = 3; + string status = 4; + optional int32 assigneeID = 5; + string dueDate = 6; + int32 version = 7; +} +message SetTaskStatusReq { + int32 ID = 1; + string status = 2; + int32 version = 3; +} +message DeleteTaskReq { + int32 ID = 1; + int32 version = 2; +} +message TaskRsp { DeveloperTask task = 1; } +message DeleteTaskRsp {} diff --git a/bin/evening_detective_server b/bin/evening_detective_server index 43c62b3..5d07abc 100755 Binary files a/bin/evening_detective_server and b/bin/evening_detective_server differ diff --git a/cmd/evening_detective_server/main.go b/cmd/evening_detective_server/main.go index c9d319c..cb25ef0 100644 --- a/cmd/evening_detective_server/main.go +++ b/cmd/evening_detective_server/main.go @@ -25,6 +25,7 @@ import ( "evening_detective_server/internal/repos/refresh_tokens_repo" "evening_detective_server/internal/repos/scenarios_repo" "evening_detective_server/internal/repos/screen_sessions_repo" + "evening_detective_server/internal/repos/tasks_repo" "evening_detective_server/internal/repos/team_answers_repo" "evening_detective_server/internal/repos/teams_repo" "evening_detective_server/internal/repos/tickets_repo" @@ -41,6 +42,7 @@ import ( "evening_detective_server/internal/services/scenarios_service" "evening_detective_server/internal/services/screen_plan_service" "evening_detective_server/internal/services/screen_service" + "evening_detective_server/internal/services/task_service" "evening_detective_server/internal/services/team_service" "evening_detective_server/internal/services/ticket_service" "evening_detective_server/internal/services/ui_service" @@ -108,6 +110,7 @@ func main() { processorJWT := processor_jwt.NewProcessor(os.Getenv("JWT_SECRET")) refreshTokensRepo := refresh_tokens_repo.NewRefreshTokensRepo(dbpool) usersService := users_service.NewUsersService(usersRepo, passwordGenerator, emailSender, processorJWT, refreshTokensRepo, os.Getenv("APP_BASE_URL")) + taskService := task_service.NewTaskService(tasks_repo.NewTasksRepo(dbpool)) uiService := ui_service.NewUIService() fileStorage, err := file_storage.NewRustFSStorage( context.Background(), @@ -226,6 +229,7 @@ func main() { playlistService, screenPlanService, mapService, + taskService, ), ) diff --git a/cmd/evening_detective_server/main.swagger.json b/cmd/evening_detective_server/main.swagger.json index d5165b3..a7e530b 100644 --- a/cmd/evening_detective_server/main.swagger.json +++ b/cmd/evening_detective_server/main.swagger.json @@ -2724,6 +2724,209 @@ ] } }, + "/api/tasks": { + "get": { + "summary": "Получить общую доску задач", + "description": "Доступно разработчикам и администратору.", + "operationId": "EveningDetectiveServer_GetTasks", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/evening_detective_serverGetTasksRsp" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "tags": [ + "Задачи" + ] + }, + "post": { + "summary": "Создать задачу", + "description": "Доступно разработчикам и администратору.", + "operationId": "EveningDetectiveServer_CreateTask", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/evening_detective_serverTaskRsp" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/evening_detective_serverCreateTaskReq" + } + } + ], + "tags": [ + "Задачи" + ] + } + }, + "/api/tasks/assignees": { + "get": { + "summary": "Получить разработчиков для назначения", + "description": "Доступно разработчикам и администратору.", + "operationId": "EveningDetectiveServer_GetTaskAssignees", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/evening_detective_serverGetTaskAssigneesRsp" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "tags": [ + "Задачи" + ] + } + }, + "/api/tasks/{ID}": { + "put": { + "summary": "Редактировать задачу", + "description": "Доступно разработчикам и администратору.", + "operationId": "EveningDetectiveServer_UpdateTask", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/evening_detective_serverTaskRsp" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "ID", + "in": "path", + "required": true, + "type": "integer", + "format": "int32" + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/EveningDetectiveServerUpdateTaskBody" + } + } + ], + "tags": [ + "Задачи" + ] + } + }, + "/api/tasks/{ID}/delete": { + "post": { + "summary": "Удалить задачу", + "description": "Доступно разработчикам и администратору.", + "operationId": "EveningDetectiveServer_DeleteTask", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/evening_detective_serverDeleteTaskRsp" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "ID", + "in": "path", + "required": true, + "type": "integer", + "format": "int32" + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/EveningDetectiveServerDeleteTaskBody" + } + } + ], + "tags": [ + "Задачи" + ] + } + }, + "/api/tasks/{ID}/status": { + "post": { + "summary": "Изменить статус задачи", + "description": "Доступно разработчикам и администратору.", + "operationId": "EveningDetectiveServer_SetTaskStatus", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/evening_detective_serverTaskRsp" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "parameters": [ + { + "name": "ID", + "in": "path", + "required": true, + "type": "integer", + "format": "int32" + }, + { + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/EveningDetectiveServerSetTaskStatusBody" + } + } + ], + "tags": [ + "Задачи" + ] + } + }, "/api/teams": { "post": { "summary": "Создать команду", @@ -3586,6 +3789,15 @@ } } }, + "EveningDetectiveServerDeleteTaskBody": { + "type": "object", + "properties": { + "version": { + "type": "integer", + "format": "int32" + } + } + }, "EveningDetectiveServerDeleteUserRoleBody": { "type": "object", "properties": { @@ -3742,6 +3954,18 @@ } } }, + "EveningDetectiveServerSetTaskStatusBody": { + "type": "object", + "properties": { + "status": { + "type": "string" + }, + "version": { + "type": "integer", + "format": "int32" + } + } + }, "EveningDetectiveServerSetTeamAnswerScoreBody": { "type": "object", "properties": { @@ -3876,6 +4100,31 @@ } } }, + "EveningDetectiveServerUpdateTaskBody": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "status": { + "type": "string" + }, + "assigneeID": { + "type": "integer", + "format": "int32" + }, + "dueDate": { + "type": "string" + }, + "version": { + "type": "integer", + "format": "int32" + } + } + }, "EveningDetectiveServerUpdateTeamBody": { "type": "object", "properties": { @@ -4162,6 +4411,27 @@ } } }, + "evening_detective_serverCreateTaskReq": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "status": { + "type": "string" + }, + "assigneeID": { + "type": "integer", + "format": "int32" + }, + "dueDate": { + "type": "string" + } + } + }, "evening_detective_serverDeleteAccountRsp": { "type": "object" }, @@ -4186,12 +4456,63 @@ "evening_detective_serverDeleteScenarioRsp": { "type": "object" }, + "evening_detective_serverDeleteTaskRsp": { + "type": "object" + }, "evening_detective_serverDeleteTeamRsp": { "type": "object" }, "evening_detective_serverDeleteUserRoleRsp": { "type": "object" }, + "evening_detective_serverDeveloperTask": { + "type": "object", + "properties": { + "ID": { + "type": "integer", + "format": "int32" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "status": { + "type": "string" + }, + "assigneeID": { + "type": "integer", + "format": "int32", + "description": "Omitted assignee means the task is unassigned." + }, + "assigneeName": { + "type": "string" + }, + "authorID": { + "type": "integer", + "format": "int32" + }, + "dueDate": { + "type": "string", + "description": "Calendar deadline in YYYY-MM-DD format; empty means no deadline." + }, + "createdAt": { + "type": "string", + "format": "date-time" + }, + "updatedAt": { + "type": "string", + "format": "date-time" + }, + "version": { + "type": "integer", + "format": "int32", + "description": "Required for updates and deletion to detect concurrent edits." + } + }, + "description": "Developer tasks use new, in_progress, review and done statuses." + }, "evening_detective_serverDoor": { "type": "object", "properties": { @@ -4581,6 +4902,30 @@ } } }, + "evening_detective_serverGetTaskAssigneesRsp": { + "type": "object", + "properties": { + "assignees": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/evening_detective_serverTaskAssignee" + } + } + } + }, + "evening_detective_serverGetTasksRsp": { + "type": "object", + "properties": { + "tasks": { + "type": "array", + "items": { + "type": "object", + "$ref": "#/definitions/evening_detective_serverDeveloperTask" + } + } + } + }, "evening_detective_serverGetTeamAnswersRsp": { "type": "object", "properties": { @@ -5271,6 +5616,26 @@ "evening_detective_serverSubmitTeamAnswersRsp": { "type": "object" }, + "evening_detective_serverTaskAssignee": { + "type": "object", + "properties": { + "ID": { + "type": "integer", + "format": "int32" + }, + "name": { + "type": "string" + } + } + }, + "evening_detective_serverTaskRsp": { + "type": "object", + "properties": { + "task": { + "$ref": "#/definitions/evening_detective_serverDeveloperTask" + } + } + }, "evening_detective_serverTeam": { "type": "object", "properties": { diff --git a/internal/app/server.go b/internal/app/server.go index 055a9a2..bedec3e 100644 --- a/internal/app/server.go +++ b/internal/app/server.go @@ -12,6 +12,7 @@ import ( "evening_detective_server/internal/services/scenarios_service" "evening_detective_server/internal/services/screen_plan_service" "evening_detective_server/internal/services/screen_service" + "evening_detective_server/internal/services/task_service" "evening_detective_server/internal/services/team_service" "evening_detective_server/internal/services/ticket_service" "evening_detective_server/internal/services/ui_service" @@ -24,6 +25,7 @@ type server struct { usersService *users_service.UsersService uiService *ui_service.UIService + taskService *task_service.TaskService fileService *file_service.FileService scenarioService *scenarios_service.ScenarioService gameService *game_service.GameService @@ -56,8 +58,10 @@ func NewServer( playlistService *playlist_service.Service, screenPlanService *screen_plan_service.ScreenPlanService, mapService *map_service.MapService, + taskService *task_service.TaskService, ) proto.EveningDetectiveServerServer { return &server{ + taskService: taskService, usersService: usersService, uiService: uiService, fileService: fileService, diff --git a/internal/app/tasks.go b/internal/app/tasks.go new file mode 100644 index 0000000..0758cc4 --- /dev/null +++ b/internal/app/tasks.go @@ -0,0 +1,107 @@ +package app + +import ( + "context" + + "evening_detective_server/internal/modules/roles" + proto "evening_detective_server/proto" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func taskActor(ctx context.Context) (int, error) { + claims, err := claimsFromContext(ctx) + if err != nil { + return 0, err + } + if !roles.HasRole(claims, roles.Developer) { + return 0, status.Error(codes.PermissionDenied, "Нет доступа к задачам") + } + return claims.UserID, nil +} + +func (s *server) GetTasks(ctx context.Context, _ *proto.GetTasksReq) (*proto.GetTasksRsp, error) { + if _, err := taskActor(ctx); err != nil { + return nil, err + } + tasks, err := s.taskService.List(ctx) + if err != nil { + return nil, taskErrorStatus(err) + } + result := &proto.GetTasksRsp{Tasks: make([]*proto.DeveloperTask, 0, len(tasks))} + for _, task := range tasks { + result.Tasks = append(result.Tasks, mapTask(task)) + } + return result, nil +} + +func (s *server) GetTaskAssignees(ctx context.Context, _ *proto.GetTaskAssigneesReq) (*proto.GetTaskAssigneesRsp, error) { + if _, err := taskActor(ctx); err != nil { + return nil, err + } + users, err := s.taskService.ListAssignees(ctx) + if err != nil { + return nil, taskErrorStatus(err) + } + result := &proto.GetTaskAssigneesRsp{Assignees: make([]*proto.TaskAssignee, 0, len(users))} + for _, user := range users { + result.Assignees = append(result.Assignees, mapTaskAssignee(user)) + } + return result, nil +} + +func (s *server) CreateTask(ctx context.Context, req *proto.CreateTaskReq) (*proto.TaskRsp, error) { + actorID, err := taskActor(ctx) + if err != nil { + return nil, err + } + task, err := taskInput(req.GetTitle(), req.GetDescription(), req.GetStatus(), req.AssigneeID, req.GetDueDate()) + if err != nil { + return nil, taskErrorStatus(err) + } + task.AuthorID = &actorID + result, err := s.taskService.Create(ctx, task) + if err != nil { + return nil, taskErrorStatus(err) + } + return &proto.TaskRsp{Task: mapTask(result)}, nil +} + +func (s *server) UpdateTask(ctx context.Context, req *proto.UpdateTaskReq) (*proto.TaskRsp, error) { + if _, err := taskActor(ctx); err != nil { + return nil, err + } + task, err := taskInput(req.GetTitle(), req.GetDescription(), req.GetStatus(), req.AssigneeID, req.GetDueDate()) + if err != nil { + return nil, taskErrorStatus(err) + } + task.ID = int(req.GetID()) + task.Version = int(req.GetVersion()) + result, err := s.taskService.Update(ctx, task) + if err != nil { + return nil, taskErrorStatus(err) + } + return &proto.TaskRsp{Task: mapTask(result)}, nil +} + +func (s *server) SetTaskStatus(ctx context.Context, req *proto.SetTaskStatusReq) (*proto.TaskRsp, error) { + if _, err := taskActor(ctx); err != nil { + return nil, err + } + result, err := s.taskService.SetStatus(ctx, int(req.GetID()), int(req.GetVersion()), req.GetStatus()) + if err != nil { + return nil, taskErrorStatus(err) + } + return &proto.TaskRsp{Task: mapTask(result)}, nil +} + +func (s *server) DeleteTask(ctx context.Context, req *proto.DeleteTaskReq) (*proto.DeleteTaskRsp, error) { + if _, err := taskActor(ctx); err != nil { + return nil, err + } + if err := s.taskService.Delete(ctx, int(req.GetID()), int(req.GetVersion())); err != nil { + return nil, taskErrorStatus(err) + } + return &proto.DeleteTaskRsp{}, nil +} diff --git a/internal/app/tasks_errors.go b/internal/app/tasks_errors.go new file mode 100644 index 0000000..5ec43e3 --- /dev/null +++ b/internal/app/tasks_errors.go @@ -0,0 +1,27 @@ +package app + +import ( + "errors" + "log" + + "evening_detective_server/internal/services/task_service" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func taskErrorStatus(err error) error { + switch { + case errors.Is(err, task_service.ErrInvalidTask): + return status.Error(codes.InvalidArgument, task_service.ErrInvalidTask.Error()) + case errors.Is(err, task_service.ErrInvalidAssignee): + return status.Error(codes.InvalidArgument, task_service.ErrInvalidAssignee.Error()) + case errors.Is(err, task_service.ErrNotFound): + return status.Error(codes.NotFound, task_service.ErrNotFound.Error()) + case errors.Is(err, task_service.ErrConflict): + return status.Error(codes.Aborted, task_service.ErrConflict.Error()) + default: + log.Printf("task operation failed: %v", err) + return status.Error(codes.Internal, "Не удалось выполнить операцию с задачей") + } +} diff --git a/internal/app/tasks_mapper.go b/internal/app/tasks_mapper.go new file mode 100644 index 0000000..ca7aab5 --- /dev/null +++ b/internal/app/tasks_mapper.go @@ -0,0 +1,65 @@ +package app + +import ( + "evening_detective_server/internal/services/task_service" + proto "evening_detective_server/proto" + + "google.golang.org/protobuf/types/known/timestamppb" +) + +func taskInput(title, description, status string, assigneeID *int32, dueDate string) (task_service.Task, error) { + date, err := task_service.ParseDueDate(dueDate) + if err != nil { + return task_service.Task{}, err + } + return task_service.Task{ + Title: title, + Description: description, + Status: status, + AssigneeID: taskDomainID(assigneeID), + DueDate: date, + }, nil +} + +func taskDomainID(value *int32) *int { + if value == nil { + return nil + } + result := int(*value) + return &result +} + +func taskProtoID(value *int) *int32 { + if value == nil { + return nil + } + result := int32(*value) + return &result +} + +func mapTask(task *task_service.Task) *proto.DeveloperTask { + dueDate := "" + if task.DueDate != nil { + dueDate = task.DueDate.Format("2006-01-02") + } + return &proto.DeveloperTask{ + ID: int32(task.ID), + Title: task.Title, + Description: task.Description, + Status: task.Status, + AssigneeID: taskProtoID(task.AssigneeID), + AssigneeName: task.AssigneeName, + AuthorID: taskProtoID(task.AuthorID), + DueDate: dueDate, + CreatedAt: timestamppb.New(task.CreatedAt), + UpdatedAt: timestamppb.New(task.UpdatedAt), + Version: int32(task.Version), + } +} + +func mapTaskAssignee(user task_service.Assignee) *proto.TaskAssignee { + return &proto.TaskAssignee{ + ID: int32(user.ID), + Name: user.Name, + } +} diff --git a/internal/app/tasks_test.go b/internal/app/tasks_test.go new file mode 100644 index 0000000..edb546e --- /dev/null +++ b/internal/app/tasks_test.go @@ -0,0 +1,106 @@ +package app + +import ( + "context" + "errors" + "fmt" + "strings" + "testing" + "time" + + "evening_detective_server/internal/modules/processor_jwt" + "evening_detective_server/internal/services/task_service" + proto "evening_detective_server/proto" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func TestTaskEndpointsRejectUnauthorizedRoles(t *testing.T) { + s := &server{} + operations := []struct { + name string + call func(context.Context) error + }{ + {"list", func(ctx context.Context) error { _, err := s.GetTasks(ctx, &proto.GetTasksReq{}); return err }}, + {"assignees", func(ctx context.Context) error { + _, err := s.GetTaskAssignees(ctx, &proto.GetTaskAssigneesReq{}) + return err + }}, + {"create", func(ctx context.Context) error { _, err := s.CreateTask(ctx, &proto.CreateTaskReq{}); return err }}, + {"update", func(ctx context.Context) error { _, err := s.UpdateTask(ctx, &proto.UpdateTaskReq{}); return err }}, + {"status", func(ctx context.Context) error { _, err := s.SetTaskStatus(ctx, &proto.SetTaskStatusReq{}); return err }}, + {"delete", func(ctx context.Context) error { _, err := s.DeleteTask(ctx, &proto.DeleteTaskReq{}); return err }}, + } + for _, operation := range operations { + for _, role := range []string{"", "user", "author", "organizer"} { + t.Run(operation.name+"/"+role, func(t *testing.T) { + ctx := context.Background() + want := codes.Unauthenticated + if role != "" { + ctx = processor_jwt.ContextWithClaims(ctx, &processor_jwt.JWTClaims{UserID: 1, Roles: []string{role}}) + want = codes.PermissionDenied + } + if err := operation.call(ctx); status.Code(err) != want { + t.Fatalf("error=%v want=%v", err, want) + } + }) + } + } +} + +func TestTaskActorAllowsDeveloperAndAdmin(t *testing.T) { + for _, role := range []string{"developer", "admin"} { + t.Run(role, func(t *testing.T) { + ctx := processor_jwt.ContextWithClaims(context.Background(), &processor_jwt.JWTClaims{UserID: 42, Roles: []string{role}}) + id, err := taskActor(ctx) + if id != 42 || err != nil { + t.Fatalf("id=%d error=%v", id, err) + } + }) + } +} + +func TestTaskErrorsUseSafeTransportCodes(t *testing.T) { + for _, tc := range []struct { + err error + code codes.Code + }{ + {task_service.ErrInvalidTask, codes.InvalidArgument}, + {task_service.ErrInvalidAssignee, codes.InvalidArgument}, + {task_service.ErrNotFound, codes.NotFound}, + {task_service.ErrConflict, codes.Aborted}, + {errors.New("database-password-secret"), codes.Internal}, + } { + t.Run(tc.err.Error(), func(t *testing.T) { + err := taskErrorStatus(fmt.Errorf("database-password-secret: %w", tc.err)) + if status.Code(err) != tc.code || strings.Contains(err.Error(), "database-password-secret") { + t.Fatalf("unsafe or incorrect error=%v", err) + } + }) + } +} + +func TestTaskMappingPreservesOptionalFields(t *testing.T) { + id := 4 + date := time.Date(2026, 10, 7, 0, 0, 0, 0, time.UTC) + for _, tc := range []struct { + name string + assignee *int + date *time.Time + wantDate string + }{ + {"unset", nil, nil, ""}, {"set", &id, &date, "2026-10-07"}, + } { + t.Run(tc.name, func(t *testing.T) { + task := mapTask(&task_service.Task{ID: 1, AssigneeID: tc.assignee, DueDate: tc.date, CreatedAt: date, UpdatedAt: date, Version: 2}) + if task.DueDate != tc.wantDate || (task.AssigneeID == nil) != (tc.assignee == nil) || task.Version != 2 { + t.Fatalf("task=%+v", task) + } + input, err := taskInput("Task", "", "new", task.AssigneeID, task.DueDate) + if err != nil || (input.AssigneeID == nil) != (tc.assignee == nil) { + t.Fatalf("input=%+v error=%v", input, err) + } + }) + } +} diff --git a/internal/modules/roles/interface.go b/internal/modules/roles/interface.go index 1fdb73c..36bfc14 100644 --- a/internal/modules/roles/interface.go +++ b/internal/modules/roles/interface.go @@ -3,6 +3,7 @@ package roles const ( Admin = "admin" + Developer = "developer" Author = "author" Organizer = "organizer" User = "user" @@ -10,6 +11,7 @@ const ( var AllRoles = []string{ Admin, + Developer, Author, Organizer, User, diff --git a/internal/repos/tasks_repo/repo.go b/internal/repos/tasks_repo/repo.go new file mode 100644 index 0000000..1725d67 --- /dev/null +++ b/internal/repos/tasks_repo/repo.go @@ -0,0 +1,256 @@ +// Package tasks_repo persists developer tasks. +package tasks_repo + +import ( + "context" + "errors" + "time" + + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgconn" + "github.com/jackc/pgx/v5/pgxpool" +) + +var ( + ErrInvalidTask = errors.New("некорректные поля задачи") + ErrNotFound = errors.New("задача не найдена") + ErrConflict = errors.New("задача изменена другим пользователем; обновите данные") + ErrInvalidAssignee = errors.New("ответственный должен иметь роль разработчика") +) + +// Task is a persisted developer task. +type Task struct { + ID int + Title string + Description string + Status string + AssigneeID *int + AssigneeName string + AuthorID *int + DueDate *time.Time + CreatedAt time.Time + UpdatedAt time.Time + Version int +} + +// Assignee contains only the public identity needed for task assignment. +type Assignee struct { + ID int + Name string +} + +// TasksRepo persists the shared task board. +type TasksRepo struct{ pool *pgxpool.Pool } + +func NewTasksRepo(pool *pgxpool.Pool) *TasksRepo { return &TasksRepo{pool: pool} } + +const taskColumns = ` + id, + title, + description, + status, + assignee_id, + author_id, + due_date, + created_at, + updated_at, + version, + COALESCE(( + SELECT username + FROM users + WHERE users.id = developer_tasks.assignee_id + ), '')` + +func scanTask(row pgx.Row) (*Task, error) { + var task Task + err := row.Scan(&task.ID, &task.Title, &task.Description, &task.Status, + &task.AssigneeID, &task.AuthorID, &task.DueDate, &task.CreatedAt, &task.UpdatedAt, &task.Version, &task.AssigneeName) + if errors.Is(err, pgx.ErrNoRows) { + return nil, ErrNotFound + } + return &task, err +} + +func (r *TasksRepo) Get(ctx context.Context, id int) (*Task, error) { + return scanTask(r.pool.QueryRow( + ctx, + `SELECT `+taskColumns+` + FROM developer_tasks + WHERE id = $1`, + id, + )) +} + +func (r *TasksRepo) List(ctx context.Context) ([]*Task, error) { + rows, err := r.pool.Query( + ctx, + `SELECT + t.id, + t.title, + t.description, + t.status, + t.assignee_id, + t.author_id, + t.due_date, + t.created_at, + t.updated_at, + t.version, + COALESCE(u.username, '') + FROM developer_tasks t + LEFT JOIN users u ON u.id = t.assignee_id + ORDER BY t.created_at DESC, t.id DESC`, + ) + if err != nil { + return nil, err + } + defer rows.Close() + tasks := make([]*Task, 0) + for rows.Next() { + var task Task + if err := rows.Scan(&task.ID, &task.Title, &task.Description, &task.Status, + &task.AssigneeID, &task.AuthorID, &task.DueDate, &task.CreatedAt, + &task.UpdatedAt, &task.Version, &task.AssigneeName); err != nil { + return nil, err + } + tasks = append(tasks, &task) + } + return tasks, rows.Err() +} + +func (r *TasksRepo) ListAssignees(ctx context.Context) ([]Assignee, error) { + rows, err := r.pool.Query( + ctx, + `SELECT + id, + username + FROM users + WHERE roles @> '["developer"]'::jsonb + ORDER BY username, id`, + ) + if err != nil { + return nil, err + } + defer rows.Close() + result := make([]Assignee, 0) + for rows.Next() { + var user Assignee + if err := rows.Scan(&user.ID, &user.Name); err != nil { + return nil, err + } + result = append(result, user) + } + return result, rows.Err() +} + +func (r *TasksRepo) Create(ctx context.Context, task Task) (*Task, error) { + result, err := scanTask(r.pool.QueryRow( + ctx, + `INSERT INTO developer_tasks (title, description, status, assignee_id, author_id, due_date) + SELECT $1, $2, $3, $4::integer, $5::integer, $6::date + WHERE $4::integer IS NULL OR EXISTS ( + SELECT 1 + FROM users + WHERE id = $4 AND roles @> '["developer"]'::jsonb + ) + RETURNING `+taskColumns, + task.Title, + task.Description, + task.Status, + task.AssigneeID, + task.AuthorID, + task.DueDate, + )) + if errors.Is(err, ErrNotFound) { + return nil, ErrInvalidAssignee + } + return result, writeError(err) +} + +func (r *TasksRepo) Update(ctx context.Context, task Task) (*Task, error) { + result, err := scanTask(r.pool.QueryRow( + ctx, + `UPDATE developer_tasks + SET title = $1, description = $2, status = $3, + assignee_id = $4, due_date = $5, updated_at = NOW(), version = version + 1 + WHERE id = $6 AND version = $7 AND ( + $4::integer IS NULL OR assignee_id = $4 OR EXISTS ( + SELECT 1 + FROM users + WHERE id = $4 AND roles @> '["developer"]'::jsonb + ) + ) + RETURNING `+taskColumns, + task.Title, + task.Description, + task.Status, + task.AssigneeID, + task.DueDate, + task.ID, + task.Version, + )) + if errors.Is(err, ErrNotFound) { + current, getErr := r.Get(ctx, task.ID) + if getErr != nil { + return nil, getErr + } + if current.Version != task.Version { + return nil, ErrConflict + } + return nil, ErrInvalidAssignee + } + return result, writeError(err) +} + +func (r *TasksRepo) SetStatus(ctx context.Context, id, version int, status string) (*Task, error) { + result, err := scanTask(r.pool.QueryRow( + ctx, + `UPDATE developer_tasks + SET status = $1, updated_at = NOW(), version = version + 1 + WHERE id = $2 AND version = $3 + RETURNING `+taskColumns, + status, + id, + version, + )) + if errors.Is(err, ErrNotFound) { + return nil, r.missingWrite(ctx, id) + } + return result, err +} + +func (r *TasksRepo) Delete(ctx context.Context, id, version int) error { + tag, err := r.pool.Exec( + ctx, + `DELETE FROM developer_tasks + WHERE id = $1 AND version = $2`, + id, + version, + ) + if err != nil { + return err + } + if tag.RowsAffected() == 0 { + return r.missingWrite(ctx, id) + } + return nil +} + +func (r *TasksRepo) missingWrite(ctx context.Context, id int) error { + if _, err := r.Get(ctx, id); err != nil { + return err + } + return ErrConflict +} + +func writeError(err error) error { + var pgErr *pgconn.PgError + if errors.As(err, &pgErr) { + switch pgErr.Code { + case "23503": + return ErrInvalidAssignee + case "23514", "22001": + return ErrInvalidTask + } + } + return err +} diff --git a/internal/repos/tasks_repo/repo_test.go b/internal/repos/tasks_repo/repo_test.go new file mode 100644 index 0000000..5ed3035 --- /dev/null +++ b/internal/repos/tasks_repo/repo_test.go @@ -0,0 +1,279 @@ +package tasks_repo_test + +import ( + "context" + "errors" + "fmt" + "os" + "strings" + "testing" + "time" + + "evening_detective_server/internal/repos/tasks_repo" + "evening_detective_server/internal/repos/user_agreements_repo" + "evening_detective_server/internal/repos/users_repo" + + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgxpool" +) + +type taskFixture struct { + repo *tasks_repo.TasksRepo + users *users_repo.UsersRepo + developerID int + otherID int + pool *pgxpool.Pool +} + +// newTaskFixture prepares an isolated schema using the application's migrations. +// Scenarios below create and inspect data only through public repository methods. +func newTaskFixture(t *testing.T) taskFixture { + t.Helper() + dsn := os.Getenv("TEST_DATABASE_URL") + if dsn == "" { + t.Skip("set TEST_DATABASE_URL to run PostgreSQL integration checks") + } + ctx := context.Background() + admin, err := pgxpool.New(ctx, dsn) + if err != nil { + t.Fatal(err) + } + schema := fmt.Sprintf("tasks_test_%d", time.Now().UnixNano()) + quoted := pgx.Identifier{schema}.Sanitize() + if _, err := admin.Exec(ctx, "CREATE SCHEMA "+quoted); err != nil { + admin.Close() + t.Fatal(err) + } + t.Cleanup(func() { + if _, err := admin.Exec(ctx, "DROP SCHEMA "+quoted+" CASCADE"); err != nil { + t.Error(err) + } + admin.Close() + }) + config, err := pgxpool.ParseConfig(dsn) + if err != nil { + t.Fatal(err) + } + config.ConnConfig.RuntimeParams["search_path"] = schema + pool, err := pgxpool.NewWithConfig(ctx, config) + if err != nil { + t.Fatal(err) + } + t.Cleanup(pool.Close) + for _, migration := range []string{ + "20260628175120_create_users_table.sql", + "20260704192907_refresh_tokens_table.sql", + "20260818231943_create_user_agreements_table.sql", + "20261007130000_create_developer_tasks.sql", + } { + applyTaskMigration(t, pool, migration, false) + } + users := users_repo.NewUserRepo(pool) + agreements := []user_agreements_repo.Agreement{{AgreementType: "terms", Version: "test"}} + developerID, err := users.AddUserWithAgreements(ctx, "developer", "dev@test.invalid", "test-hash", []string{"user"}, agreements) + if err != nil { + t.Fatal(err) + } + if err := users.AddUserRole(ctx, developerID, "developer"); err != nil { + t.Fatal(err) + } + otherID, err := users.AddUserWithAgreements(ctx, "other", "other@test.invalid", "test-hash", []string{"user"}, agreements) + if err != nil { + t.Fatal(err) + } + return taskFixture{repo: tasks_repo.NewTasksRepo(pool), users: users, developerID: developerID, otherID: otherID, pool: pool} +} + +// applyTaskMigration is schema infrastructure, not a task data access path. +func applyTaskMigration(t *testing.T, pool *pgxpool.Pool, name string, down bool) { + t.Helper() + data, err := os.ReadFile("../../../migrations/" + name) + if err != nil { + t.Fatal(err) + } + parts := strings.Split(string(data), "-- +goose Down") + sql := parts[0] + if down { + sql = parts[1] + } + if _, err := pool.Exec(context.Background(), sql); err != nil { + t.Fatal(err) + } +} + +func (f taskFixture) create(t *testing.T) *tasks_repo.Task { + t.Helper() + date := time.Date(2026, 10, 7, 0, 0, 0, 0, time.UTC) + task, err := f.repo.Create(context.Background(), tasks_repo.Task{ + Title: "Task", + Description: "Original", + Status: "new", + AssigneeID: &f.developerID, + AuthorID: &f.developerID, + DueDate: &date, + }) + if err != nil { + t.Fatal(err) + } + return task +} + +func TestTaskPersistencePostgres(t *testing.T) { + tests := []struct { + name string + run func(*testing.T, taskFixture) + }{ + {"fields and clearing", func(t *testing.T, f taskFixture) { + task := f.create(t) + if task.Version != 1 || task.AssigneeName != "developer" || task.DueDate.Format("2006-01-02") != "2026-10-07" { + t.Fatalf("created task=%+v", task) + } + task.Title, task.Description, task.Status = "Updated", "", "done" + task.AssigneeID, task.DueDate = nil, nil + updated, err := f.repo.Update(context.Background(), *task) + if err != nil { + t.Fatal(err) + } + if updated.Version != 2 || updated.AssigneeID != nil || updated.DueDate != nil || updated.AssigneeName != "" || updated.AuthorID == nil { + t.Fatalf("updated task=%+v", updated) + } + list, err := f.repo.List(context.Background()) + if err != nil || len(list) != 1 || list[0].Title != "Updated" { + t.Fatalf("list=%v error=%v", list, err) + } + }}, + {"assignment requires developer", func(t *testing.T, f taskFixture) { + candidates, err := f.repo.ListAssignees(context.Background()) + if err != nil || len(candidates) != 1 || candidates[0].ID != f.developerID { + t.Fatalf("assignees=%v error=%v", candidates, err) + } + _, err = f.repo.Create(context.Background(), tasks_repo.Task{Title: "Invalid", Status: "new", AssigneeID: &f.otherID}) + if !errors.Is(err, tasks_repo.ErrInvalidAssignee) { + t.Fatalf("error=%v", err) + } + task := f.create(t) + task.AssigneeID = &f.otherID + _, err = f.repo.Update(context.Background(), *task) + if !errors.Is(err, tasks_repo.ErrInvalidAssignee) { + t.Fatalf("error=%v", err) + } + }}, + {"revoked role preserves current assignment", func(t *testing.T, f taskFixture) { + task := f.create(t) + if err := f.users.DeleteUserRole(context.Background(), f.developerID, "developer"); err != nil { + t.Fatal(err) + } + task.Title = "Retained assignment" + updated, err := f.repo.Update(context.Background(), *task) + if err != nil || updated.AssigneeID == nil || *updated.AssigneeID != f.developerID { + t.Fatalf("updated=%v error=%v", updated, err) + } + candidates, err := f.repo.ListAssignees(context.Background()) + if err != nil || len(candidates) != 0 { + t.Fatalf("assignees=%v error=%v", candidates, err) + } + _, err = f.repo.Create(context.Background(), tasks_repo.Task{Title: "New assignment", Status: "new", AssigneeID: &f.developerID}) + if !errors.Is(err, tasks_repo.ErrInvalidAssignee) { + t.Fatalf("error=%v", err) + } + }}, + {"status writes protect other fields", func(t *testing.T, f taskFixture) { + task := f.create(t) + for _, state := range []string{"in_progress", "review", "done", "new"} { + updated, err := f.repo.SetStatus(context.Background(), task.ID, task.Version, state) + if err != nil { + t.Fatal(err) + } + if updated.Status != state || updated.Title != task.Title || updated.Description != task.Description || + updated.Version != task.Version+1 || updated.AssigneeID == nil || updated.DueDate == nil { + t.Fatalf("updated=%+v", updated) + } + task = updated + } + }}, + {"concurrent writes and stale deletion", func(t *testing.T, f taskFixture) { + task := f.create(t) + results := make(chan error, 4) + for range 4 { + go func() { + _, err := f.repo.SetStatus(context.Background(), task.ID, task.Version, "review") + results <- err + }() + } + successes := 0 + for range 4 { + err := <-results + if err == nil { + successes++ + } else if !errors.Is(err, tasks_repo.ErrConflict) { + t.Fatal(err) + } + } + if successes != 1 { + t.Fatalf("successes=%d", successes) + } + if err := f.repo.Delete(context.Background(), task.ID, task.Version); !errors.Is(err, tasks_repo.ErrConflict) { + t.Fatalf("error=%v", err) + } + _, err := f.repo.Update(context.Background(), *task) + if !errors.Is(err, tasks_repo.ErrConflict) { + t.Fatalf("error=%v", err) + } + current, err := f.repo.Get(context.Background(), task.ID) + if err != nil { + t.Fatal(err) + } + if err := f.repo.Delete(context.Background(), current.ID, current.Version); err != nil { + t.Fatal(err) + } + if _, err := f.repo.Get(context.Background(), task.ID); !errors.Is(err, tasks_repo.ErrNotFound) { + t.Fatalf("error=%v", err) + } + if err := f.repo.Delete(context.Background(), task.ID, current.Version); !errors.Is(err, tasks_repo.ErrNotFound) { + t.Fatalf("error=%v", err) + } + if _, err := f.repo.Update(context.Background(), *task); !errors.Is(err, tasks_repo.ErrNotFound) { + t.Fatalf("error=%v", err) + } + if _, err := f.repo.SetStatus(context.Background(), task.ID, current.Version, "new"); !errors.Is(err, tasks_repo.ErrNotFound) { + t.Fatalf("error=%v", err) + } + }}, + {"user deletion retains tasks", func(t *testing.T, f taskFixture) { + task := f.create(t) + if err := f.users.DeleteUser(context.Background(), f.developerID); err != nil { + t.Fatal(err) + } + current, err := f.repo.Get(context.Background(), task.ID) + if err != nil || current.AssigneeID != nil || current.AuthorID != nil || current.Title != task.Title { + t.Fatalf("task=%v error=%v", current, err) + } + }}, + {"database constraints", func(t *testing.T, f taskFixture) { + for _, task := range []tasks_repo.Task{ + {Title: " ", Status: "new"}, {Title: strings.Repeat("Я", 256), Status: "new"}, + {Title: "Task", Status: "invalid"}, {Title: "Task", Status: "new", Description: strings.Repeat("Я", 10001)}, + } { + if _, err := f.repo.Create(context.Background(), task); !errors.Is(err, tasks_repo.ErrInvalidTask) { + t.Fatalf("error=%v", err) + } + } + }}, + {"migration rollback and reapply", func(t *testing.T, f taskFixture) { + f.create(t) + const migration = "20261007130000_create_developer_tasks.sql" + applyTaskMigration(t, f.pool, migration, true) + if _, err := f.repo.List(context.Background()); err == nil { + t.Fatal("table still exists after Down") + } + applyTaskMigration(t, f.pool, migration, false) + tasks, err := f.repo.List(context.Background()) + if err != nil || len(tasks) != 0 { + t.Fatalf("tasks=%v error=%v", tasks, err) + } + }}, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { tc.run(t, newTaskFixture(t)) }) + } +} diff --git a/internal/services/task_service/service.go b/internal/services/task_service/service.go new file mode 100644 index 0000000..fcb0a05 --- /dev/null +++ b/internal/services/task_service/service.go @@ -0,0 +1,100 @@ +// Package task_service implements the shared developer board. +package task_service + +import ( + "context" + "strings" + "time" + "unicode/utf8" + + "evening_detective_server/internal/repos/tasks_repo" +) + +var ( + ErrInvalidTask = tasks_repo.ErrInvalidTask + ErrNotFound = tasks_repo.ErrNotFound + ErrConflict = tasks_repo.ErrConflict + ErrInvalidAssignee = tasks_repo.ErrInvalidAssignee +) + +type Task = tasks_repo.Task +type Assignee = tasks_repo.Assignee + +type ITasksRepo interface { + List(context.Context) ([]*Task, error) + ListAssignees(context.Context) ([]Assignee, error) + Create(context.Context, Task) (*Task, error) + Update(context.Context, Task) (*Task, error) + SetStatus(context.Context, int, int, string) (*Task, error) + Delete(context.Context, int, int) error +} + +type TaskService struct{ repo ITasksRepo } + +func NewTaskService(repo ITasksRepo) *TaskService { return &TaskService{repo: repo} } + +func (s *TaskService) List(ctx context.Context) ([]*Task, error) { return s.repo.List(ctx) } +func (s *TaskService) ListAssignees(ctx context.Context) ([]Assignee, error) { + return s.repo.ListAssignees(ctx) +} + +// ParseDueDate preserves calendar dates without a local time zone conversion. +func ParseDueDate(value string) (*time.Time, error) { + if value == "" { + return nil, nil + } + date, err := time.Parse("2006-01-02", value) + if err != nil || date.Year() < 1 { + return nil, ErrInvalidTask + } + return &date, nil +} + +func validStatus(status string) bool { + return status == "new" || status == "in_progress" || status == "review" || status == "done" +} + +func validate(task *Task) error { + task.Title = strings.TrimSpace(task.Title) + if task.Title == "" || strings.ContainsRune(task.Title, 0) || strings.ContainsRune(task.Description, 0) || + utf8.RuneCountInString(task.Title) > 255 || + utf8.RuneCountInString(task.Description) > 10000 || !validStatus(task.Status) || + (task.AssigneeID != nil && *task.AssigneeID <= 0) { + return ErrInvalidTask + } + return nil +} + +func (s *TaskService) Create(ctx context.Context, task Task) (*Task, error) { + if task.Status == "" { + task.Status = "new" + } + if err := validate(&task); err != nil { + return nil, err + } + return s.repo.Create(ctx, task) +} + +func (s *TaskService) Update(ctx context.Context, task Task) (*Task, error) { + if task.ID <= 0 || task.Version <= 0 { + return nil, ErrInvalidTask + } + if err := validate(&task); err != nil { + return nil, err + } + return s.repo.Update(ctx, task) +} + +func (s *TaskService) SetStatus(ctx context.Context, id, version int, status string) (*Task, error) { + if id <= 0 || version <= 0 || !validStatus(status) { + return nil, ErrInvalidTask + } + return s.repo.SetStatus(ctx, id, version, status) +} + +func (s *TaskService) Delete(ctx context.Context, id, version int) error { + if id <= 0 || version <= 0 { + return ErrInvalidTask + } + return s.repo.Delete(ctx, id, version) +} diff --git a/internal/services/task_service/service_test.go b/internal/services/task_service/service_test.go new file mode 100644 index 0000000..99ae9ef --- /dev/null +++ b/internal/services/task_service/service_test.go @@ -0,0 +1,133 @@ +package task_service + +import ( + "context" + "errors" + "strings" + "testing" +) + +type fakeTasks struct { + task Task + err error + calls int +} + +func (f *fakeTasks) List(context.Context) ([]*Task, error) { return []*Task{&f.task}, f.err } +func (f *fakeTasks) ListAssignees(context.Context) ([]Assignee, error) { return nil, f.err } +func (f *fakeTasks) Create(_ context.Context, task Task) (*Task, error) { + f.calls++ + f.task = task + return &f.task, f.err +} +func (f *fakeTasks) Update(ctx context.Context, task Task) (*Task, error) { return f.Create(ctx, task) } +func (f *fakeTasks) SetStatus(_ context.Context, id, version int, status string) (*Task, error) { + f.calls++ + f.task.ID, f.task.Version, f.task.Status = id, version, status + return &f.task, f.err +} +func (f *fakeTasks) Delete(context.Context, int, int) error { f.calls++; return f.err } + +func TestTaskValidationAndErrors(t *testing.T) { + zero := 0 + tests := []struct { + name string + task Task + repoErr error + wantErr error + wantCalls int + }{ + {name: "default status and trimmed title", task: Task{Title: " Задача "}, wantCalls: 1}, + {name: "unicode limit", task: Task{Title: strings.Repeat("Я", 255)}, wantCalls: 1}, + {name: "NUL in title", task: Task{Title: "Task\x00"}, wantErr: ErrInvalidTask}, + {name: "NUL in description", task: Task{Title: "Task", Description: "\x00"}, wantErr: ErrInvalidTask}, + {name: "blank title", task: Task{Title: " "}, wantErr: ErrInvalidTask}, + {name: "long title", task: Task{Title: strings.Repeat("Я", 256)}, wantErr: ErrInvalidTask}, + {name: "long description", task: Task{Title: "Task", Description: strings.Repeat("Я", 10001)}, wantErr: ErrInvalidTask}, + {name: "unknown status", task: Task{Title: "Task", Status: "cancelled"}, wantErr: ErrInvalidTask}, + {name: "invalid assignee ID", task: Task{Title: "Task", AssigneeID: &zero}, wantErr: ErrInvalidTask}, + {name: "ineligible assignee", task: Task{Title: "Task"}, repoErr: ErrInvalidAssignee, wantErr: ErrInvalidAssignee, wantCalls: 1}, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + repo := &fakeTasks{err: tc.repoErr} + _, err := NewTaskService(repo).Create(context.Background(), tc.task) + if !errors.Is(err, tc.wantErr) || repo.calls != tc.wantCalls { + t.Fatalf("error=%v calls=%d", err, repo.calls) + } + if err == nil && (repo.task.Title != strings.TrimSpace(tc.task.Title) || repo.task.Status != "new") { + t.Fatalf("saved task=%+v", repo.task) + } + }) + } +} + +func TestWritesValidateVersionAndPropagateErrors(t *testing.T) { + for _, operation := range []string{"update", "status", "delete"} { + for _, tc := range []struct { + name string + id, version int + repoErr, wantErr error + }{ + {"valid", 1, 1, nil, nil}, + {"invalid ID", 0, 1, nil, ErrInvalidTask}, + {"invalid version", 1, 0, nil, ErrInvalidTask}, + {"conflict", 1, 1, ErrConflict, ErrConflict}, + {"missing", 1, 1, ErrNotFound, ErrNotFound}, + } { + t.Run(operation+"/"+tc.name, func(t *testing.T) { + repo := &fakeTasks{err: tc.repoErr} + service := NewTaskService(repo) + var err error + switch operation { + case "update": + _, err = service.Update(context.Background(), Task{ID: tc.id, Version: tc.version, Title: "Task", Status: "new"}) + case "status": + _, err = service.SetStatus(context.Background(), tc.id, tc.version, "review") + case "delete": + err = service.Delete(context.Background(), tc.id, tc.version) + } + if !errors.Is(err, tc.wantErr) { + t.Fatalf("error=%v want=%v", err, tc.wantErr) + } + }) + } + } +} + +func TestStatusTransitionsAllowAllFourStates(t *testing.T) { + for _, status := range []string{"new", "in_progress", "review", "done", "unknown"} { + t.Run(status, func(t *testing.T) { + repo := &fakeTasks{} + _, err := NewTaskService(repo).SetStatus(context.Background(), 1, 1, status) + if status == "unknown" { + if !errors.Is(err, ErrInvalidTask) || repo.calls != 0 { + t.Fatalf("error=%v calls=%d", err, repo.calls) + } + } else if err != nil || repo.task.Status != status { + t.Fatalf("error=%v task=%+v", err, repo.task) + } + }) + } +} + +func TestDueDatesRemainCalendarDates(t *testing.T) { + for _, tc := range []struct { + value string + valid bool + }{ + {"", true}, {"2026-10-07", true}, {"2024-02-29", true}, {"2026-02-29", false}, + {"2026-10-07T00:00:00Z", false}, {"2026-1-2", false}, {"0000-01-01", false}, + } { + t.Run(tc.value, func(t *testing.T) { + date, err := ParseDueDate(tc.value) + if tc.valid { + if err != nil || (tc.value != "" && date.Format("2006-01-02") != tc.value) || (tc.value == "" && date != nil) { + t.Fatalf("date=%v err=%v", date, err) + } + } else if !errors.Is(err, ErrInvalidTask) { + t.Fatalf("error=%v", err) + } + }) + } +} diff --git a/internal/services/ui_service/service.go b/internal/services/ui_service/service.go index 9bafee9..5f8e396 100644 --- a/internal/services/ui_service/service.go +++ b/internal/services/ui_service/service.go @@ -12,6 +12,9 @@ var ( "users_page", "reviews_page", }, + rolesModule.Developer: { + "tasks_page", + }, rolesModule.Author: { "scenarios_page", "scenario_editor_page", diff --git a/internal/services/ui_service/service_test.go b/internal/services/ui_service/service_test.go new file mode 100644 index 0000000..d1dd022 --- /dev/null +++ b/internal/services/ui_service/service_test.go @@ -0,0 +1,25 @@ +package ui_service + +import ( + "slices" + "testing" +) + +func TestTasksPermission(t *testing.T) { + for _, tc := range []struct { + role string + allowed bool + }{ + {"developer", true}, {"admin", true}, {"user", false}, {"author", false}, {"organizer", false}, + } { + t.Run(tc.role, func(t *testing.T) { + got := NewUIService().GetPermissions([]string{tc.role}) + if slices.Contains(got, "tasks_page") != tc.allowed { + t.Fatalf("permissions=%v", got) + } + if tc.role == "developer" && slices.Contains(got, "users_page") { + t.Fatal("developer has administrative permission") + } + }) + } +} diff --git a/internal/services/users_service/developer_role_test.go b/internal/services/users_service/developer_role_test.go new file mode 100644 index 0000000..d29b321 --- /dev/null +++ b/internal/services/users_service/developer_role_test.go @@ -0,0 +1,25 @@ +package users_service + +import ( + "context" + "errors" + "testing" +) + +func TestDeveloperRoleCanBeAssignedAndRemoved(t *testing.T) { + for _, tc := range []struct { + role string + wantErr error + }{ + {"developer", nil}, {"invalid", ErrInvalidRole}, + } { + t.Run(tc.role, func(t *testing.T) { + service := NewUsersService(&fakeRepo{}, nil, nil, nil, nil, "") + for _, change := range []func(context.Context, int, string) error{service.AddUserRole, service.DeleteUserRole} { + if err := change(context.Background(), 1, tc.role); !errors.Is(err, tc.wantErr) { + t.Fatalf("error=%v", err) + } + } + }) + } +} diff --git a/migrations/20261007130000_create_developer_tasks.sql b/migrations/20261007130000_create_developer_tasks.sql new file mode 100644 index 0000000..15a341d --- /dev/null +++ b/migrations/20261007130000_create_developer_tasks.sql @@ -0,0 +1,16 @@ +-- +goose Up +CREATE TABLE developer_tasks ( + id SERIAL PRIMARY KEY, + title VARCHAR(255) NOT NULL CHECK (char_length(btrim(title)) > 0), + description TEXT NOT NULL DEFAULT '' CHECK (char_length(description) <= 10000), + status TEXT NOT NULL DEFAULT 'new' CHECK (status IN ('new', 'in_progress', 'review', 'done')), + assignee_id INTEGER REFERENCES users(id) ON DELETE SET NULL, + author_id INTEGER REFERENCES users(id) ON DELETE SET NULL, + due_date DATE, + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + version INTEGER NOT NULL DEFAULT 1 CHECK (version > 0) +); + +-- +goose Down +DROP TABLE developer_tasks; diff --git a/proto/main.pb.go b/proto/main.pb.go index e3d6e92..9d8e5d7 100644 --- a/proto/main.pb.go +++ b/proto/main.pb.go @@ -11063,6 +11063,706 @@ func (x *TicketPage) GetUsedBy() string { return "" } +// Developer tasks use new, in_progress, review and done statuses. +type DeveloperTask struct { + state protoimpl.MessageState `protogen:"open.v1"` + ID int32 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"` + Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"` + Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` + Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` + // Omitted assignee means the task is unassigned. + AssigneeID *int32 `protobuf:"varint,5,opt,name=assigneeID,proto3,oneof" json:"assigneeID,omitempty"` + AssigneeName string `protobuf:"bytes,6,opt,name=assigneeName,proto3" json:"assigneeName,omitempty"` + AuthorID *int32 `protobuf:"varint,7,opt,name=authorID,proto3,oneof" json:"authorID,omitempty"` + // Calendar deadline in YYYY-MM-DD format; empty means no deadline. + DueDate string `protobuf:"bytes,8,opt,name=dueDate,proto3" json:"dueDate,omitempty"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,9,opt,name=createdAt,proto3" json:"createdAt,omitempty"` + UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,10,opt,name=updatedAt,proto3" json:"updatedAt,omitempty"` + // Required for updates and deletion to detect concurrent edits. + Version int32 `protobuf:"varint,11,opt,name=version,proto3" json:"version,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeveloperTask) Reset() { + *x = DeveloperTask{} + mi := &file_main_proto_msgTypes[212] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeveloperTask) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeveloperTask) ProtoMessage() {} + +func (x *DeveloperTask) ProtoReflect() protoreflect.Message { + mi := &file_main_proto_msgTypes[212] + 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 DeveloperTask.ProtoReflect.Descriptor instead. +func (*DeveloperTask) Descriptor() ([]byte, []int) { + return file_main_proto_rawDescGZIP(), []int{212} +} + +func (x *DeveloperTask) GetID() int32 { + if x != nil { + return x.ID + } + return 0 +} + +func (x *DeveloperTask) GetTitle() string { + if x != nil { + return x.Title + } + return "" +} + +func (x *DeveloperTask) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *DeveloperTask) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *DeveloperTask) GetAssigneeID() int32 { + if x != nil && x.AssigneeID != nil { + return *x.AssigneeID + } + return 0 +} + +func (x *DeveloperTask) GetAssigneeName() string { + if x != nil { + return x.AssigneeName + } + return "" +} + +func (x *DeveloperTask) GetAuthorID() int32 { + if x != nil && x.AuthorID != nil { + return *x.AuthorID + } + return 0 +} + +func (x *DeveloperTask) GetDueDate() string { + if x != nil { + return x.DueDate + } + return "" +} + +func (x *DeveloperTask) GetCreatedAt() *timestamppb.Timestamp { + if x != nil { + return x.CreatedAt + } + return nil +} + +func (x *DeveloperTask) GetUpdatedAt() *timestamppb.Timestamp { + if x != nil { + return x.UpdatedAt + } + return nil +} + +func (x *DeveloperTask) GetVersion() int32 { + if x != nil { + return x.Version + } + return 0 +} + +type TaskAssignee struct { + state protoimpl.MessageState `protogen:"open.v1"` + ID int32 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TaskAssignee) Reset() { + *x = TaskAssignee{} + mi := &file_main_proto_msgTypes[213] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TaskAssignee) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TaskAssignee) ProtoMessage() {} + +func (x *TaskAssignee) ProtoReflect() protoreflect.Message { + mi := &file_main_proto_msgTypes[213] + 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 TaskAssignee.ProtoReflect.Descriptor instead. +func (*TaskAssignee) Descriptor() ([]byte, []int) { + return file_main_proto_rawDescGZIP(), []int{213} +} + +func (x *TaskAssignee) GetID() int32 { + if x != nil { + return x.ID + } + return 0 +} + +func (x *TaskAssignee) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +type GetTasksReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetTasksReq) Reset() { + *x = GetTasksReq{} + mi := &file_main_proto_msgTypes[214] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetTasksReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTasksReq) ProtoMessage() {} + +func (x *GetTasksReq) ProtoReflect() protoreflect.Message { + mi := &file_main_proto_msgTypes[214] + 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 GetTasksReq.ProtoReflect.Descriptor instead. +func (*GetTasksReq) Descriptor() ([]byte, []int) { + return file_main_proto_rawDescGZIP(), []int{214} +} + +type GetTasksRsp struct { + state protoimpl.MessageState `protogen:"open.v1"` + Tasks []*DeveloperTask `protobuf:"bytes,1,rep,name=tasks,proto3" json:"tasks,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetTasksRsp) Reset() { + *x = GetTasksRsp{} + mi := &file_main_proto_msgTypes[215] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetTasksRsp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTasksRsp) ProtoMessage() {} + +func (x *GetTasksRsp) ProtoReflect() protoreflect.Message { + mi := &file_main_proto_msgTypes[215] + 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 GetTasksRsp.ProtoReflect.Descriptor instead. +func (*GetTasksRsp) Descriptor() ([]byte, []int) { + return file_main_proto_rawDescGZIP(), []int{215} +} + +func (x *GetTasksRsp) GetTasks() []*DeveloperTask { + if x != nil { + return x.Tasks + } + return nil +} + +type GetTaskAssigneesReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetTaskAssigneesReq) Reset() { + *x = GetTaskAssigneesReq{} + mi := &file_main_proto_msgTypes[216] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetTaskAssigneesReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTaskAssigneesReq) ProtoMessage() {} + +func (x *GetTaskAssigneesReq) ProtoReflect() protoreflect.Message { + mi := &file_main_proto_msgTypes[216] + 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 GetTaskAssigneesReq.ProtoReflect.Descriptor instead. +func (*GetTaskAssigneesReq) Descriptor() ([]byte, []int) { + return file_main_proto_rawDescGZIP(), []int{216} +} + +type GetTaskAssigneesRsp struct { + state protoimpl.MessageState `protogen:"open.v1"` + Assignees []*TaskAssignee `protobuf:"bytes,1,rep,name=assignees,proto3" json:"assignees,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetTaskAssigneesRsp) Reset() { + *x = GetTaskAssigneesRsp{} + mi := &file_main_proto_msgTypes[217] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetTaskAssigneesRsp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTaskAssigneesRsp) ProtoMessage() {} + +func (x *GetTaskAssigneesRsp) ProtoReflect() protoreflect.Message { + mi := &file_main_proto_msgTypes[217] + 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 GetTaskAssigneesRsp.ProtoReflect.Descriptor instead. +func (*GetTaskAssigneesRsp) Descriptor() ([]byte, []int) { + return file_main_proto_rawDescGZIP(), []int{217} +} + +func (x *GetTaskAssigneesRsp) GetAssignees() []*TaskAssignee { + if x != nil { + return x.Assignees + } + return nil +} + +type CreateTaskReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"` + AssigneeID *int32 `protobuf:"varint,4,opt,name=assigneeID,proto3,oneof" json:"assigneeID,omitempty"` + DueDate string `protobuf:"bytes,5,opt,name=dueDate,proto3" json:"dueDate,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateTaskReq) Reset() { + *x = CreateTaskReq{} + mi := &file_main_proto_msgTypes[218] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateTaskReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateTaskReq) ProtoMessage() {} + +func (x *CreateTaskReq) ProtoReflect() protoreflect.Message { + mi := &file_main_proto_msgTypes[218] + 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 CreateTaskReq.ProtoReflect.Descriptor instead. +func (*CreateTaskReq) Descriptor() ([]byte, []int) { + return file_main_proto_rawDescGZIP(), []int{218} +} + +func (x *CreateTaskReq) GetTitle() string { + if x != nil { + return x.Title + } + return "" +} + +func (x *CreateTaskReq) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *CreateTaskReq) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *CreateTaskReq) GetAssigneeID() int32 { + if x != nil && x.AssigneeID != nil { + return *x.AssigneeID + } + return 0 +} + +func (x *CreateTaskReq) GetDueDate() string { + if x != nil { + return x.DueDate + } + return "" +} + +type UpdateTaskReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + ID int32 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"` + Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"` + Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` + Status string `protobuf:"bytes,4,opt,name=status,proto3" json:"status,omitempty"` + AssigneeID *int32 `protobuf:"varint,5,opt,name=assigneeID,proto3,oneof" json:"assigneeID,omitempty"` + DueDate string `protobuf:"bytes,6,opt,name=dueDate,proto3" json:"dueDate,omitempty"` + Version int32 `protobuf:"varint,7,opt,name=version,proto3" json:"version,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateTaskReq) Reset() { + *x = UpdateTaskReq{} + mi := &file_main_proto_msgTypes[219] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateTaskReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateTaskReq) ProtoMessage() {} + +func (x *UpdateTaskReq) ProtoReflect() protoreflect.Message { + mi := &file_main_proto_msgTypes[219] + 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 UpdateTaskReq.ProtoReflect.Descriptor instead. +func (*UpdateTaskReq) Descriptor() ([]byte, []int) { + return file_main_proto_rawDescGZIP(), []int{219} +} + +func (x *UpdateTaskReq) GetID() int32 { + if x != nil { + return x.ID + } + return 0 +} + +func (x *UpdateTaskReq) GetTitle() string { + if x != nil { + return x.Title + } + return "" +} + +func (x *UpdateTaskReq) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *UpdateTaskReq) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *UpdateTaskReq) GetAssigneeID() int32 { + if x != nil && x.AssigneeID != nil { + return *x.AssigneeID + } + return 0 +} + +func (x *UpdateTaskReq) GetDueDate() string { + if x != nil { + return x.DueDate + } + return "" +} + +func (x *UpdateTaskReq) GetVersion() int32 { + if x != nil { + return x.Version + } + return 0 +} + +type SetTaskStatusReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + ID int32 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"` + Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"` + Version int32 `protobuf:"varint,3,opt,name=version,proto3" json:"version,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SetTaskStatusReq) Reset() { + *x = SetTaskStatusReq{} + mi := &file_main_proto_msgTypes[220] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SetTaskStatusReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SetTaskStatusReq) ProtoMessage() {} + +func (x *SetTaskStatusReq) ProtoReflect() protoreflect.Message { + mi := &file_main_proto_msgTypes[220] + 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 SetTaskStatusReq.ProtoReflect.Descriptor instead. +func (*SetTaskStatusReq) Descriptor() ([]byte, []int) { + return file_main_proto_rawDescGZIP(), []int{220} +} + +func (x *SetTaskStatusReq) GetID() int32 { + if x != nil { + return x.ID + } + return 0 +} + +func (x *SetTaskStatusReq) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *SetTaskStatusReq) GetVersion() int32 { + if x != nil { + return x.Version + } + return 0 +} + +type DeleteTaskReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + ID int32 `protobuf:"varint,1,opt,name=ID,proto3" json:"ID,omitempty"` + Version int32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteTaskReq) Reset() { + *x = DeleteTaskReq{} + mi := &file_main_proto_msgTypes[221] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteTaskReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteTaskReq) ProtoMessage() {} + +func (x *DeleteTaskReq) ProtoReflect() protoreflect.Message { + mi := &file_main_proto_msgTypes[221] + 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 DeleteTaskReq.ProtoReflect.Descriptor instead. +func (*DeleteTaskReq) Descriptor() ([]byte, []int) { + return file_main_proto_rawDescGZIP(), []int{221} +} + +func (x *DeleteTaskReq) GetID() int32 { + if x != nil { + return x.ID + } + return 0 +} + +func (x *DeleteTaskReq) GetVersion() int32 { + if x != nil { + return x.Version + } + return 0 +} + +type TaskRsp struct { + state protoimpl.MessageState `protogen:"open.v1"` + Task *DeveloperTask `protobuf:"bytes,1,opt,name=task,proto3" json:"task,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *TaskRsp) Reset() { + *x = TaskRsp{} + mi := &file_main_proto_msgTypes[222] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *TaskRsp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TaskRsp) ProtoMessage() {} + +func (x *TaskRsp) ProtoReflect() protoreflect.Message { + mi := &file_main_proto_msgTypes[222] + 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 TaskRsp.ProtoReflect.Descriptor instead. +func (*TaskRsp) Descriptor() ([]byte, []int) { + return file_main_proto_rawDescGZIP(), []int{222} +} + +func (x *TaskRsp) GetTask() *DeveloperTask { + if x != nil { + return x.Task + } + return nil +} + +type DeleteTaskRsp struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteTaskRsp) Reset() { + *x = DeleteTaskRsp{} + mi := &file_main_proto_msgTypes[223] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteTaskRsp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteTaskRsp) ProtoMessage() {} + +func (x *DeleteTaskRsp) ProtoReflect() protoreflect.Message { + mi := &file_main_proto_msgTypes[223] + 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 DeleteTaskRsp.ProtoReflect.Descriptor instead. +func (*DeleteTaskRsp) Descriptor() ([]byte, []int) { + return file_main_proto_rawDescGZIP(), []int{223} +} + var File_main_proto protoreflect.FileDescriptor const file_main_proto_rawDesc = "" + @@ -11745,7 +12445,63 @@ const file_main_proto_rawDesc = "" + "\aused_at\x18\a \x01(\v2\x1a.google.protobuf.TimestampH\x00R\x06usedAt\x88\x01\x01\x12\x17\n" + "\aused_by\x18\b \x01(\tR\x06usedByB\n" + "\n" + - "\b_used_at*\xf6\x01\n" + + "\b_used_at\"\x9d\x03\n" + + "\rDeveloperTask\x12\x0e\n" + + "\x02ID\x18\x01 \x01(\x05R\x02ID\x12\x14\n" + + "\x05title\x18\x02 \x01(\tR\x05title\x12 \n" + + "\vdescription\x18\x03 \x01(\tR\vdescription\x12\x16\n" + + "\x06status\x18\x04 \x01(\tR\x06status\x12#\n" + + "\n" + + "assigneeID\x18\x05 \x01(\x05H\x00R\n" + + "assigneeID\x88\x01\x01\x12\"\n" + + "\fassigneeName\x18\x06 \x01(\tR\fassigneeName\x12\x1f\n" + + "\bauthorID\x18\a \x01(\x05H\x01R\bauthorID\x88\x01\x01\x12\x18\n" + + "\adueDate\x18\b \x01(\tR\adueDate\x128\n" + + "\tcreatedAt\x18\t \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x128\n" + + "\tupdatedAt\x18\n" + + " \x01(\v2\x1a.google.protobuf.TimestampR\tupdatedAt\x12\x18\n" + + "\aversion\x18\v \x01(\x05R\aversionB\r\n" + + "\v_assigneeIDB\v\n" + + "\t_authorID\"2\n" + + "\fTaskAssignee\x12\x0e\n" + + "\x02ID\x18\x01 \x01(\x05R\x02ID\x12\x12\n" + + "\x04name\x18\x02 \x01(\tR\x04name\"\r\n" + + "\vGetTasksReq\"R\n" + + "\vGetTasksRsp\x12C\n" + + "\x05tasks\x18\x01 \x03(\v2-.crabs.evening_detective_server.DeveloperTaskR\x05tasks\"\x15\n" + + "\x13GetTaskAssigneesReq\"a\n" + + "\x13GetTaskAssigneesRsp\x12J\n" + + "\tassignees\x18\x01 \x03(\v2,.crabs.evening_detective_server.TaskAssigneeR\tassignees\"\xad\x01\n" + + "\rCreateTaskReq\x12\x14\n" + + "\x05title\x18\x01 \x01(\tR\x05title\x12 \n" + + "\vdescription\x18\x02 \x01(\tR\vdescription\x12\x16\n" + + "\x06status\x18\x03 \x01(\tR\x06status\x12#\n" + + "\n" + + "assigneeID\x18\x04 \x01(\x05H\x00R\n" + + "assigneeID\x88\x01\x01\x12\x18\n" + + "\adueDate\x18\x05 \x01(\tR\adueDateB\r\n" + + "\v_assigneeID\"\xd7\x01\n" + + "\rUpdateTaskReq\x12\x0e\n" + + "\x02ID\x18\x01 \x01(\x05R\x02ID\x12\x14\n" + + "\x05title\x18\x02 \x01(\tR\x05title\x12 \n" + + "\vdescription\x18\x03 \x01(\tR\vdescription\x12\x16\n" + + "\x06status\x18\x04 \x01(\tR\x06status\x12#\n" + + "\n" + + "assigneeID\x18\x05 \x01(\x05H\x00R\n" + + "assigneeID\x88\x01\x01\x12\x18\n" + + "\adueDate\x18\x06 \x01(\tR\adueDate\x12\x18\n" + + "\aversion\x18\a \x01(\x05R\aversionB\r\n" + + "\v_assigneeID\"T\n" + + "\x10SetTaskStatusReq\x12\x0e\n" + + "\x02ID\x18\x01 \x01(\x05R\x02ID\x12\x16\n" + + "\x06status\x18\x02 \x01(\tR\x06status\x12\x18\n" + + "\aversion\x18\x03 \x01(\x05R\aversion\"9\n" + + "\rDeleteTaskReq\x12\x0e\n" + + "\x02ID\x18\x01 \x01(\x05R\x02ID\x12\x18\n" + + "\aversion\x18\x02 \x01(\x05R\aversion\"L\n" + + "\aTaskRsp\x12A\n" + + "\x04task\x18\x01 \x01(\v2-.crabs.evening_detective_server.DeveloperTaskR\x04task\"\x0f\n" + + "\rDeleteTaskRsp*\xf6\x01\n" + "\n" + "ScreenMode\x12\x1b\n" + "\x17SCREEN_MODE_UNSPECIFIED\x10\x00\x12\x15\n" + @@ -11781,8 +12537,25 @@ const file_main_proto_rawDesc = "" + "\x1aMUSIC_PLAYBACK_UNSPECIFIED\x10\x00\x12\x1a\n" + "\x16MUSIC_PLAYBACK_STOPPED\x10\x01\x12\x1a\n" + "\x16MUSIC_PLAYBACK_PLAYING\x10\x02\x12\x19\n" + - "\x15MUSIC_PLAYBACK_PAUSED\x10\x032\xf6\xbc\x01\n" + - "\x16EveningDetectiveServer\x12\xd3\x05\n" + + "\x15MUSIC_PLAYBACK_PAUSED\x10\x032\xfe\xc9\x01\n" + + "\x16EveningDetectiveServer\x12\x8c\x02\n" + + "\bGetTasks\x12+.crabs.evening_detective_server.GetTasksReq\x1a+.crabs.evening_detective_server.GetTasksRsp\"\xa5\x01\x92A\x8f\x01\n" + + "\fЗадачи\x121Получить общую доску задач\x1aLДоступно разработчикам и администратору.\x82\xd3\xe4\x93\x02\f\x12\n" + + "/api/tasks\x12\xc4\x02\n" + + "\x10GetTaskAssignees\x123.crabs.evening_detective_server.GetTaskAssigneesReq\x1a3.crabs.evening_detective_server.GetTaskAssigneesRsp\"\xc5\x01\x92A\xa5\x01\n" + + "\fЗадачи\x12GПолучить разработчиков для назначения\x1aLДоступно разработчикам и администратору.\x82\xd3\xe4\x93\x02\x16\x12\x14/api/tasks/assignees\x12\xf8\x01\n" + + "\n" + + "CreateTask\x12-.crabs.evening_detective_server.CreateTaskReq\x1a'.crabs.evening_detective_server.TaskRsp\"\x91\x01\x92Ay\n" + + "\fЗадачи\x12\x1bСоздать задачу\x1aLДоступно разработчикам и администратору.\x82\xd3\xe4\x93\x02\x0f:\x01*\"\n" + + "/api/tasks\x12\x8a\x02\n" + + "\n" + + "UpdateTask\x12-.crabs.evening_detective_server.UpdateTaskReq\x1a'.crabs.evening_detective_server.TaskRsp\"\xa3\x01\x92A\x85\x01\n" + + "\fЗадачи\x12'Редактировать задачу\x1aLДоступно разработчикам и администратору.\x82\xd3\xe4\x93\x02\x14:\x01*\x1a\x0f/api/tasks/{ID}\x12\x9a\x02\n" + + "\rSetTaskStatus\x120.crabs.evening_detective_server.SetTaskStatusReq\x1a'.crabs.evening_detective_server.TaskRsp\"\xad\x01\x92A\x88\x01\n" + + "\fЗадачи\x12*Изменить статус задачи\x1aLДоступно разработчикам и администратору.\x82\xd3\xe4\x93\x02\x1b:\x01*\"\x16/api/tasks/{ID}/status\x12\x8a\x02\n" + + "\n" + + "DeleteTask\x12-.crabs.evening_detective_server.DeleteTaskReq\x1a-.crabs.evening_detective_server.DeleteTaskRsp\"\x9d\x01\x92Ay\n" + + "\fЗадачи\x12\x1bУдалить задачу\x1aLДоступно разработчикам и администратору.\x82\xd3\xe4\x93\x02\x1b:\x01*\"\x16/api/tasks/{ID}/delete\x12\xd3\x05\n" + "\x10GetParticipation\x123.crabs.evening_detective_server.GetParticipationReq\x1a0.crabs.evening_detective_server.ParticipationRsp\"\xd7\x04\x92A\xb2\x04\n" + ")Подтверждение участия\x122Получить состояние участия\x1a\xce\x03Возвращает команду, игру и текущее решение по персональному токену из письма. Авторизация JWT не требуется. Чтение не меняет статус участия. Токен передаётся в теле запроса. Недействительная ссылка и ошибки обработки возвращаются стандартным gRPC status error.b\x00\x82\xd3\xe4\x93\x02\x1b:\x01*\"\x16/api/participation/get\x12\xf9\b\n" + "\x13AnswerParticipation\x126.crabs.evening_detective_server.AnswerParticipationReq\x1a0.crabs.evening_detective_server.ParticipationRsp\"\xf7\a\x92A\xcf\a\n" + @@ -12051,7 +12824,7 @@ func file_main_proto_rawDescGZIP() []byte { } var file_main_proto_enumTypes = make([]protoimpl.EnumInfo, 4) -var file_main_proto_msgTypes = make([]protoimpl.MessageInfo, 212) +var file_main_proto_msgTypes = make([]protoimpl.MessageInfo, 224) var file_main_proto_goTypes = []any{ (ScreenMode)(0), // 0: crabs.evening_detective_server.ScreenMode (ScreenTimerState)(0), // 1: crabs.evening_detective_server.ScreenTimerState @@ -12269,12 +13042,24 @@ var file_main_proto_goTypes = []any{ (*AcceptTicketReq)(nil), // 213: crabs.evening_detective_server.AcceptTicketReq (*AcceptTicketRsp)(nil), // 214: crabs.evening_detective_server.AcceptTicketRsp (*TicketPage)(nil), // 215: crabs.evening_detective_server.TicketPage - (*timestamppb.Timestamp)(nil), // 216: google.protobuf.Timestamp - (*httpbody.HttpBody)(nil), // 217: google.api.HttpBody + (*DeveloperTask)(nil), // 216: crabs.evening_detective_server.DeveloperTask + (*TaskAssignee)(nil), // 217: crabs.evening_detective_server.TaskAssignee + (*GetTasksReq)(nil), // 218: crabs.evening_detective_server.GetTasksReq + (*GetTasksRsp)(nil), // 219: crabs.evening_detective_server.GetTasksRsp + (*GetTaskAssigneesReq)(nil), // 220: crabs.evening_detective_server.GetTaskAssigneesReq + (*GetTaskAssigneesRsp)(nil), // 221: crabs.evening_detective_server.GetTaskAssigneesRsp + (*CreateTaskReq)(nil), // 222: crabs.evening_detective_server.CreateTaskReq + (*UpdateTaskReq)(nil), // 223: crabs.evening_detective_server.UpdateTaskReq + (*SetTaskStatusReq)(nil), // 224: crabs.evening_detective_server.SetTaskStatusReq + (*DeleteTaskReq)(nil), // 225: crabs.evening_detective_server.DeleteTaskReq + (*TaskRsp)(nil), // 226: crabs.evening_detective_server.TaskRsp + (*DeleteTaskRsp)(nil), // 227: crabs.evening_detective_server.DeleteTaskRsp + (*timestamppb.Timestamp)(nil), // 228: google.protobuf.Timestamp + (*httpbody.HttpBody)(nil), // 229: google.api.HttpBody } var file_main_proto_depIdxs = []int32{ 26, // 0: crabs.evening_detective_server.GetUsersRsp.users:type_name -> crabs.evening_detective_server.User - 216, // 1: crabs.evening_detective_server.User.created_at:type_name -> google.protobuf.Timestamp + 228, // 1: crabs.evening_detective_server.User.created_at:type_name -> google.protobuf.Timestamp 26, // 2: crabs.evening_detective_server.GetUserByIDRsp.user:type_name -> crabs.evening_detective_server.User 26, // 3: crabs.evening_detective_server.GetMeRsp.user:type_name -> crabs.evening_detective_server.User 42, // 4: crabs.evening_detective_server.Playlist.tracks:type_name -> crabs.evening_detective_server.PlaylistTrack @@ -12287,9 +13072,9 @@ var file_main_proto_depIdxs = []int32{ 66, // 11: crabs.evening_detective_server.GetScenarioRsp.scenario:type_name -> crabs.evening_detective_server.Scenario 67, // 12: crabs.evening_detective_server.Scenario.story:type_name -> crabs.evening_detective_server.Story 26, // 13: crabs.evening_detective_server.Scenario.author:type_name -> crabs.evening_detective_server.User - 216, // 14: crabs.evening_detective_server.Scenario.updated_at:type_name -> google.protobuf.Timestamp - 216, // 15: crabs.evening_detective_server.Scenario.created_at:type_name -> google.protobuf.Timestamp - 216, // 16: crabs.evening_detective_server.Scenario.published_at:type_name -> google.protobuf.Timestamp + 228, // 14: crabs.evening_detective_server.Scenario.updated_at:type_name -> google.protobuf.Timestamp + 228, // 15: crabs.evening_detective_server.Scenario.created_at:type_name -> google.protobuf.Timestamp + 228, // 16: crabs.evening_detective_server.Scenario.published_at:type_name -> google.protobuf.Timestamp 70, // 17: crabs.evening_detective_server.Story.places:type_name -> crabs.evening_detective_server.Place 69, // 18: crabs.evening_detective_server.Story.introduction:type_name -> crabs.evening_detective_server.Introduction 74, // 19: crabs.evening_detective_server.Story.questions:type_name -> crabs.evening_detective_server.Question @@ -12306,13 +13091,13 @@ var file_main_proto_depIdxs = []int32{ 69, // 30: crabs.evening_detective_server.UpdateScenarioIntroReq.introduction:type_name -> crabs.evening_detective_server.Introduction 74, // 31: crabs.evening_detective_server.AddScenarioQuestionReq.question:type_name -> crabs.evening_detective_server.Question 74, // 32: crabs.evening_detective_server.UpdateScenarioQuestionReq.question:type_name -> crabs.evening_detective_server.Question - 216, // 33: crabs.evening_detective_server.AddGameReq.start_at:type_name -> google.protobuf.Timestamp + 228, // 33: crabs.evening_detective_server.AddGameReq.start_at:type_name -> google.protobuf.Timestamp 108, // 34: crabs.evening_detective_server.GetGamesRsp.games:type_name -> crabs.evening_detective_server.Game - 216, // 35: crabs.evening_detective_server.Game.start_at:type_name -> google.protobuf.Timestamp + 228, // 35: crabs.evening_detective_server.Game.start_at:type_name -> google.protobuf.Timestamp 66, // 36: crabs.evening_detective_server.Game.scenario:type_name -> crabs.evening_detective_server.Scenario 153, // 37: crabs.evening_detective_server.Game.teams:type_name -> crabs.evening_detective_server.Team - 216, // 38: crabs.evening_detective_server.Game.started_at:type_name -> google.protobuf.Timestamp - 216, // 39: crabs.evening_detective_server.Game.ended_at:type_name -> google.protobuf.Timestamp + 228, // 38: crabs.evening_detective_server.Game.started_at:type_name -> google.protobuf.Timestamp + 228, // 39: crabs.evening_detective_server.Game.ended_at:type_name -> google.protobuf.Timestamp 0, // 40: crabs.evening_detective_server.ScreenState.mode:type_name -> crabs.evening_detective_server.ScreenMode 2, // 41: crabs.evening_detective_server.ScreenState.command:type_name -> crabs.evening_detective_server.ScreenCommand 1, // 42: crabs.evening_detective_server.ScreenState.timer_state:type_name -> crabs.evening_detective_server.ScreenTimerState @@ -12338,7 +13123,7 @@ var file_main_proto_depIdxs = []int32{ 141, // 62: crabs.evening_detective_server.SetScreenPlanStepRsp.plan:type_name -> crabs.evening_detective_server.ScreenPlan 159, // 63: crabs.evening_detective_server.GetScreenResultsRsp.questions:type_name -> crabs.evening_detective_server.ResultsQuestion 160, // 64: crabs.evening_detective_server.GetScreenResultsRsp.teams:type_name -> crabs.evening_detective_server.TeamResult - 216, // 65: crabs.evening_detective_server.ParticipationRsp.start_at:type_name -> google.protobuf.Timestamp + 228, // 65: crabs.evening_detective_server.ParticipationRsp.start_at:type_name -> google.protobuf.Timestamp 71, // 66: crabs.evening_detective_server.Team.applications:type_name -> crabs.evening_detective_server.Application 108, // 67: crabs.evening_detective_server.GetGameRsp.game:type_name -> crabs.evening_detective_server.Game 74, // 68: crabs.evening_detective_server.GetGameAnswersRsp.questions:type_name -> crabs.evening_detective_server.Question @@ -12347,11 +13132,11 @@ var file_main_proto_depIdxs = []int32{ 76, // 71: crabs.evening_detective_server.TeamResult.answers:type_name -> crabs.evening_detective_server.AnswerScore 159, // 72: crabs.evening_detective_server.GetGameResultsRsp.questions:type_name -> crabs.evening_detective_server.ResultsQuestion 160, // 73: crabs.evening_detective_server.GetGameResultsRsp.teams:type_name -> crabs.evening_detective_server.TeamResult - 216, // 74: crabs.evening_detective_server.GameReview.created_at:type_name -> google.protobuf.Timestamp + 228, // 74: crabs.evening_detective_server.GameReview.created_at:type_name -> google.protobuf.Timestamp 162, // 75: crabs.evening_detective_server.CreateGameReviewRsp.review:type_name -> crabs.evening_detective_server.GameReview 162, // 76: crabs.evening_detective_server.GetGameReviewsRsp.reviews:type_name -> crabs.evening_detective_server.GameReview 162, // 77: crabs.evening_detective_server.ModerateGameReviewRsp.review:type_name -> crabs.evening_detective_server.GameReview - 216, // 78: crabs.evening_detective_server.UpdateGameReq.start_at:type_name -> google.protobuf.Timestamp + 228, // 78: crabs.evening_detective_server.UpdateGameReq.start_at:type_name -> google.protobuf.Timestamp 67, // 79: crabs.evening_detective_server.GetTeamStoryRsp.story:type_name -> crabs.evening_detective_server.Story 108, // 80: crabs.evening_detective_server.GetTeamStoryRsp.game:type_name -> crabs.evening_detective_server.Game 195, // 81: crabs.evening_detective_server.GetTeamStoryRsp.actions:type_name -> crabs.evening_detective_server.TeamAction @@ -12360,209 +13145,226 @@ var file_main_proto_depIdxs = []int32{ 210, // 84: crabs.evening_detective_server.IssueGameTicketsRsp.tickets:type_name -> crabs.evening_detective_server.Ticket 215, // 85: crabs.evening_detective_server.GetTicketRsp.ticket:type_name -> crabs.evening_detective_server.TicketPage 215, // 86: crabs.evening_detective_server.AcceptTicketRsp.ticket:type_name -> crabs.evening_detective_server.TicketPage - 216, // 87: crabs.evening_detective_server.TicketPage.start_at:type_name -> google.protobuf.Timestamp - 216, // 88: crabs.evening_detective_server.TicketPage.used_at:type_name -> google.protobuf.Timestamp - 150, // 89: crabs.evening_detective_server.EveningDetectiveServer.GetParticipation:input_type -> crabs.evening_detective_server.GetParticipationReq - 151, // 90: crabs.evening_detective_server.EveningDetectiveServer.AnswerParticipation:input_type -> crabs.evening_detective_server.AnswerParticipationReq - 4, // 91: crabs.evening_detective_server.EveningDetectiveServer.Ping:input_type -> crabs.evening_detective_server.PingReq - 6, // 92: crabs.evening_detective_server.EveningDetectiveServer.Echo:input_type -> crabs.evening_detective_server.EchoReq - 8, // 93: crabs.evening_detective_server.EveningDetectiveServer.Signup:input_type -> crabs.evening_detective_server.SignupReq - 10, // 94: crabs.evening_detective_server.EveningDetectiveServer.RefreshPassword:input_type -> crabs.evening_detective_server.RefreshPasswordReq - 12, // 95: crabs.evening_detective_server.EveningDetectiveServer.Login:input_type -> crabs.evening_detective_server.LoginReq - 14, // 96: crabs.evening_detective_server.EveningDetectiveServer.Refresh:input_type -> crabs.evening_detective_server.RefreshReq - 16, // 97: crabs.evening_detective_server.EveningDetectiveServer.DeleteAccount:input_type -> crabs.evening_detective_server.DeleteAccountReq - 18, // 98: crabs.evening_detective_server.EveningDetectiveServer.GetTerms:input_type -> crabs.evening_detective_server.GetTermsReq - 20, // 99: crabs.evening_detective_server.EveningDetectiveServer.GetPrivacy:input_type -> crabs.evening_detective_server.GetPrivacyReq - 22, // 100: crabs.evening_detective_server.EveningDetectiveServer.GetConsent:input_type -> crabs.evening_detective_server.GetConsentReq - 24, // 101: crabs.evening_detective_server.EveningDetectiveServer.GetUsers:input_type -> crabs.evening_detective_server.GetUsersReq - 27, // 102: crabs.evening_detective_server.EveningDetectiveServer.GetUserByID:input_type -> crabs.evening_detective_server.GetUserByIDReq - 29, // 103: crabs.evening_detective_server.EveningDetectiveServer.GetMe:input_type -> crabs.evening_detective_server.GetMeReq - 31, // 104: crabs.evening_detective_server.EveningDetectiveServer.ChangeUserPassword:input_type -> crabs.evening_detective_server.ChangeUserPasswordReq - 33, // 105: crabs.evening_detective_server.EveningDetectiveServer.AddUserRole:input_type -> crabs.evening_detective_server.AddUserRoleReq - 35, // 106: crabs.evening_detective_server.EveningDetectiveServer.DeleteUserRole:input_type -> crabs.evening_detective_server.DeleteUserRoleReq - 37, // 107: crabs.evening_detective_server.EveningDetectiveServer.GetPermissions:input_type -> crabs.evening_detective_server.GetPermissionsReq - 39, // 108: crabs.evening_detective_server.EveningDetectiveServer.UploadFile:input_type -> crabs.evening_detective_server.UploadFileReq - 41, // 109: crabs.evening_detective_server.EveningDetectiveServer.DownloadFile:input_type -> crabs.evening_detective_server.DownloadFileReq - 44, // 110: crabs.evening_detective_server.EveningDetectiveServer.GetPlaylists:input_type -> crabs.evening_detective_server.GetPlaylistsReq - 46, // 111: crabs.evening_detective_server.EveningDetectiveServer.CreatePlaylist:input_type -> crabs.evening_detective_server.CreatePlaylistReq - 48, // 112: crabs.evening_detective_server.EveningDetectiveServer.UpdatePlaylist:input_type -> crabs.evening_detective_server.UpdatePlaylistReq - 50, // 113: crabs.evening_detective_server.EveningDetectiveServer.DeletePlaylist:input_type -> crabs.evening_detective_server.DeletePlaylistReq - 52, // 114: crabs.evening_detective_server.EveningDetectiveServer.UploadPlaylistTrack:input_type -> crabs.evening_detective_server.UploadPlaylistTrackReq - 54, // 115: crabs.evening_detective_server.EveningDetectiveServer.DeletePlaylistTrack:input_type -> crabs.evening_detective_server.DeletePlaylistTrackReq - 56, // 116: crabs.evening_detective_server.EveningDetectiveServer.SetScenarioPlaylist:input_type -> crabs.evening_detective_server.SetScenarioPlaylistReq - 58, // 117: crabs.evening_detective_server.EveningDetectiveServer.AddScenario:input_type -> crabs.evening_detective_server.AddScenarioReq - 60, // 118: crabs.evening_detective_server.EveningDetectiveServer.GetMyScenarios:input_type -> crabs.evening_detective_server.GetMyScenariosReq - 62, // 119: crabs.evening_detective_server.EveningDetectiveServer.GetScenariosCatalog:input_type -> crabs.evening_detective_server.GetScenariosCatalogReq - 64, // 120: crabs.evening_detective_server.EveningDetectiveServer.GetFullScenario:input_type -> crabs.evening_detective_server.GetScenarioReq - 64, // 121: crabs.evening_detective_server.EveningDetectiveServer.GetScenario:input_type -> crabs.evening_detective_server.GetScenarioReq - 78, // 122: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenario:input_type -> crabs.evening_detective_server.UpdateScenarioReq - 80, // 123: crabs.evening_detective_server.EveningDetectiveServer.PublicScenario:input_type -> crabs.evening_detective_server.PublicScenarioReq - 82, // 124: crabs.evening_detective_server.EveningDetectiveServer.DraftScenario:input_type -> crabs.evening_detective_server.DraftScenarioReq - 84, // 125: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenario:input_type -> crabs.evening_detective_server.DeleteScenarioReq - 86, // 126: crabs.evening_detective_server.EveningDetectiveServer.AddScenarioPlace:input_type -> crabs.evening_detective_server.AddScenarioPlaceReq - 88, // 127: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioPlace:input_type -> crabs.evening_detective_server.UpdateScenarioPlaceReq - 90, // 128: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenarioPlace:input_type -> crabs.evening_detective_server.DeleteScenarioPlaceReq - 96, // 129: crabs.evening_detective_server.EveningDetectiveServer.AddScenarioQuestion:input_type -> crabs.evening_detective_server.AddScenarioQuestionReq - 98, // 130: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioQuestion:input_type -> crabs.evening_detective_server.UpdateScenarioQuestionReq - 100, // 131: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenarioQuestion:input_type -> crabs.evening_detective_server.DeleteScenarioQuestionReq - 206, // 132: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioBackground:input_type -> crabs.evening_detective_server.UpdateScenarioBackgroundReq - 94, // 133: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioIntro:input_type -> crabs.evening_detective_server.UpdateScenarioIntroReq - 92, // 134: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioConclusion:input_type -> crabs.evening_detective_server.UpdateScenarioConclusionReq - 102, // 135: crabs.evening_detective_server.EveningDetectiveServer.DownloadScenarioArchive:input_type -> crabs.evening_detective_server.DownloadScenarioArchiveReq - 217, // 136: crabs.evening_detective_server.EveningDetectiveServer.UploadScenarioArchive:input_type -> google.api.HttpBody - 104, // 137: crabs.evening_detective_server.EveningDetectiveServer.AddGame:input_type -> crabs.evening_detective_server.AddGameReq - 106, // 138: crabs.evening_detective_server.EveningDetectiveServer.GetGames:input_type -> crabs.evening_detective_server.GetGamesReq - 154, // 139: crabs.evening_detective_server.EveningDetectiveServer.GetGame:input_type -> crabs.evening_detective_server.GetGameReq - 208, // 140: crabs.evening_detective_server.EveningDetectiveServer.IssueGameTickets:input_type -> crabs.evening_detective_server.IssueGameTicketsReq - 211, // 141: crabs.evening_detective_server.EveningDetectiveServer.GetTicket:input_type -> crabs.evening_detective_server.GetTicketReq - 213, // 142: crabs.evening_detective_server.EveningDetectiveServer.AcceptTicket:input_type -> crabs.evening_detective_server.AcceptTicketReq - 110, // 143: crabs.evening_detective_server.EveningDetectiveServer.CreateScreenSession:input_type -> crabs.evening_detective_server.CreateScreenSessionReq - 112, // 144: crabs.evening_detective_server.EveningDetectiveServer.GetScreenState:input_type -> crabs.evening_detective_server.GetScreenStateReq - 114, // 145: crabs.evening_detective_server.EveningDetectiveServer.GetGameScreens:input_type -> crabs.evening_detective_server.GetGameScreensReq - 117, // 146: crabs.evening_detective_server.EveningDetectiveServer.GetGameMusic:input_type -> crabs.evening_detective_server.GetGameMusicReq - 119, // 147: crabs.evening_detective_server.EveningDetectiveServer.SetGameMusic:input_type -> crabs.evening_detective_server.SetGameMusicReq - 121, // 148: crabs.evening_detective_server.EveningDetectiveServer.AdvanceScreenMusic:input_type -> crabs.evening_detective_server.AdvanceScreenMusicReq - 123, // 149: crabs.evening_detective_server.EveningDetectiveServer.BindScreen:input_type -> crabs.evening_detective_server.BindScreenReq - 125, // 150: crabs.evening_detective_server.EveningDetectiveServer.UnbindScreen:input_type -> crabs.evening_detective_server.UnbindScreenReq - 127, // 151: crabs.evening_detective_server.EveningDetectiveServer.SetScreenSound:input_type -> crabs.evening_detective_server.SetScreenSoundReq - 130, // 152: crabs.evening_detective_server.EveningDetectiveServer.GetGameMap:input_type -> crabs.evening_detective_server.GetGameMapReq - 132, // 153: crabs.evening_detective_server.EveningDetectiveServer.UpdateGameMapItem:input_type -> crabs.evening_detective_server.UpdateGameMapItemReq - 134, // 154: crabs.evening_detective_server.EveningDetectiveServer.SetScreenMode:input_type -> crabs.evening_detective_server.SetScreenModeReq - 136, // 155: crabs.evening_detective_server.EveningDetectiveServer.SetScreenTimer:input_type -> crabs.evening_detective_server.SetScreenTimerReq - 138, // 156: crabs.evening_detective_server.EveningDetectiveServer.SendScreenCommand:input_type -> crabs.evening_detective_server.SendScreenCommandReq - 142, // 157: crabs.evening_detective_server.EveningDetectiveServer.GetScreenPlan:input_type -> crabs.evening_detective_server.GetScreenPlanReq - 144, // 158: crabs.evening_detective_server.EveningDetectiveServer.SaveScreenPlan:input_type -> crabs.evening_detective_server.SaveScreenPlanReq - 146, // 159: crabs.evening_detective_server.EveningDetectiveServer.SetScreenPlanStep:input_type -> crabs.evening_detective_server.SetScreenPlanStepReq - 148, // 160: crabs.evening_detective_server.EveningDetectiveServer.GetScreenResults:input_type -> crabs.evening_detective_server.GetScreenResultsReq - 154, // 161: crabs.evening_detective_server.EveningDetectiveServer.DownloadTeamQR:input_type -> crabs.evening_detective_server.GetGameReq - 156, // 162: crabs.evening_detective_server.EveningDetectiveServer.GetGameAnswers:input_type -> crabs.evening_detective_server.GetGameAnswersReq - 158, // 163: crabs.evening_detective_server.EveningDetectiveServer.GetGameResults:input_type -> crabs.evening_detective_server.GetGameResultsReq - 163, // 164: crabs.evening_detective_server.EveningDetectiveServer.CreateGameReview:input_type -> crabs.evening_detective_server.CreateGameReviewReq - 165, // 165: crabs.evening_detective_server.EveningDetectiveServer.GetGameReviews:input_type -> crabs.evening_detective_server.GetGameReviewsReq - 166, // 166: crabs.evening_detective_server.EveningDetectiveServer.GetScenarioReviews:input_type -> crabs.evening_detective_server.GetScenarioReviewsReq - 165, // 167: crabs.evening_detective_server.EveningDetectiveServer.GetGameReviewsForModeration:input_type -> crabs.evening_detective_server.GetGameReviewsReq - 167, // 168: crabs.evening_detective_server.EveningDetectiveServer.GetReviewsForModeration:input_type -> crabs.evening_detective_server.GetReviewsForModerationReq - 169, // 169: crabs.evening_detective_server.EveningDetectiveServer.ModerateGameReview:input_type -> crabs.evening_detective_server.ModerateGameReviewReq - 171, // 170: crabs.evening_detective_server.EveningDetectiveServer.UpdateGame:input_type -> crabs.evening_detective_server.UpdateGameReq - 173, // 171: crabs.evening_detective_server.EveningDetectiveServer.StartGame:input_type -> crabs.evening_detective_server.StartGameReq - 175, // 172: crabs.evening_detective_server.EveningDetectiveServer.PauseGame:input_type -> crabs.evening_detective_server.PauseGameReq - 177, // 173: crabs.evening_detective_server.EveningDetectiveServer.PlayGame:input_type -> crabs.evening_detective_server.PlayGameReq - 179, // 174: crabs.evening_detective_server.EveningDetectiveServer.FinishGame:input_type -> crabs.evening_detective_server.FinishGameReq - 181, // 175: crabs.evening_detective_server.EveningDetectiveServer.ResetGame:input_type -> crabs.evening_detective_server.ResetGameReq - 183, // 176: crabs.evening_detective_server.EveningDetectiveServer.DeleteGame:input_type -> crabs.evening_detective_server.DeleteGameReq - 185, // 177: crabs.evening_detective_server.EveningDetectiveServer.AddTeam:input_type -> crabs.evening_detective_server.AddTeamReq - 187, // 178: crabs.evening_detective_server.EveningDetectiveServer.UpdateTeam:input_type -> crabs.evening_detective_server.UpdateTeamReq - 189, // 179: crabs.evening_detective_server.EveningDetectiveServer.DeleteTeam:input_type -> crabs.evening_detective_server.DeleteTeamReq - 191, // 180: crabs.evening_detective_server.EveningDetectiveServer.GiveTeamApplications:input_type -> crabs.evening_detective_server.GiveTeamApplicationsReq - 193, // 181: crabs.evening_detective_server.EveningDetectiveServer.GetTeamStory:input_type -> crabs.evening_detective_server.GetTeamStoryReq - 196, // 182: crabs.evening_detective_server.EveningDetectiveServer.AddTeamAction:input_type -> crabs.evening_detective_server.AddTeamActionReq - 198, // 183: crabs.evening_detective_server.EveningDetectiveServer.DeleteLastTeamAction:input_type -> crabs.evening_detective_server.DeleteLastTeamActionReq - 200, // 184: crabs.evening_detective_server.EveningDetectiveServer.GetTeamAnswers:input_type -> crabs.evening_detective_server.GetTeamAnswersReq - 202, // 185: crabs.evening_detective_server.EveningDetectiveServer.SubmitTeamAnswers:input_type -> crabs.evening_detective_server.SubmitTeamAnswersReq - 204, // 186: crabs.evening_detective_server.EveningDetectiveServer.SetTeamAnswerScore:input_type -> crabs.evening_detective_server.SetTeamAnswerScoreReq - 152, // 187: crabs.evening_detective_server.EveningDetectiveServer.GetParticipation:output_type -> crabs.evening_detective_server.ParticipationRsp - 152, // 188: crabs.evening_detective_server.EveningDetectiveServer.AnswerParticipation:output_type -> crabs.evening_detective_server.ParticipationRsp - 5, // 189: crabs.evening_detective_server.EveningDetectiveServer.Ping:output_type -> crabs.evening_detective_server.PingRsp - 7, // 190: crabs.evening_detective_server.EveningDetectiveServer.Echo:output_type -> crabs.evening_detective_server.EchoRsp - 9, // 191: crabs.evening_detective_server.EveningDetectiveServer.Signup:output_type -> crabs.evening_detective_server.SignupRsp - 11, // 192: crabs.evening_detective_server.EveningDetectiveServer.RefreshPassword:output_type -> crabs.evening_detective_server.RefreshPasswordRsp - 13, // 193: crabs.evening_detective_server.EveningDetectiveServer.Login:output_type -> crabs.evening_detective_server.LoginRsp - 15, // 194: crabs.evening_detective_server.EveningDetectiveServer.Refresh:output_type -> crabs.evening_detective_server.RefreshRsp - 17, // 195: crabs.evening_detective_server.EveningDetectiveServer.DeleteAccount:output_type -> crabs.evening_detective_server.DeleteAccountRsp - 19, // 196: crabs.evening_detective_server.EveningDetectiveServer.GetTerms:output_type -> crabs.evening_detective_server.GetTermsRsp - 21, // 197: crabs.evening_detective_server.EveningDetectiveServer.GetPrivacy:output_type -> crabs.evening_detective_server.GetPrivacyRsp - 23, // 198: crabs.evening_detective_server.EveningDetectiveServer.GetConsent:output_type -> crabs.evening_detective_server.GetConsentRsp - 25, // 199: crabs.evening_detective_server.EveningDetectiveServer.GetUsers:output_type -> crabs.evening_detective_server.GetUsersRsp - 28, // 200: crabs.evening_detective_server.EveningDetectiveServer.GetUserByID:output_type -> crabs.evening_detective_server.GetUserByIDRsp - 30, // 201: crabs.evening_detective_server.EveningDetectiveServer.GetMe:output_type -> crabs.evening_detective_server.GetMeRsp - 32, // 202: crabs.evening_detective_server.EveningDetectiveServer.ChangeUserPassword:output_type -> crabs.evening_detective_server.ChangeUserPasswordRsp - 34, // 203: crabs.evening_detective_server.EveningDetectiveServer.AddUserRole:output_type -> crabs.evening_detective_server.AddUserRoleRsp - 36, // 204: crabs.evening_detective_server.EveningDetectiveServer.DeleteUserRole:output_type -> crabs.evening_detective_server.DeleteUserRoleRsp - 38, // 205: crabs.evening_detective_server.EveningDetectiveServer.GetPermissions:output_type -> crabs.evening_detective_server.GetPermissionsRsp - 40, // 206: crabs.evening_detective_server.EveningDetectiveServer.UploadFile:output_type -> crabs.evening_detective_server.UploadFileRsp - 217, // 207: crabs.evening_detective_server.EveningDetectiveServer.DownloadFile:output_type -> google.api.HttpBody - 45, // 208: crabs.evening_detective_server.EveningDetectiveServer.GetPlaylists:output_type -> crabs.evening_detective_server.GetPlaylistsRsp - 47, // 209: crabs.evening_detective_server.EveningDetectiveServer.CreatePlaylist:output_type -> crabs.evening_detective_server.CreatePlaylistRsp - 49, // 210: crabs.evening_detective_server.EveningDetectiveServer.UpdatePlaylist:output_type -> crabs.evening_detective_server.UpdatePlaylistRsp - 51, // 211: crabs.evening_detective_server.EveningDetectiveServer.DeletePlaylist:output_type -> crabs.evening_detective_server.DeletePlaylistRsp - 53, // 212: crabs.evening_detective_server.EveningDetectiveServer.UploadPlaylistTrack:output_type -> crabs.evening_detective_server.UploadPlaylistTrackRsp - 55, // 213: crabs.evening_detective_server.EveningDetectiveServer.DeletePlaylistTrack:output_type -> crabs.evening_detective_server.DeletePlaylistTrackRsp - 57, // 214: crabs.evening_detective_server.EveningDetectiveServer.SetScenarioPlaylist:output_type -> crabs.evening_detective_server.SetScenarioPlaylistRsp - 59, // 215: crabs.evening_detective_server.EveningDetectiveServer.AddScenario:output_type -> crabs.evening_detective_server.AddScenarioRsp - 61, // 216: crabs.evening_detective_server.EveningDetectiveServer.GetMyScenarios:output_type -> crabs.evening_detective_server.GetMyScenariosRsp - 63, // 217: crabs.evening_detective_server.EveningDetectiveServer.GetScenariosCatalog:output_type -> crabs.evening_detective_server.GetScenariosCatalogRsp - 65, // 218: crabs.evening_detective_server.EveningDetectiveServer.GetFullScenario:output_type -> crabs.evening_detective_server.GetScenarioRsp - 65, // 219: crabs.evening_detective_server.EveningDetectiveServer.GetScenario:output_type -> crabs.evening_detective_server.GetScenarioRsp - 79, // 220: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenario:output_type -> crabs.evening_detective_server.UpdateScenarioRsp - 81, // 221: crabs.evening_detective_server.EveningDetectiveServer.PublicScenario:output_type -> crabs.evening_detective_server.PublicScenarioRsp - 83, // 222: crabs.evening_detective_server.EveningDetectiveServer.DraftScenario:output_type -> crabs.evening_detective_server.DraftScenarioRsp - 85, // 223: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenario:output_type -> crabs.evening_detective_server.DeleteScenarioRsp - 87, // 224: crabs.evening_detective_server.EveningDetectiveServer.AddScenarioPlace:output_type -> crabs.evening_detective_server.AddScenarioPlaceRsp - 89, // 225: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioPlace:output_type -> crabs.evening_detective_server.UpdateScenarioPlaceRsp - 91, // 226: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenarioPlace:output_type -> crabs.evening_detective_server.DeleteScenarioPlaceRsp - 97, // 227: crabs.evening_detective_server.EveningDetectiveServer.AddScenarioQuestion:output_type -> crabs.evening_detective_server.AddScenarioQuestionRsp - 99, // 228: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioQuestion:output_type -> crabs.evening_detective_server.UpdateScenarioQuestionRsp - 101, // 229: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenarioQuestion:output_type -> crabs.evening_detective_server.DeleteScenarioQuestionRsp - 207, // 230: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioBackground:output_type -> crabs.evening_detective_server.UpdateScenarioBackgroundRsp - 95, // 231: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioIntro:output_type -> crabs.evening_detective_server.UpdateScenarioIntroRsp - 93, // 232: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioConclusion:output_type -> crabs.evening_detective_server.UpdateScenarioConclusionRsp - 217, // 233: crabs.evening_detective_server.EveningDetectiveServer.DownloadScenarioArchive:output_type -> google.api.HttpBody - 103, // 234: crabs.evening_detective_server.EveningDetectiveServer.UploadScenarioArchive:output_type -> crabs.evening_detective_server.UploadScenarioArchiveRsp - 105, // 235: crabs.evening_detective_server.EveningDetectiveServer.AddGame:output_type -> crabs.evening_detective_server.AddGameRsp - 107, // 236: crabs.evening_detective_server.EveningDetectiveServer.GetGames:output_type -> crabs.evening_detective_server.GetGamesRsp - 155, // 237: crabs.evening_detective_server.EveningDetectiveServer.GetGame:output_type -> crabs.evening_detective_server.GetGameRsp - 209, // 238: crabs.evening_detective_server.EveningDetectiveServer.IssueGameTickets:output_type -> crabs.evening_detective_server.IssueGameTicketsRsp - 212, // 239: crabs.evening_detective_server.EveningDetectiveServer.GetTicket:output_type -> crabs.evening_detective_server.GetTicketRsp - 214, // 240: crabs.evening_detective_server.EveningDetectiveServer.AcceptTicket:output_type -> crabs.evening_detective_server.AcceptTicketRsp - 111, // 241: crabs.evening_detective_server.EveningDetectiveServer.CreateScreenSession:output_type -> crabs.evening_detective_server.CreateScreenSessionRsp - 113, // 242: crabs.evening_detective_server.EveningDetectiveServer.GetScreenState:output_type -> crabs.evening_detective_server.GetScreenStateRsp - 115, // 243: crabs.evening_detective_server.EveningDetectiveServer.GetGameScreens:output_type -> crabs.evening_detective_server.GetGameScreensRsp - 118, // 244: crabs.evening_detective_server.EveningDetectiveServer.GetGameMusic:output_type -> crabs.evening_detective_server.GetGameMusicRsp - 120, // 245: crabs.evening_detective_server.EveningDetectiveServer.SetGameMusic:output_type -> crabs.evening_detective_server.SetGameMusicRsp - 122, // 246: crabs.evening_detective_server.EveningDetectiveServer.AdvanceScreenMusic:output_type -> crabs.evening_detective_server.AdvanceScreenMusicRsp - 124, // 247: crabs.evening_detective_server.EveningDetectiveServer.BindScreen:output_type -> crabs.evening_detective_server.BindScreenRsp - 126, // 248: crabs.evening_detective_server.EveningDetectiveServer.UnbindScreen:output_type -> crabs.evening_detective_server.UnbindScreenRsp - 128, // 249: crabs.evening_detective_server.EveningDetectiveServer.SetScreenSound:output_type -> crabs.evening_detective_server.SetScreenSoundRsp - 131, // 250: crabs.evening_detective_server.EveningDetectiveServer.GetGameMap:output_type -> crabs.evening_detective_server.GetGameMapRsp - 133, // 251: crabs.evening_detective_server.EveningDetectiveServer.UpdateGameMapItem:output_type -> crabs.evening_detective_server.UpdateGameMapItemRsp - 135, // 252: crabs.evening_detective_server.EveningDetectiveServer.SetScreenMode:output_type -> crabs.evening_detective_server.SetScreenModeRsp - 137, // 253: crabs.evening_detective_server.EveningDetectiveServer.SetScreenTimer:output_type -> crabs.evening_detective_server.SetScreenTimerRsp - 139, // 254: crabs.evening_detective_server.EveningDetectiveServer.SendScreenCommand:output_type -> crabs.evening_detective_server.SendScreenCommandRsp - 143, // 255: crabs.evening_detective_server.EveningDetectiveServer.GetScreenPlan:output_type -> crabs.evening_detective_server.GetScreenPlanRsp - 145, // 256: crabs.evening_detective_server.EveningDetectiveServer.SaveScreenPlan:output_type -> crabs.evening_detective_server.SaveScreenPlanRsp - 147, // 257: crabs.evening_detective_server.EveningDetectiveServer.SetScreenPlanStep:output_type -> crabs.evening_detective_server.SetScreenPlanStepRsp - 149, // 258: crabs.evening_detective_server.EveningDetectiveServer.GetScreenResults:output_type -> crabs.evening_detective_server.GetScreenResultsRsp - 217, // 259: crabs.evening_detective_server.EveningDetectiveServer.DownloadTeamQR:output_type -> google.api.HttpBody - 157, // 260: crabs.evening_detective_server.EveningDetectiveServer.GetGameAnswers:output_type -> crabs.evening_detective_server.GetGameAnswersRsp - 161, // 261: crabs.evening_detective_server.EveningDetectiveServer.GetGameResults:output_type -> crabs.evening_detective_server.GetGameResultsRsp - 164, // 262: crabs.evening_detective_server.EveningDetectiveServer.CreateGameReview:output_type -> crabs.evening_detective_server.CreateGameReviewRsp - 168, // 263: crabs.evening_detective_server.EveningDetectiveServer.GetGameReviews:output_type -> crabs.evening_detective_server.GetGameReviewsRsp - 168, // 264: crabs.evening_detective_server.EveningDetectiveServer.GetScenarioReviews:output_type -> crabs.evening_detective_server.GetGameReviewsRsp - 168, // 265: crabs.evening_detective_server.EveningDetectiveServer.GetGameReviewsForModeration:output_type -> crabs.evening_detective_server.GetGameReviewsRsp - 168, // 266: crabs.evening_detective_server.EveningDetectiveServer.GetReviewsForModeration:output_type -> crabs.evening_detective_server.GetGameReviewsRsp - 170, // 267: crabs.evening_detective_server.EveningDetectiveServer.ModerateGameReview:output_type -> crabs.evening_detective_server.ModerateGameReviewRsp - 172, // 268: crabs.evening_detective_server.EveningDetectiveServer.UpdateGame:output_type -> crabs.evening_detective_server.UpdateGameRsp - 174, // 269: crabs.evening_detective_server.EveningDetectiveServer.StartGame:output_type -> crabs.evening_detective_server.StartGameRsp - 176, // 270: crabs.evening_detective_server.EveningDetectiveServer.PauseGame:output_type -> crabs.evening_detective_server.PauseGameRsp - 178, // 271: crabs.evening_detective_server.EveningDetectiveServer.PlayGame:output_type -> crabs.evening_detective_server.PlayGameRsp - 180, // 272: crabs.evening_detective_server.EveningDetectiveServer.FinishGame:output_type -> crabs.evening_detective_server.FinishGameRsp - 182, // 273: crabs.evening_detective_server.EveningDetectiveServer.ResetGame:output_type -> crabs.evening_detective_server.ResetGameRsp - 184, // 274: crabs.evening_detective_server.EveningDetectiveServer.DeleteGame:output_type -> crabs.evening_detective_server.DeleteGameRsp - 186, // 275: crabs.evening_detective_server.EveningDetectiveServer.AddTeam:output_type -> crabs.evening_detective_server.AddTeamRsp - 188, // 276: crabs.evening_detective_server.EveningDetectiveServer.UpdateTeam:output_type -> crabs.evening_detective_server.UpdateTeamRsp - 190, // 277: crabs.evening_detective_server.EveningDetectiveServer.DeleteTeam:output_type -> crabs.evening_detective_server.DeleteTeamRsp - 192, // 278: crabs.evening_detective_server.EveningDetectiveServer.GiveTeamApplications:output_type -> crabs.evening_detective_server.GiveTeamApplicationsRsp - 194, // 279: crabs.evening_detective_server.EveningDetectiveServer.GetTeamStory:output_type -> crabs.evening_detective_server.GetTeamStoryRsp - 197, // 280: crabs.evening_detective_server.EveningDetectiveServer.AddTeamAction:output_type -> crabs.evening_detective_server.AddTeamActionRsp - 199, // 281: crabs.evening_detective_server.EveningDetectiveServer.DeleteLastTeamAction:output_type -> crabs.evening_detective_server.DeleteLastTeamActionRsp - 201, // 282: crabs.evening_detective_server.EveningDetectiveServer.GetTeamAnswers:output_type -> crabs.evening_detective_server.GetTeamAnswersRsp - 203, // 283: crabs.evening_detective_server.EveningDetectiveServer.SubmitTeamAnswers:output_type -> crabs.evening_detective_server.SubmitTeamAnswersRsp - 205, // 284: crabs.evening_detective_server.EveningDetectiveServer.SetTeamAnswerScore:output_type -> crabs.evening_detective_server.SetTeamAnswerScoreRsp - 187, // [187:285] is the sub-list for method output_type - 89, // [89:187] is the sub-list for method input_type - 89, // [89:89] is the sub-list for extension type_name - 89, // [89:89] is the sub-list for extension extendee - 0, // [0:89] is the sub-list for field type_name + 228, // 87: crabs.evening_detective_server.TicketPage.start_at:type_name -> google.protobuf.Timestamp + 228, // 88: crabs.evening_detective_server.TicketPage.used_at:type_name -> google.protobuf.Timestamp + 228, // 89: crabs.evening_detective_server.DeveloperTask.createdAt:type_name -> google.protobuf.Timestamp + 228, // 90: crabs.evening_detective_server.DeveloperTask.updatedAt:type_name -> google.protobuf.Timestamp + 216, // 91: crabs.evening_detective_server.GetTasksRsp.tasks:type_name -> crabs.evening_detective_server.DeveloperTask + 217, // 92: crabs.evening_detective_server.GetTaskAssigneesRsp.assignees:type_name -> crabs.evening_detective_server.TaskAssignee + 216, // 93: crabs.evening_detective_server.TaskRsp.task:type_name -> crabs.evening_detective_server.DeveloperTask + 218, // 94: crabs.evening_detective_server.EveningDetectiveServer.GetTasks:input_type -> crabs.evening_detective_server.GetTasksReq + 220, // 95: crabs.evening_detective_server.EveningDetectiveServer.GetTaskAssignees:input_type -> crabs.evening_detective_server.GetTaskAssigneesReq + 222, // 96: crabs.evening_detective_server.EveningDetectiveServer.CreateTask:input_type -> crabs.evening_detective_server.CreateTaskReq + 223, // 97: crabs.evening_detective_server.EveningDetectiveServer.UpdateTask:input_type -> crabs.evening_detective_server.UpdateTaskReq + 224, // 98: crabs.evening_detective_server.EveningDetectiveServer.SetTaskStatus:input_type -> crabs.evening_detective_server.SetTaskStatusReq + 225, // 99: crabs.evening_detective_server.EveningDetectiveServer.DeleteTask:input_type -> crabs.evening_detective_server.DeleteTaskReq + 150, // 100: crabs.evening_detective_server.EveningDetectiveServer.GetParticipation:input_type -> crabs.evening_detective_server.GetParticipationReq + 151, // 101: crabs.evening_detective_server.EveningDetectiveServer.AnswerParticipation:input_type -> crabs.evening_detective_server.AnswerParticipationReq + 4, // 102: crabs.evening_detective_server.EveningDetectiveServer.Ping:input_type -> crabs.evening_detective_server.PingReq + 6, // 103: crabs.evening_detective_server.EveningDetectiveServer.Echo:input_type -> crabs.evening_detective_server.EchoReq + 8, // 104: crabs.evening_detective_server.EveningDetectiveServer.Signup:input_type -> crabs.evening_detective_server.SignupReq + 10, // 105: crabs.evening_detective_server.EveningDetectiveServer.RefreshPassword:input_type -> crabs.evening_detective_server.RefreshPasswordReq + 12, // 106: crabs.evening_detective_server.EveningDetectiveServer.Login:input_type -> crabs.evening_detective_server.LoginReq + 14, // 107: crabs.evening_detective_server.EveningDetectiveServer.Refresh:input_type -> crabs.evening_detective_server.RefreshReq + 16, // 108: crabs.evening_detective_server.EveningDetectiveServer.DeleteAccount:input_type -> crabs.evening_detective_server.DeleteAccountReq + 18, // 109: crabs.evening_detective_server.EveningDetectiveServer.GetTerms:input_type -> crabs.evening_detective_server.GetTermsReq + 20, // 110: crabs.evening_detective_server.EveningDetectiveServer.GetPrivacy:input_type -> crabs.evening_detective_server.GetPrivacyReq + 22, // 111: crabs.evening_detective_server.EveningDetectiveServer.GetConsent:input_type -> crabs.evening_detective_server.GetConsentReq + 24, // 112: crabs.evening_detective_server.EveningDetectiveServer.GetUsers:input_type -> crabs.evening_detective_server.GetUsersReq + 27, // 113: crabs.evening_detective_server.EveningDetectiveServer.GetUserByID:input_type -> crabs.evening_detective_server.GetUserByIDReq + 29, // 114: crabs.evening_detective_server.EveningDetectiveServer.GetMe:input_type -> crabs.evening_detective_server.GetMeReq + 31, // 115: crabs.evening_detective_server.EveningDetectiveServer.ChangeUserPassword:input_type -> crabs.evening_detective_server.ChangeUserPasswordReq + 33, // 116: crabs.evening_detective_server.EveningDetectiveServer.AddUserRole:input_type -> crabs.evening_detective_server.AddUserRoleReq + 35, // 117: crabs.evening_detective_server.EveningDetectiveServer.DeleteUserRole:input_type -> crabs.evening_detective_server.DeleteUserRoleReq + 37, // 118: crabs.evening_detective_server.EveningDetectiveServer.GetPermissions:input_type -> crabs.evening_detective_server.GetPermissionsReq + 39, // 119: crabs.evening_detective_server.EveningDetectiveServer.UploadFile:input_type -> crabs.evening_detective_server.UploadFileReq + 41, // 120: crabs.evening_detective_server.EveningDetectiveServer.DownloadFile:input_type -> crabs.evening_detective_server.DownloadFileReq + 44, // 121: crabs.evening_detective_server.EveningDetectiveServer.GetPlaylists:input_type -> crabs.evening_detective_server.GetPlaylistsReq + 46, // 122: crabs.evening_detective_server.EveningDetectiveServer.CreatePlaylist:input_type -> crabs.evening_detective_server.CreatePlaylistReq + 48, // 123: crabs.evening_detective_server.EveningDetectiveServer.UpdatePlaylist:input_type -> crabs.evening_detective_server.UpdatePlaylistReq + 50, // 124: crabs.evening_detective_server.EveningDetectiveServer.DeletePlaylist:input_type -> crabs.evening_detective_server.DeletePlaylistReq + 52, // 125: crabs.evening_detective_server.EveningDetectiveServer.UploadPlaylistTrack:input_type -> crabs.evening_detective_server.UploadPlaylistTrackReq + 54, // 126: crabs.evening_detective_server.EveningDetectiveServer.DeletePlaylistTrack:input_type -> crabs.evening_detective_server.DeletePlaylistTrackReq + 56, // 127: crabs.evening_detective_server.EveningDetectiveServer.SetScenarioPlaylist:input_type -> crabs.evening_detective_server.SetScenarioPlaylistReq + 58, // 128: crabs.evening_detective_server.EveningDetectiveServer.AddScenario:input_type -> crabs.evening_detective_server.AddScenarioReq + 60, // 129: crabs.evening_detective_server.EveningDetectiveServer.GetMyScenarios:input_type -> crabs.evening_detective_server.GetMyScenariosReq + 62, // 130: crabs.evening_detective_server.EveningDetectiveServer.GetScenariosCatalog:input_type -> crabs.evening_detective_server.GetScenariosCatalogReq + 64, // 131: crabs.evening_detective_server.EveningDetectiveServer.GetFullScenario:input_type -> crabs.evening_detective_server.GetScenarioReq + 64, // 132: crabs.evening_detective_server.EveningDetectiveServer.GetScenario:input_type -> crabs.evening_detective_server.GetScenarioReq + 78, // 133: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenario:input_type -> crabs.evening_detective_server.UpdateScenarioReq + 80, // 134: crabs.evening_detective_server.EveningDetectiveServer.PublicScenario:input_type -> crabs.evening_detective_server.PublicScenarioReq + 82, // 135: crabs.evening_detective_server.EveningDetectiveServer.DraftScenario:input_type -> crabs.evening_detective_server.DraftScenarioReq + 84, // 136: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenario:input_type -> crabs.evening_detective_server.DeleteScenarioReq + 86, // 137: crabs.evening_detective_server.EveningDetectiveServer.AddScenarioPlace:input_type -> crabs.evening_detective_server.AddScenarioPlaceReq + 88, // 138: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioPlace:input_type -> crabs.evening_detective_server.UpdateScenarioPlaceReq + 90, // 139: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenarioPlace:input_type -> crabs.evening_detective_server.DeleteScenarioPlaceReq + 96, // 140: crabs.evening_detective_server.EveningDetectiveServer.AddScenarioQuestion:input_type -> crabs.evening_detective_server.AddScenarioQuestionReq + 98, // 141: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioQuestion:input_type -> crabs.evening_detective_server.UpdateScenarioQuestionReq + 100, // 142: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenarioQuestion:input_type -> crabs.evening_detective_server.DeleteScenarioQuestionReq + 206, // 143: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioBackground:input_type -> crabs.evening_detective_server.UpdateScenarioBackgroundReq + 94, // 144: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioIntro:input_type -> crabs.evening_detective_server.UpdateScenarioIntroReq + 92, // 145: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioConclusion:input_type -> crabs.evening_detective_server.UpdateScenarioConclusionReq + 102, // 146: crabs.evening_detective_server.EveningDetectiveServer.DownloadScenarioArchive:input_type -> crabs.evening_detective_server.DownloadScenarioArchiveReq + 229, // 147: crabs.evening_detective_server.EveningDetectiveServer.UploadScenarioArchive:input_type -> google.api.HttpBody + 104, // 148: crabs.evening_detective_server.EveningDetectiveServer.AddGame:input_type -> crabs.evening_detective_server.AddGameReq + 106, // 149: crabs.evening_detective_server.EveningDetectiveServer.GetGames:input_type -> crabs.evening_detective_server.GetGamesReq + 154, // 150: crabs.evening_detective_server.EveningDetectiveServer.GetGame:input_type -> crabs.evening_detective_server.GetGameReq + 208, // 151: crabs.evening_detective_server.EveningDetectiveServer.IssueGameTickets:input_type -> crabs.evening_detective_server.IssueGameTicketsReq + 211, // 152: crabs.evening_detective_server.EveningDetectiveServer.GetTicket:input_type -> crabs.evening_detective_server.GetTicketReq + 213, // 153: crabs.evening_detective_server.EveningDetectiveServer.AcceptTicket:input_type -> crabs.evening_detective_server.AcceptTicketReq + 110, // 154: crabs.evening_detective_server.EveningDetectiveServer.CreateScreenSession:input_type -> crabs.evening_detective_server.CreateScreenSessionReq + 112, // 155: crabs.evening_detective_server.EveningDetectiveServer.GetScreenState:input_type -> crabs.evening_detective_server.GetScreenStateReq + 114, // 156: crabs.evening_detective_server.EveningDetectiveServer.GetGameScreens:input_type -> crabs.evening_detective_server.GetGameScreensReq + 117, // 157: crabs.evening_detective_server.EveningDetectiveServer.GetGameMusic:input_type -> crabs.evening_detective_server.GetGameMusicReq + 119, // 158: crabs.evening_detective_server.EveningDetectiveServer.SetGameMusic:input_type -> crabs.evening_detective_server.SetGameMusicReq + 121, // 159: crabs.evening_detective_server.EveningDetectiveServer.AdvanceScreenMusic:input_type -> crabs.evening_detective_server.AdvanceScreenMusicReq + 123, // 160: crabs.evening_detective_server.EveningDetectiveServer.BindScreen:input_type -> crabs.evening_detective_server.BindScreenReq + 125, // 161: crabs.evening_detective_server.EveningDetectiveServer.UnbindScreen:input_type -> crabs.evening_detective_server.UnbindScreenReq + 127, // 162: crabs.evening_detective_server.EveningDetectiveServer.SetScreenSound:input_type -> crabs.evening_detective_server.SetScreenSoundReq + 130, // 163: crabs.evening_detective_server.EveningDetectiveServer.GetGameMap:input_type -> crabs.evening_detective_server.GetGameMapReq + 132, // 164: crabs.evening_detective_server.EveningDetectiveServer.UpdateGameMapItem:input_type -> crabs.evening_detective_server.UpdateGameMapItemReq + 134, // 165: crabs.evening_detective_server.EveningDetectiveServer.SetScreenMode:input_type -> crabs.evening_detective_server.SetScreenModeReq + 136, // 166: crabs.evening_detective_server.EveningDetectiveServer.SetScreenTimer:input_type -> crabs.evening_detective_server.SetScreenTimerReq + 138, // 167: crabs.evening_detective_server.EveningDetectiveServer.SendScreenCommand:input_type -> crabs.evening_detective_server.SendScreenCommandReq + 142, // 168: crabs.evening_detective_server.EveningDetectiveServer.GetScreenPlan:input_type -> crabs.evening_detective_server.GetScreenPlanReq + 144, // 169: crabs.evening_detective_server.EveningDetectiveServer.SaveScreenPlan:input_type -> crabs.evening_detective_server.SaveScreenPlanReq + 146, // 170: crabs.evening_detective_server.EveningDetectiveServer.SetScreenPlanStep:input_type -> crabs.evening_detective_server.SetScreenPlanStepReq + 148, // 171: crabs.evening_detective_server.EveningDetectiveServer.GetScreenResults:input_type -> crabs.evening_detective_server.GetScreenResultsReq + 154, // 172: crabs.evening_detective_server.EveningDetectiveServer.DownloadTeamQR:input_type -> crabs.evening_detective_server.GetGameReq + 156, // 173: crabs.evening_detective_server.EveningDetectiveServer.GetGameAnswers:input_type -> crabs.evening_detective_server.GetGameAnswersReq + 158, // 174: crabs.evening_detective_server.EveningDetectiveServer.GetGameResults:input_type -> crabs.evening_detective_server.GetGameResultsReq + 163, // 175: crabs.evening_detective_server.EveningDetectiveServer.CreateGameReview:input_type -> crabs.evening_detective_server.CreateGameReviewReq + 165, // 176: crabs.evening_detective_server.EveningDetectiveServer.GetGameReviews:input_type -> crabs.evening_detective_server.GetGameReviewsReq + 166, // 177: crabs.evening_detective_server.EveningDetectiveServer.GetScenarioReviews:input_type -> crabs.evening_detective_server.GetScenarioReviewsReq + 165, // 178: crabs.evening_detective_server.EveningDetectiveServer.GetGameReviewsForModeration:input_type -> crabs.evening_detective_server.GetGameReviewsReq + 167, // 179: crabs.evening_detective_server.EveningDetectiveServer.GetReviewsForModeration:input_type -> crabs.evening_detective_server.GetReviewsForModerationReq + 169, // 180: crabs.evening_detective_server.EveningDetectiveServer.ModerateGameReview:input_type -> crabs.evening_detective_server.ModerateGameReviewReq + 171, // 181: crabs.evening_detective_server.EveningDetectiveServer.UpdateGame:input_type -> crabs.evening_detective_server.UpdateGameReq + 173, // 182: crabs.evening_detective_server.EveningDetectiveServer.StartGame:input_type -> crabs.evening_detective_server.StartGameReq + 175, // 183: crabs.evening_detective_server.EveningDetectiveServer.PauseGame:input_type -> crabs.evening_detective_server.PauseGameReq + 177, // 184: crabs.evening_detective_server.EveningDetectiveServer.PlayGame:input_type -> crabs.evening_detective_server.PlayGameReq + 179, // 185: crabs.evening_detective_server.EveningDetectiveServer.FinishGame:input_type -> crabs.evening_detective_server.FinishGameReq + 181, // 186: crabs.evening_detective_server.EveningDetectiveServer.ResetGame:input_type -> crabs.evening_detective_server.ResetGameReq + 183, // 187: crabs.evening_detective_server.EveningDetectiveServer.DeleteGame:input_type -> crabs.evening_detective_server.DeleteGameReq + 185, // 188: crabs.evening_detective_server.EveningDetectiveServer.AddTeam:input_type -> crabs.evening_detective_server.AddTeamReq + 187, // 189: crabs.evening_detective_server.EveningDetectiveServer.UpdateTeam:input_type -> crabs.evening_detective_server.UpdateTeamReq + 189, // 190: crabs.evening_detective_server.EveningDetectiveServer.DeleteTeam:input_type -> crabs.evening_detective_server.DeleteTeamReq + 191, // 191: crabs.evening_detective_server.EveningDetectiveServer.GiveTeamApplications:input_type -> crabs.evening_detective_server.GiveTeamApplicationsReq + 193, // 192: crabs.evening_detective_server.EveningDetectiveServer.GetTeamStory:input_type -> crabs.evening_detective_server.GetTeamStoryReq + 196, // 193: crabs.evening_detective_server.EveningDetectiveServer.AddTeamAction:input_type -> crabs.evening_detective_server.AddTeamActionReq + 198, // 194: crabs.evening_detective_server.EveningDetectiveServer.DeleteLastTeamAction:input_type -> crabs.evening_detective_server.DeleteLastTeamActionReq + 200, // 195: crabs.evening_detective_server.EveningDetectiveServer.GetTeamAnswers:input_type -> crabs.evening_detective_server.GetTeamAnswersReq + 202, // 196: crabs.evening_detective_server.EveningDetectiveServer.SubmitTeamAnswers:input_type -> crabs.evening_detective_server.SubmitTeamAnswersReq + 204, // 197: crabs.evening_detective_server.EveningDetectiveServer.SetTeamAnswerScore:input_type -> crabs.evening_detective_server.SetTeamAnswerScoreReq + 219, // 198: crabs.evening_detective_server.EveningDetectiveServer.GetTasks:output_type -> crabs.evening_detective_server.GetTasksRsp + 221, // 199: crabs.evening_detective_server.EveningDetectiveServer.GetTaskAssignees:output_type -> crabs.evening_detective_server.GetTaskAssigneesRsp + 226, // 200: crabs.evening_detective_server.EveningDetectiveServer.CreateTask:output_type -> crabs.evening_detective_server.TaskRsp + 226, // 201: crabs.evening_detective_server.EveningDetectiveServer.UpdateTask:output_type -> crabs.evening_detective_server.TaskRsp + 226, // 202: crabs.evening_detective_server.EveningDetectiveServer.SetTaskStatus:output_type -> crabs.evening_detective_server.TaskRsp + 227, // 203: crabs.evening_detective_server.EveningDetectiveServer.DeleteTask:output_type -> crabs.evening_detective_server.DeleteTaskRsp + 152, // 204: crabs.evening_detective_server.EveningDetectiveServer.GetParticipation:output_type -> crabs.evening_detective_server.ParticipationRsp + 152, // 205: crabs.evening_detective_server.EveningDetectiveServer.AnswerParticipation:output_type -> crabs.evening_detective_server.ParticipationRsp + 5, // 206: crabs.evening_detective_server.EveningDetectiveServer.Ping:output_type -> crabs.evening_detective_server.PingRsp + 7, // 207: crabs.evening_detective_server.EveningDetectiveServer.Echo:output_type -> crabs.evening_detective_server.EchoRsp + 9, // 208: crabs.evening_detective_server.EveningDetectiveServer.Signup:output_type -> crabs.evening_detective_server.SignupRsp + 11, // 209: crabs.evening_detective_server.EveningDetectiveServer.RefreshPassword:output_type -> crabs.evening_detective_server.RefreshPasswordRsp + 13, // 210: crabs.evening_detective_server.EveningDetectiveServer.Login:output_type -> crabs.evening_detective_server.LoginRsp + 15, // 211: crabs.evening_detective_server.EveningDetectiveServer.Refresh:output_type -> crabs.evening_detective_server.RefreshRsp + 17, // 212: crabs.evening_detective_server.EveningDetectiveServer.DeleteAccount:output_type -> crabs.evening_detective_server.DeleteAccountRsp + 19, // 213: crabs.evening_detective_server.EveningDetectiveServer.GetTerms:output_type -> crabs.evening_detective_server.GetTermsRsp + 21, // 214: crabs.evening_detective_server.EveningDetectiveServer.GetPrivacy:output_type -> crabs.evening_detective_server.GetPrivacyRsp + 23, // 215: crabs.evening_detective_server.EveningDetectiveServer.GetConsent:output_type -> crabs.evening_detective_server.GetConsentRsp + 25, // 216: crabs.evening_detective_server.EveningDetectiveServer.GetUsers:output_type -> crabs.evening_detective_server.GetUsersRsp + 28, // 217: crabs.evening_detective_server.EveningDetectiveServer.GetUserByID:output_type -> crabs.evening_detective_server.GetUserByIDRsp + 30, // 218: crabs.evening_detective_server.EveningDetectiveServer.GetMe:output_type -> crabs.evening_detective_server.GetMeRsp + 32, // 219: crabs.evening_detective_server.EveningDetectiveServer.ChangeUserPassword:output_type -> crabs.evening_detective_server.ChangeUserPasswordRsp + 34, // 220: crabs.evening_detective_server.EveningDetectiveServer.AddUserRole:output_type -> crabs.evening_detective_server.AddUserRoleRsp + 36, // 221: crabs.evening_detective_server.EveningDetectiveServer.DeleteUserRole:output_type -> crabs.evening_detective_server.DeleteUserRoleRsp + 38, // 222: crabs.evening_detective_server.EveningDetectiveServer.GetPermissions:output_type -> crabs.evening_detective_server.GetPermissionsRsp + 40, // 223: crabs.evening_detective_server.EveningDetectiveServer.UploadFile:output_type -> crabs.evening_detective_server.UploadFileRsp + 229, // 224: crabs.evening_detective_server.EveningDetectiveServer.DownloadFile:output_type -> google.api.HttpBody + 45, // 225: crabs.evening_detective_server.EveningDetectiveServer.GetPlaylists:output_type -> crabs.evening_detective_server.GetPlaylistsRsp + 47, // 226: crabs.evening_detective_server.EveningDetectiveServer.CreatePlaylist:output_type -> crabs.evening_detective_server.CreatePlaylistRsp + 49, // 227: crabs.evening_detective_server.EveningDetectiveServer.UpdatePlaylist:output_type -> crabs.evening_detective_server.UpdatePlaylistRsp + 51, // 228: crabs.evening_detective_server.EveningDetectiveServer.DeletePlaylist:output_type -> crabs.evening_detective_server.DeletePlaylistRsp + 53, // 229: crabs.evening_detective_server.EveningDetectiveServer.UploadPlaylistTrack:output_type -> crabs.evening_detective_server.UploadPlaylistTrackRsp + 55, // 230: crabs.evening_detective_server.EveningDetectiveServer.DeletePlaylistTrack:output_type -> crabs.evening_detective_server.DeletePlaylistTrackRsp + 57, // 231: crabs.evening_detective_server.EveningDetectiveServer.SetScenarioPlaylist:output_type -> crabs.evening_detective_server.SetScenarioPlaylistRsp + 59, // 232: crabs.evening_detective_server.EveningDetectiveServer.AddScenario:output_type -> crabs.evening_detective_server.AddScenarioRsp + 61, // 233: crabs.evening_detective_server.EveningDetectiveServer.GetMyScenarios:output_type -> crabs.evening_detective_server.GetMyScenariosRsp + 63, // 234: crabs.evening_detective_server.EveningDetectiveServer.GetScenariosCatalog:output_type -> crabs.evening_detective_server.GetScenariosCatalogRsp + 65, // 235: crabs.evening_detective_server.EveningDetectiveServer.GetFullScenario:output_type -> crabs.evening_detective_server.GetScenarioRsp + 65, // 236: crabs.evening_detective_server.EveningDetectiveServer.GetScenario:output_type -> crabs.evening_detective_server.GetScenarioRsp + 79, // 237: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenario:output_type -> crabs.evening_detective_server.UpdateScenarioRsp + 81, // 238: crabs.evening_detective_server.EveningDetectiveServer.PublicScenario:output_type -> crabs.evening_detective_server.PublicScenarioRsp + 83, // 239: crabs.evening_detective_server.EveningDetectiveServer.DraftScenario:output_type -> crabs.evening_detective_server.DraftScenarioRsp + 85, // 240: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenario:output_type -> crabs.evening_detective_server.DeleteScenarioRsp + 87, // 241: crabs.evening_detective_server.EveningDetectiveServer.AddScenarioPlace:output_type -> crabs.evening_detective_server.AddScenarioPlaceRsp + 89, // 242: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioPlace:output_type -> crabs.evening_detective_server.UpdateScenarioPlaceRsp + 91, // 243: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenarioPlace:output_type -> crabs.evening_detective_server.DeleteScenarioPlaceRsp + 97, // 244: crabs.evening_detective_server.EveningDetectiveServer.AddScenarioQuestion:output_type -> crabs.evening_detective_server.AddScenarioQuestionRsp + 99, // 245: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioQuestion:output_type -> crabs.evening_detective_server.UpdateScenarioQuestionRsp + 101, // 246: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenarioQuestion:output_type -> crabs.evening_detective_server.DeleteScenarioQuestionRsp + 207, // 247: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioBackground:output_type -> crabs.evening_detective_server.UpdateScenarioBackgroundRsp + 95, // 248: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioIntro:output_type -> crabs.evening_detective_server.UpdateScenarioIntroRsp + 93, // 249: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioConclusion:output_type -> crabs.evening_detective_server.UpdateScenarioConclusionRsp + 229, // 250: crabs.evening_detective_server.EveningDetectiveServer.DownloadScenarioArchive:output_type -> google.api.HttpBody + 103, // 251: crabs.evening_detective_server.EveningDetectiveServer.UploadScenarioArchive:output_type -> crabs.evening_detective_server.UploadScenarioArchiveRsp + 105, // 252: crabs.evening_detective_server.EveningDetectiveServer.AddGame:output_type -> crabs.evening_detective_server.AddGameRsp + 107, // 253: crabs.evening_detective_server.EveningDetectiveServer.GetGames:output_type -> crabs.evening_detective_server.GetGamesRsp + 155, // 254: crabs.evening_detective_server.EveningDetectiveServer.GetGame:output_type -> crabs.evening_detective_server.GetGameRsp + 209, // 255: crabs.evening_detective_server.EveningDetectiveServer.IssueGameTickets:output_type -> crabs.evening_detective_server.IssueGameTicketsRsp + 212, // 256: crabs.evening_detective_server.EveningDetectiveServer.GetTicket:output_type -> crabs.evening_detective_server.GetTicketRsp + 214, // 257: crabs.evening_detective_server.EveningDetectiveServer.AcceptTicket:output_type -> crabs.evening_detective_server.AcceptTicketRsp + 111, // 258: crabs.evening_detective_server.EveningDetectiveServer.CreateScreenSession:output_type -> crabs.evening_detective_server.CreateScreenSessionRsp + 113, // 259: crabs.evening_detective_server.EveningDetectiveServer.GetScreenState:output_type -> crabs.evening_detective_server.GetScreenStateRsp + 115, // 260: crabs.evening_detective_server.EveningDetectiveServer.GetGameScreens:output_type -> crabs.evening_detective_server.GetGameScreensRsp + 118, // 261: crabs.evening_detective_server.EveningDetectiveServer.GetGameMusic:output_type -> crabs.evening_detective_server.GetGameMusicRsp + 120, // 262: crabs.evening_detective_server.EveningDetectiveServer.SetGameMusic:output_type -> crabs.evening_detective_server.SetGameMusicRsp + 122, // 263: crabs.evening_detective_server.EveningDetectiveServer.AdvanceScreenMusic:output_type -> crabs.evening_detective_server.AdvanceScreenMusicRsp + 124, // 264: crabs.evening_detective_server.EveningDetectiveServer.BindScreen:output_type -> crabs.evening_detective_server.BindScreenRsp + 126, // 265: crabs.evening_detective_server.EveningDetectiveServer.UnbindScreen:output_type -> crabs.evening_detective_server.UnbindScreenRsp + 128, // 266: crabs.evening_detective_server.EveningDetectiveServer.SetScreenSound:output_type -> crabs.evening_detective_server.SetScreenSoundRsp + 131, // 267: crabs.evening_detective_server.EveningDetectiveServer.GetGameMap:output_type -> crabs.evening_detective_server.GetGameMapRsp + 133, // 268: crabs.evening_detective_server.EveningDetectiveServer.UpdateGameMapItem:output_type -> crabs.evening_detective_server.UpdateGameMapItemRsp + 135, // 269: crabs.evening_detective_server.EveningDetectiveServer.SetScreenMode:output_type -> crabs.evening_detective_server.SetScreenModeRsp + 137, // 270: crabs.evening_detective_server.EveningDetectiveServer.SetScreenTimer:output_type -> crabs.evening_detective_server.SetScreenTimerRsp + 139, // 271: crabs.evening_detective_server.EveningDetectiveServer.SendScreenCommand:output_type -> crabs.evening_detective_server.SendScreenCommandRsp + 143, // 272: crabs.evening_detective_server.EveningDetectiveServer.GetScreenPlan:output_type -> crabs.evening_detective_server.GetScreenPlanRsp + 145, // 273: crabs.evening_detective_server.EveningDetectiveServer.SaveScreenPlan:output_type -> crabs.evening_detective_server.SaveScreenPlanRsp + 147, // 274: crabs.evening_detective_server.EveningDetectiveServer.SetScreenPlanStep:output_type -> crabs.evening_detective_server.SetScreenPlanStepRsp + 149, // 275: crabs.evening_detective_server.EveningDetectiveServer.GetScreenResults:output_type -> crabs.evening_detective_server.GetScreenResultsRsp + 229, // 276: crabs.evening_detective_server.EveningDetectiveServer.DownloadTeamQR:output_type -> google.api.HttpBody + 157, // 277: crabs.evening_detective_server.EveningDetectiveServer.GetGameAnswers:output_type -> crabs.evening_detective_server.GetGameAnswersRsp + 161, // 278: crabs.evening_detective_server.EveningDetectiveServer.GetGameResults:output_type -> crabs.evening_detective_server.GetGameResultsRsp + 164, // 279: crabs.evening_detective_server.EveningDetectiveServer.CreateGameReview:output_type -> crabs.evening_detective_server.CreateGameReviewRsp + 168, // 280: crabs.evening_detective_server.EveningDetectiveServer.GetGameReviews:output_type -> crabs.evening_detective_server.GetGameReviewsRsp + 168, // 281: crabs.evening_detective_server.EveningDetectiveServer.GetScenarioReviews:output_type -> crabs.evening_detective_server.GetGameReviewsRsp + 168, // 282: crabs.evening_detective_server.EveningDetectiveServer.GetGameReviewsForModeration:output_type -> crabs.evening_detective_server.GetGameReviewsRsp + 168, // 283: crabs.evening_detective_server.EveningDetectiveServer.GetReviewsForModeration:output_type -> crabs.evening_detective_server.GetGameReviewsRsp + 170, // 284: crabs.evening_detective_server.EveningDetectiveServer.ModerateGameReview:output_type -> crabs.evening_detective_server.ModerateGameReviewRsp + 172, // 285: crabs.evening_detective_server.EveningDetectiveServer.UpdateGame:output_type -> crabs.evening_detective_server.UpdateGameRsp + 174, // 286: crabs.evening_detective_server.EveningDetectiveServer.StartGame:output_type -> crabs.evening_detective_server.StartGameRsp + 176, // 287: crabs.evening_detective_server.EveningDetectiveServer.PauseGame:output_type -> crabs.evening_detective_server.PauseGameRsp + 178, // 288: crabs.evening_detective_server.EveningDetectiveServer.PlayGame:output_type -> crabs.evening_detective_server.PlayGameRsp + 180, // 289: crabs.evening_detective_server.EveningDetectiveServer.FinishGame:output_type -> crabs.evening_detective_server.FinishGameRsp + 182, // 290: crabs.evening_detective_server.EveningDetectiveServer.ResetGame:output_type -> crabs.evening_detective_server.ResetGameRsp + 184, // 291: crabs.evening_detective_server.EveningDetectiveServer.DeleteGame:output_type -> crabs.evening_detective_server.DeleteGameRsp + 186, // 292: crabs.evening_detective_server.EveningDetectiveServer.AddTeam:output_type -> crabs.evening_detective_server.AddTeamRsp + 188, // 293: crabs.evening_detective_server.EveningDetectiveServer.UpdateTeam:output_type -> crabs.evening_detective_server.UpdateTeamRsp + 190, // 294: crabs.evening_detective_server.EveningDetectiveServer.DeleteTeam:output_type -> crabs.evening_detective_server.DeleteTeamRsp + 192, // 295: crabs.evening_detective_server.EveningDetectiveServer.GiveTeamApplications:output_type -> crabs.evening_detective_server.GiveTeamApplicationsRsp + 194, // 296: crabs.evening_detective_server.EveningDetectiveServer.GetTeamStory:output_type -> crabs.evening_detective_server.GetTeamStoryRsp + 197, // 297: crabs.evening_detective_server.EveningDetectiveServer.AddTeamAction:output_type -> crabs.evening_detective_server.AddTeamActionRsp + 199, // 298: crabs.evening_detective_server.EveningDetectiveServer.DeleteLastTeamAction:output_type -> crabs.evening_detective_server.DeleteLastTeamActionRsp + 201, // 299: crabs.evening_detective_server.EveningDetectiveServer.GetTeamAnswers:output_type -> crabs.evening_detective_server.GetTeamAnswersRsp + 203, // 300: crabs.evening_detective_server.EveningDetectiveServer.SubmitTeamAnswers:output_type -> crabs.evening_detective_server.SubmitTeamAnswersRsp + 205, // 301: crabs.evening_detective_server.EveningDetectiveServer.SetTeamAnswerScore:output_type -> crabs.evening_detective_server.SetTeamAnswerScoreRsp + 198, // [198:302] is the sub-list for method output_type + 94, // [94:198] is the sub-list for method input_type + 94, // [94:94] is the sub-list for extension type_name + 94, // [94:94] is the sub-list for extension extendee + 0, // [0:94] is the sub-list for field type_name } func init() { file_main_proto_init() } @@ -12576,13 +13378,16 @@ func file_main_proto_init() { file_main_proto_msgTypes[105].OneofWrappers = []any{} file_main_proto_msgTypes[200].OneofWrappers = []any{} file_main_proto_msgTypes[211].OneofWrappers = []any{} + file_main_proto_msgTypes[212].OneofWrappers = []any{} + file_main_proto_msgTypes[218].OneofWrappers = []any{} + file_main_proto_msgTypes[219].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_main_proto_rawDesc), len(file_main_proto_rawDesc)), NumEnums: 4, - NumMessages: 212, + NumMessages: 224, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/main.pb.gw.go b/proto/main.pb.gw.go index f8249bc..d9755fe 100644 --- a/proto/main.pb.gw.go +++ b/proto/main.pb.gw.go @@ -36,6 +36,210 @@ var ( _ = metadata.Join ) +func request_EveningDetectiveServer_GetTasks_0(ctx context.Context, marshaler runtime.Marshaler, client EveningDetectiveServerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetTasksReq + metadata runtime.ServerMetadata + ) + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + msg, err := client.GetTasks(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_EveningDetectiveServer_GetTasks_0(ctx context.Context, marshaler runtime.Marshaler, server EveningDetectiveServerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetTasksReq + metadata runtime.ServerMetadata + ) + msg, err := server.GetTasks(ctx, &protoReq) + return msg, metadata, err +} + +func request_EveningDetectiveServer_GetTaskAssignees_0(ctx context.Context, marshaler runtime.Marshaler, client EveningDetectiveServerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetTaskAssigneesReq + metadata runtime.ServerMetadata + ) + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + msg, err := client.GetTaskAssignees(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_EveningDetectiveServer_GetTaskAssignees_0(ctx context.Context, marshaler runtime.Marshaler, server EveningDetectiveServerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetTaskAssigneesReq + metadata runtime.ServerMetadata + ) + msg, err := server.GetTaskAssignees(ctx, &protoReq) + return msg, metadata, err +} + +func request_EveningDetectiveServer_CreateTask_0(ctx context.Context, marshaler runtime.Marshaler, client EveningDetectiveServerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq CreateTaskReq + 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.CreateTask(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_EveningDetectiveServer_CreateTask_0(ctx context.Context, marshaler runtime.Marshaler, server EveningDetectiveServerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq CreateTaskReq + 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.CreateTask(ctx, &protoReq) + return msg, metadata, err +} + +func request_EveningDetectiveServer_UpdateTask_0(ctx context.Context, marshaler runtime.Marshaler, client EveningDetectiveServerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq UpdateTaskReq + metadata runtime.ServerMetadata + err error + ) + 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) + } + val, ok := pathParams["ID"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "ID") + } + protoReq.ID, err = runtime.Int32(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "ID", err) + } + msg, err := client.UpdateTask(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_EveningDetectiveServer_UpdateTask_0(ctx context.Context, marshaler runtime.Marshaler, server EveningDetectiveServerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq UpdateTaskReq + metadata runtime.ServerMetadata + err error + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + val, ok := pathParams["ID"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "ID") + } + protoReq.ID, err = runtime.Int32(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "ID", err) + } + msg, err := server.UpdateTask(ctx, &protoReq) + return msg, metadata, err +} + +func request_EveningDetectiveServer_SetTaskStatus_0(ctx context.Context, marshaler runtime.Marshaler, client EveningDetectiveServerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq SetTaskStatusReq + metadata runtime.ServerMetadata + err error + ) + 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) + } + val, ok := pathParams["ID"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "ID") + } + protoReq.ID, err = runtime.Int32(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "ID", err) + } + msg, err := client.SetTaskStatus(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_EveningDetectiveServer_SetTaskStatus_0(ctx context.Context, marshaler runtime.Marshaler, server EveningDetectiveServerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq SetTaskStatusReq + metadata runtime.ServerMetadata + err error + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + val, ok := pathParams["ID"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "ID") + } + protoReq.ID, err = runtime.Int32(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "ID", err) + } + msg, err := server.SetTaskStatus(ctx, &protoReq) + return msg, metadata, err +} + +func request_EveningDetectiveServer_DeleteTask_0(ctx context.Context, marshaler runtime.Marshaler, client EveningDetectiveServerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq DeleteTaskReq + metadata runtime.ServerMetadata + err error + ) + 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) + } + val, ok := pathParams["ID"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "ID") + } + protoReq.ID, err = runtime.Int32(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "ID", err) + } + msg, err := client.DeleteTask(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_EveningDetectiveServer_DeleteTask_0(ctx context.Context, marshaler runtime.Marshaler, server EveningDetectiveServerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq DeleteTaskReq + metadata runtime.ServerMetadata + err error + ) + if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && !errors.Is(err, io.EOF) { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + val, ok := pathParams["ID"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "ID") + } + protoReq.ID, err = runtime.Int32(val) + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "ID", err) + } + msg, err := server.DeleteTask(ctx, &protoReq) + return msg, metadata, err +} + func request_EveningDetectiveServer_GetParticipation_0(ctx context.Context, marshaler runtime.Marshaler, client EveningDetectiveServerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var ( protoReq GetParticipationReq @@ -3836,6 +4040,126 @@ func local_request_EveningDetectiveServer_SetTeamAnswerScore_0(ctx context.Conte // Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterEveningDetectiveServerHandlerFromEndpoint instead. // GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call. func RegisterEveningDetectiveServerHandlerServer(ctx context.Context, mux *runtime.ServeMux, server EveningDetectiveServerServer) error { + mux.Handle(http.MethodGet, pattern_EveningDetectiveServer_GetTasks_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/GetTasks", runtime.WithHTTPPathPattern("/api/tasks")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_EveningDetectiveServer_GetTasks_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_GetTasks_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodGet, pattern_EveningDetectiveServer_GetTaskAssignees_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/GetTaskAssignees", runtime.WithHTTPPathPattern("/api/tasks/assignees")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_EveningDetectiveServer_GetTaskAssignees_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_GetTaskAssignees_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodPost, pattern_EveningDetectiveServer_CreateTask_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/CreateTask", runtime.WithHTTPPathPattern("/api/tasks")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_EveningDetectiveServer_CreateTask_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_CreateTask_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodPut, pattern_EveningDetectiveServer_UpdateTask_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/UpdateTask", runtime.WithHTTPPathPattern("/api/tasks/{ID}")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_EveningDetectiveServer_UpdateTask_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_UpdateTask_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodPost, pattern_EveningDetectiveServer_SetTaskStatus_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/SetTaskStatus", runtime.WithHTTPPathPattern("/api/tasks/{ID}/status")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_EveningDetectiveServer_SetTaskStatus_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_SetTaskStatus_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodPost, pattern_EveningDetectiveServer_DeleteTask_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/DeleteTask", runtime.WithHTTPPathPattern("/api/tasks/{ID}/delete")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_EveningDetectiveServer_DeleteTask_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_DeleteTask_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) mux.Handle(http.MethodPost, pattern_EveningDetectiveServer_GetParticipation_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -5836,6 +6160,108 @@ func RegisterEveningDetectiveServerHandler(ctx context.Context, mux *runtime.Ser // doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in // "EveningDetectiveServerClient" to call the correct interceptors. This client ignores the HTTP middlewares. func RegisterEveningDetectiveServerHandlerClient(ctx context.Context, mux *runtime.ServeMux, client EveningDetectiveServerClient) error { + mux.Handle(http.MethodGet, pattern_EveningDetectiveServer_GetTasks_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/GetTasks", runtime.WithHTTPPathPattern("/api/tasks")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_EveningDetectiveServer_GetTasks_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_GetTasks_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodGet, pattern_EveningDetectiveServer_GetTaskAssignees_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/GetTaskAssignees", runtime.WithHTTPPathPattern("/api/tasks/assignees")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_EveningDetectiveServer_GetTaskAssignees_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_GetTaskAssignees_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodPost, pattern_EveningDetectiveServer_CreateTask_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/CreateTask", runtime.WithHTTPPathPattern("/api/tasks")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_EveningDetectiveServer_CreateTask_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_CreateTask_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodPut, pattern_EveningDetectiveServer_UpdateTask_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/UpdateTask", runtime.WithHTTPPathPattern("/api/tasks/{ID}")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_EveningDetectiveServer_UpdateTask_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_UpdateTask_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodPost, pattern_EveningDetectiveServer_SetTaskStatus_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/SetTaskStatus", runtime.WithHTTPPathPattern("/api/tasks/{ID}/status")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_EveningDetectiveServer_SetTaskStatus_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_SetTaskStatus_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodPost, pattern_EveningDetectiveServer_DeleteTask_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/DeleteTask", runtime.WithHTTPPathPattern("/api/tasks/{ID}/delete")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_EveningDetectiveServer_DeleteTask_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_DeleteTask_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) mux.Handle(http.MethodPost, pattern_EveningDetectiveServer_GetParticipation_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -7506,6 +7932,12 @@ func RegisterEveningDetectiveServerHandlerClient(ctx context.Context, mux *runti } var ( + pattern_EveningDetectiveServer_GetTasks_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"api", "tasks"}, "")) + pattern_EveningDetectiveServer_GetTaskAssignees_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "tasks", "assignees"}, "")) + pattern_EveningDetectiveServer_CreateTask_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"api", "tasks"}, "")) + pattern_EveningDetectiveServer_UpdateTask_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"api", "tasks", "ID"}, "")) + pattern_EveningDetectiveServer_SetTaskStatus_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3}, []string{"api", "tasks", "ID", "status"}, "")) + pattern_EveningDetectiveServer_DeleteTask_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2, 2, 3}, []string{"api", "tasks", "ID", "delete"}, "")) pattern_EveningDetectiveServer_GetParticipation_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "participation", "get"}, "")) pattern_EveningDetectiveServer_AnswerParticipation_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "participation", "answer"}, "")) pattern_EveningDetectiveServer_Ping_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "test", "ping"}, "")) @@ -7607,6 +8039,12 @@ var ( ) var ( + forward_EveningDetectiveServer_GetTasks_0 = runtime.ForwardResponseMessage + forward_EveningDetectiveServer_GetTaskAssignees_0 = runtime.ForwardResponseMessage + forward_EveningDetectiveServer_CreateTask_0 = runtime.ForwardResponseMessage + forward_EveningDetectiveServer_UpdateTask_0 = runtime.ForwardResponseMessage + forward_EveningDetectiveServer_SetTaskStatus_0 = runtime.ForwardResponseMessage + forward_EveningDetectiveServer_DeleteTask_0 = runtime.ForwardResponseMessage forward_EveningDetectiveServer_GetParticipation_0 = runtime.ForwardResponseMessage forward_EveningDetectiveServer_AnswerParticipation_0 = runtime.ForwardResponseMessage forward_EveningDetectiveServer_Ping_0 = runtime.ForwardResponseMessage diff --git a/proto/main_grpc.pb.go b/proto/main_grpc.pb.go index 79f19e8..c811ab2 100644 --- a/proto/main_grpc.pb.go +++ b/proto/main_grpc.pb.go @@ -26,6 +26,12 @@ import ( const _ = grpc.SupportPackageIsVersion9 const ( + EveningDetectiveServer_GetTasks_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/GetTasks" + EveningDetectiveServer_GetTaskAssignees_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/GetTaskAssignees" + EveningDetectiveServer_CreateTask_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/CreateTask" + EveningDetectiveServer_UpdateTask_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/UpdateTask" + EveningDetectiveServer_SetTaskStatus_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/SetTaskStatus" + EveningDetectiveServer_DeleteTask_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/DeleteTask" EveningDetectiveServer_GetParticipation_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/GetParticipation" EveningDetectiveServer_AnswerParticipation_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/AnswerParticipation" EveningDetectiveServer_Ping_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/Ping" @@ -130,6 +136,12 @@ const ( // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type EveningDetectiveServerClient interface { + GetTasks(ctx context.Context, in *GetTasksReq, opts ...grpc.CallOption) (*GetTasksRsp, error) + GetTaskAssignees(ctx context.Context, in *GetTaskAssigneesReq, opts ...grpc.CallOption) (*GetTaskAssigneesRsp, error) + CreateTask(ctx context.Context, in *CreateTaskReq, opts ...grpc.CallOption) (*TaskRsp, error) + UpdateTask(ctx context.Context, in *UpdateTaskReq, opts ...grpc.CallOption) (*TaskRsp, error) + SetTaskStatus(ctx context.Context, in *SetTaskStatusReq, opts ...grpc.CallOption) (*TaskRsp, error) + DeleteTask(ctx context.Context, in *DeleteTaskReq, opts ...grpc.CallOption) (*DeleteTaskRsp, error) GetParticipation(ctx context.Context, in *GetParticipationReq, opts ...grpc.CallOption) (*ParticipationRsp, error) AnswerParticipation(ctx context.Context, in *AnswerParticipationReq, opts ...grpc.CallOption) (*ParticipationRsp, error) Ping(ctx context.Context, in *PingReq, opts ...grpc.CallOption) (*PingRsp, error) @@ -248,6 +260,66 @@ func NewEveningDetectiveServerClient(cc grpc.ClientConnInterface) EveningDetecti return &eveningDetectiveServerClient{cc} } +func (c *eveningDetectiveServerClient) GetTasks(ctx context.Context, in *GetTasksReq, opts ...grpc.CallOption) (*GetTasksRsp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetTasksRsp) + err := c.cc.Invoke(ctx, EveningDetectiveServer_GetTasks_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *eveningDetectiveServerClient) GetTaskAssignees(ctx context.Context, in *GetTaskAssigneesReq, opts ...grpc.CallOption) (*GetTaskAssigneesRsp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetTaskAssigneesRsp) + err := c.cc.Invoke(ctx, EveningDetectiveServer_GetTaskAssignees_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *eveningDetectiveServerClient) CreateTask(ctx context.Context, in *CreateTaskReq, opts ...grpc.CallOption) (*TaskRsp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(TaskRsp) + err := c.cc.Invoke(ctx, EveningDetectiveServer_CreateTask_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *eveningDetectiveServerClient) UpdateTask(ctx context.Context, in *UpdateTaskReq, opts ...grpc.CallOption) (*TaskRsp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(TaskRsp) + err := c.cc.Invoke(ctx, EveningDetectiveServer_UpdateTask_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *eveningDetectiveServerClient) SetTaskStatus(ctx context.Context, in *SetTaskStatusReq, opts ...grpc.CallOption) (*TaskRsp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(TaskRsp) + err := c.cc.Invoke(ctx, EveningDetectiveServer_SetTaskStatus_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *eveningDetectiveServerClient) DeleteTask(ctx context.Context, in *DeleteTaskReq, opts ...grpc.CallOption) (*DeleteTaskRsp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(DeleteTaskRsp) + err := c.cc.Invoke(ctx, EveningDetectiveServer_DeleteTask_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *eveningDetectiveServerClient) GetParticipation(ctx context.Context, in *GetParticipationReq, opts ...grpc.CallOption) (*ParticipationRsp, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ParticipationRsp) @@ -1232,6 +1304,12 @@ func (c *eveningDetectiveServerClient) SetTeamAnswerScore(ctx context.Context, i // All implementations must embed UnimplementedEveningDetectiveServerServer // for forward compatibility. type EveningDetectiveServerServer interface { + GetTasks(context.Context, *GetTasksReq) (*GetTasksRsp, error) + GetTaskAssignees(context.Context, *GetTaskAssigneesReq) (*GetTaskAssigneesRsp, error) + CreateTask(context.Context, *CreateTaskReq) (*TaskRsp, error) + UpdateTask(context.Context, *UpdateTaskReq) (*TaskRsp, error) + SetTaskStatus(context.Context, *SetTaskStatusReq) (*TaskRsp, error) + DeleteTask(context.Context, *DeleteTaskReq) (*DeleteTaskRsp, error) GetParticipation(context.Context, *GetParticipationReq) (*ParticipationRsp, error) AnswerParticipation(context.Context, *AnswerParticipationReq) (*ParticipationRsp, error) Ping(context.Context, *PingReq) (*PingRsp, error) @@ -1350,6 +1428,24 @@ type EveningDetectiveServerServer interface { // pointer dereference when methods are called. type UnimplementedEveningDetectiveServerServer struct{} +func (UnimplementedEveningDetectiveServerServer) GetTasks(context.Context, *GetTasksReq) (*GetTasksRsp, error) { + return nil, status.Error(codes.Unimplemented, "method GetTasks not implemented") +} +func (UnimplementedEveningDetectiveServerServer) GetTaskAssignees(context.Context, *GetTaskAssigneesReq) (*GetTaskAssigneesRsp, error) { + return nil, status.Error(codes.Unimplemented, "method GetTaskAssignees not implemented") +} +func (UnimplementedEveningDetectiveServerServer) CreateTask(context.Context, *CreateTaskReq) (*TaskRsp, error) { + return nil, status.Error(codes.Unimplemented, "method CreateTask not implemented") +} +func (UnimplementedEveningDetectiveServerServer) UpdateTask(context.Context, *UpdateTaskReq) (*TaskRsp, error) { + return nil, status.Error(codes.Unimplemented, "method UpdateTask not implemented") +} +func (UnimplementedEveningDetectiveServerServer) SetTaskStatus(context.Context, *SetTaskStatusReq) (*TaskRsp, error) { + return nil, status.Error(codes.Unimplemented, "method SetTaskStatus not implemented") +} +func (UnimplementedEveningDetectiveServerServer) DeleteTask(context.Context, *DeleteTaskReq) (*DeleteTaskRsp, error) { + return nil, status.Error(codes.Unimplemented, "method DeleteTask not implemented") +} func (UnimplementedEveningDetectiveServerServer) GetParticipation(context.Context, *GetParticipationReq) (*ParticipationRsp, error) { return nil, status.Error(codes.Unimplemented, "method GetParticipation not implemented") } @@ -1666,6 +1762,114 @@ func RegisterEveningDetectiveServerServer(s grpc.ServiceRegistrar, srv EveningDe s.RegisterService(&EveningDetectiveServer_ServiceDesc, srv) } +func _EveningDetectiveServer_GetTasks_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetTasksReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EveningDetectiveServerServer).GetTasks(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EveningDetectiveServer_GetTasks_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EveningDetectiveServerServer).GetTasks(ctx, req.(*GetTasksReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _EveningDetectiveServer_GetTaskAssignees_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetTaskAssigneesReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EveningDetectiveServerServer).GetTaskAssignees(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EveningDetectiveServer_GetTaskAssignees_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EveningDetectiveServerServer).GetTaskAssignees(ctx, req.(*GetTaskAssigneesReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _EveningDetectiveServer_CreateTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateTaskReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EveningDetectiveServerServer).CreateTask(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EveningDetectiveServer_CreateTask_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EveningDetectiveServerServer).CreateTask(ctx, req.(*CreateTaskReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _EveningDetectiveServer_UpdateTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateTaskReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EveningDetectiveServerServer).UpdateTask(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EveningDetectiveServer_UpdateTask_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EveningDetectiveServerServer).UpdateTask(ctx, req.(*UpdateTaskReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _EveningDetectiveServer_SetTaskStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(SetTaskStatusReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EveningDetectiveServerServer).SetTaskStatus(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EveningDetectiveServer_SetTaskStatus_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EveningDetectiveServerServer).SetTaskStatus(ctx, req.(*SetTaskStatusReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _EveningDetectiveServer_DeleteTask_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteTaskReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EveningDetectiveServerServer).DeleteTask(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EveningDetectiveServer_DeleteTask_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EveningDetectiveServerServer).DeleteTask(ctx, req.(*DeleteTaskReq)) + } + return interceptor(ctx, in, info, handler) +} + func _EveningDetectiveServer_GetParticipation_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetParticipationReq) if err := dec(in); err != nil { @@ -3437,6 +3641,30 @@ var EveningDetectiveServer_ServiceDesc = grpc.ServiceDesc{ ServiceName: "crabs.evening_detective_server.EveningDetectiveServer", HandlerType: (*EveningDetectiveServerServer)(nil), Methods: []grpc.MethodDesc{ + { + MethodName: "GetTasks", + Handler: _EveningDetectiveServer_GetTasks_Handler, + }, + { + MethodName: "GetTaskAssignees", + Handler: _EveningDetectiveServer_GetTaskAssignees_Handler, + }, + { + MethodName: "CreateTask", + Handler: _EveningDetectiveServer_CreateTask_Handler, + }, + { + MethodName: "UpdateTask", + Handler: _EveningDetectiveServer_UpdateTask_Handler, + }, + { + MethodName: "SetTaskStatus", + Handler: _EveningDetectiveServer_SetTaskStatus_Handler, + }, + { + MethodName: "DeleteTask", + Handler: _EveningDetectiveServer_DeleteTask_Handler, + }, { MethodName: "GetParticipation", Handler: _EveningDetectiveServer_GetParticipation_Handler,