From 204a20c814e74dea035b63809acc083365c89d32 Mon Sep 17 00:00:00 2001 From: Fedorov Vladimir Date: Wed, 19 Aug 2026 02:15:57 +0700 Subject: [PATCH] add docs --- README.md | 12 + api/main.proto | 80 +- cmd/evening_detective_server/main.go | 22 +- .../main.swagger.json | 140 ++ docs/COMPLIANCE.md | 123 ++ docs/CONSENT.md | 54 + docs/PRIVACY.md | 185 +++ docs/TERMS.md | 245 +++ docs/embed.go | 9 + docs/embed_test.go | 16 + internal/app/client_info_test.go | 96 ++ internal/app/legal_docs_test.go | 65 + internal/app/server.go | 146 +- internal/app/user_mapper.go | 6 + internal/app/user_mapper_test.go | 37 + internal/repos/scenarios_repo/repo.go | 84 +- internal/repos/user_agreements_repo/repo.go | 18 + internal/repos/users_repo/repo.go | 125 +- .../services/scenarios_service/service.go | 96 +- internal/services/users_service/service.go | 59 +- ...818231943_create_user_agreements_table.sql | 26 + ...0818232725_keep_content_on_user_delete.sql | 39 + proto/main.pb.go | 1317 +++++++++++------ proto/main.pb.gw.go | 240 +++ proto/main_grpc.pb.go | 152 ++ 25 files changed, 2892 insertions(+), 500 deletions(-) create mode 100644 docs/COMPLIANCE.md create mode 100644 docs/CONSENT.md create mode 100644 docs/PRIVACY.md create mode 100644 docs/TERMS.md create mode 100644 docs/embed.go create mode 100644 docs/embed_test.go create mode 100644 internal/app/client_info_test.go create mode 100644 internal/app/legal_docs_test.go create mode 100644 internal/app/user_mapper_test.go create mode 100644 internal/repos/user_agreements_repo/repo.go create mode 100644 migrations/20260818231943_create_user_agreements_table.sql create mode 100644 migrations/20260818232725_keep_content_on_user_delete.sql diff --git a/README.md b/README.md index b73d057..de973e0 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,18 @@ goose -dir ./migrations postgres "user=postgres password=postgres host=localhost make test ``` +## Документация и юридические документы + +- [`docs/TERMS.md`](docs/TERMS.md) — Пользовательское соглашение (оферта); раздаётся сервером по постоянному URL `/terms`; +- [`docs/PRIVACY.md`](docs/PRIVACY.md) — Политика конфиденциальности и обработки персональных данных (152-ФЗ); раздаётся сервером по постоянному URL `/privacy`; +- [`docs/CONSENT.md`](docs/CONSENT.md) — текст согласия на обработку ПДн для формы регистрации (URL `/consent`); +- [`docs/COMPLIANCE.md`](docs/COMPLIANCE.md) — чек-лист приведения сервиса в соответствие с документами. + +Юридические эндпоинты: + +- `POST /api/auth/signup` — регистрация; требует `accept_terms: true` и `accept_privacy: true` (факт акцепта фиксируется в таблице `user_agreements`); +- `DELETE /api/auth/delete-account` — удаление учётной записи и персональных данных (авторизован JWT, подтверждение паролем в HTTP-заголовке `X-Password`). + ## Агент «Юрист по ПО» (DSH) В каталоге [`agents/software-lawyer`](agents/software-lawyer) лежит агент-пресет для DeepSeek Harness: специализированный консультант по правовым вопросам разработки ПО (лицензии, авторские права, персональные данные 152-ФЗ/GDPR, договоры). Отвечает на основе встроенной базы знаний (`skills/software-law/references/`), без внешних API. diff --git a/api/main.proto b/api/main.proto index 7d7de0a..803b2f4 100644 --- a/api/main.proto +++ b/api/main.proto @@ -115,6 +115,47 @@ service EveningDetectiveServer { }; } + rpc DeleteAccount(DeleteAccountReq) returns (DeleteAccountRsp) { + option (google.api.http) = { + delete: "/api/auth/delete-account" + }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + tags : "Регистрация и вход"; + summary : "Удалить учётную запись и персональные данные"; + description: "Удаляет учётную запись и персональные данные текущего пользователя (ст. 21 152-ФЗ). Требует заголовок X-Password с паролем учётной записи (подтверждение владельца; пароль не передаётся в URL)."; + }; + } + + rpc GetTerms(GetTermsReq) returns (GetTermsRsp) { + option (google.api.http) = { + get: "/terms" + }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + tags : "Документы"; + summary: "Получить текст Пользовательского соглашения (оферты)"; + }; + } + + rpc GetPrivacy(GetPrivacyReq) returns (GetPrivacyRsp) { + option (google.api.http) = { + get: "/privacy" + }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + tags : "Документы"; + summary: "Получить текст Политики конфиденциальности"; + }; + } + + rpc GetConsent(GetConsentReq) returns (GetConsentRsp) { + option (google.api.http) = { + get: "/consent" + }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + tags : "Документы"; + summary: "Получить текст Согласия на обработку персональных данных"; + }; + } + rpc GetUsers(GetUsersReq) returns (GetUsersRsp) { option (google.api.http) = { get: "/api/users" @@ -525,8 +566,10 @@ message EchoRsp { } message SignupReq { - string username = 1; - string email = 2; + string username = 1; + string email = 2; + bool accept_terms = 3; + bool accept_privacy = 4; } message SignupRsp { @@ -562,6 +605,39 @@ message RefreshRsp { string refreshToken = 3; } +// Пароль подтверждает, что удаляет аккаунт его владелец, а не обладатель +// украденного access-токена (ст. 21 152-ФЗ). Передаётся HTTP-заголовком +// X-Password (пробрасывается матчером в cmd/evening_detective_server/main.go), +// чтобы креденшел не попадал в URL/query-параметры и логи. +message DeleteAccountReq {} + +message DeleteAccountRsp { + string error = 1; +} + +// Документы раздаются по постоянным URL, на которые ссылается сервис при +// фиксации акцептов соглашений (user_agreements) и форма регистрации. +message GetTermsReq {} + +message GetTermsRsp { + string error = 1; + string text = 2; +} + +message GetPrivacyReq {} + +message GetPrivacyRsp { + string error = 1; + string text = 2; +} + +message GetConsentReq {} + +message GetConsentRsp { + string error = 1; + string text = 2; +} + message GetUsersReq {} message GetUsersRsp { diff --git a/cmd/evening_detective_server/main.go b/cmd/evening_detective_server/main.go index 14acb7e..d2b1c16 100644 --- a/cmd/evening_detective_server/main.go +++ b/cmd/evening_detective_server/main.go @@ -27,6 +27,7 @@ import ( "net" "net/http" "os" + "strings" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/jackc/pgx/v5/pgxpool" @@ -125,6 +126,9 @@ func main() { "/crabs.evening_detective_server.EveningDetectiveServer/GetScenariosCatalog": true, "/crabs.evening_detective_server.EveningDetectiveServer/GetTeamStory": true, "/crabs.evening_detective_server.EveningDetectiveServer/AddTeamAction": true, + "/crabs.evening_detective_server.EveningDetectiveServer/GetTerms": true, + "/crabs.evening_detective_server.EveningDetectiveServer/GetPrivacy": true, + "/crabs.evening_detective_server.EveningDetectiveServer/GetConsent": true, }, processorJWT, ), @@ -158,7 +162,23 @@ func main() { log.Fatalln("Failed to dial server:", err) } - gwmux := runtime.NewServeMux() + // X-Real-IP пробрасывается от доверенного обратного прокси (если фронт- + // контур развёрнут перед gateway, см. docs/COMPLIANCE.md п. 6.6) и + // используется в clientInfoFromContext для фиксации IP клиента при + // акцепте соглашений (ст. 9 152-ФЗ). X-Password — подтверждение паролем + // при удалении аккаунта (не в query, чтобы не светить креденшел в URL + // и логах). + gwmux := runtime.NewServeMux( + runtime.WithIncomingHeaderMatcher(func(key string) (string, bool) { + switch { + case strings.EqualFold(key, "X-Real-IP"): + return "x-real-ip", true + case strings.EqualFold(key, "X-Password"): + return "x-password", true + } + return runtime.DefaultHeaderMatcher(key) + }), + ) // Register Greeter err = proto.RegisterEveningDetectiveServerHandler(context.Background(), gwmux, conn) if err != nil { diff --git a/cmd/evening_detective_server/main.swagger.json b/cmd/evening_detective_server/main.swagger.json index cefdeca..48232ac 100644 --- a/cmd/evening_detective_server/main.swagger.json +++ b/cmd/evening_detective_server/main.swagger.json @@ -16,6 +16,30 @@ "application/json" ], "paths": { + "/api/auth/delete-account": { + "delete": { + "summary": "Удалить учётную запись и персональные данные", + "description": "Удаляет учётную запись и персональные данные текущего пользователя (ст. 21 152-ФЗ). Требует заголовок X-Password с паролем учётной записи (подтверждение владельца; пароль не передаётся в URL).", + "operationId": "EveningDetectiveServer_DeleteAccount", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/evening_detective_serverDeleteAccountRsp" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "tags": [ + "Регистрация и вход" + ] + } + }, "/api/auth/login": { "post": { "summary": "Войти и получить токена доступа", @@ -1506,6 +1530,75 @@ "Пользователи" ] } + }, + "/consent": { + "get": { + "summary": "Получить текст согласия на обработку персональных данных", + "operationId": "EveningDetectiveServer_GetConsent", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/evening_detective_serverGetConsentRsp" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "tags": [ + "Документы" + ] + } + }, + "/privacy": { + "get": { + "summary": "Получить текст Политики конфиденциальности", + "operationId": "EveningDetectiveServer_GetPrivacy", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/evening_detective_serverGetPrivacyRsp" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "tags": [ + "Документы" + ] + } + }, + "/terms": { + "get": { + "summary": "Получить текст Пользовательского соглашения (оферты)", + "operationId": "EveningDetectiveServer_GetTerms", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "$ref": "#/definitions/evening_detective_serverGetTermsRsp" + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "$ref": "#/definitions/rpcStatus" + } + } + }, + "tags": [ + "Документы" + ] + } } }, "definitions": { @@ -1758,6 +1851,14 @@ } } }, + "evening_detective_serverDeleteAccountRsp": { + "type": "object", + "properties": { + "error": { + "type": "string" + } + } + }, "evening_detective_serverDeleteGameRsp": { "type": "object", "properties": { @@ -1888,6 +1989,17 @@ } } }, + "evening_detective_serverGetConsentRsp": { + "type": "object", + "properties": { + "error": { + "type": "string" + }, + "text": { + "type": "string" + } + } + }, "evening_detective_serverGetGameRsp": { "type": "object", "properties": { @@ -1954,6 +2066,17 @@ } } }, + "evening_detective_serverGetPrivacyRsp": { + "type": "object", + "properties": { + "error": { + "type": "string" + }, + "text": { + "type": "string" + } + } + }, "evening_detective_serverGetScenarioRsp": { "type": "object", "properties": { @@ -1994,6 +2117,17 @@ } } }, + "evening_detective_serverGetTermsRsp": { + "type": "object", + "properties": { + "error": { + "type": "string" + }, + "text": { + "type": "string" + } + } + }, "evening_detective_serverGetUserByIdRsp": { "type": "object", "properties": { @@ -2222,6 +2356,12 @@ }, "email": { "type": "string" + }, + "acceptTerms": { + "type": "boolean" + }, + "acceptPrivacy": { + "type": "boolean" } } }, diff --git a/docs/COMPLIANCE.md b/docs/COMPLIANCE.md new file mode 100644 index 0000000..094990f --- /dev/null +++ b/docs/COMPLIANCE.md @@ -0,0 +1,123 @@ +# ЧЕК-ЛИСТ COMPLIANCE: ПРИВЕДЕНИЕ СЕРВИСА В СООТВЕТСТВИЕ С ДОКУМЕНТАМИ + +Сервис «Вечерний детектив» · Обновлено: 18.08.2026 + +Сопутствующие документы: `docs/TERMS.md` (Пользовательское соглашение), `docs/PRIVACY.md` (Политика конфиденциальности), `docs/CONSENT.md` (Согласие на обработку ПДн). + +Легенда: ✅ — реализовано, 🟡 — частично / требует решения владельца, ⬜ — осталось сделать. + +--- + +## 1. Юридические документы + +| № | Задача | Статус | Примечание | +|---|---|---|---| +| 1.1 | Пользовательское соглашение (оферта) | ✅ | `docs/TERMS.md` — заполнить плейсхолдеры, утвердить у юриста | +| 1.2 | Политика конфиденциальности (152-ФЗ) | ✅ | `docs/PRIVACY.md` — заполнить плейсхолдеры, утвердить у юриста | +| 1.3 | Текст согласия на обработку ПДн | ✅ | `docs/CONSENT.md` — встроить в форму регистрации | +| 1.4 | Публикация документов на сайте по постоянным URL | ✅ | RPC `GetTerms`/`GetPrivacy`/`GetConsent` (`api/main.proto`, пути `/terms`, `/privacy`, `/consent`); текст встраивается из `docs/embed.go`; подставить реальные домены в тексты документов | + +## 2. Акцепт соглашений при регистрации (ст. 428 ГК РФ, ст. 9 152-ФЗ) + +| № | Задача | Статус | Где | +|---|---|---|---| +| 2.1 | Поля `accept_terms` / `accept_privacy` в запросе регистрации | ✅ | `api/main.proto` (`SignupReq`), перегенерирован `proto/` | +| 2.2 | Серверная проверка: регистрация без акцепта отклоняется (`ErrTermsNotAccepted`) | ✅ | `internal/services/users_service/service.go` → `AddUser`; `internal/app/server.go` → `Signup` | +| 2.3 | Таблица `user_agreements` (user_id, тип, версия, дата, IP, user-agent) | ✅ | `migrations/20260818231943_create_user_agreements_table.sql` | +| 2.4 | Фиксация акцепта при регистрации (terms + privacy), атомарно с созданием пользователя | ✅ | `users_repo.AddUserWithAgreements` (одна транзакция: пользователь не существует без записей о согласиях) | +| 2.5 | Версии документов как константы (`termsVersion`, `privacyVersion`) | ✅ | `users_service/service.go` — при новой редакции документов поднять версию | +| 2.6 | Чекбоксы в форме регистрации (не предустановленные!) + блокировка отправки | ⬜ | Фронтенд (репозиторий фронта) | +| 2.7 | Возраст 18+ (текст + проверка) | 🟡 | В документах и коде — запрет; проверить, что форма запрашивает подтверждение возраста | +| 2.8 | Фиксация IP и user-agent клиента при акцепте (ст. 9 ч. 3 152-ФЗ) | ✅ | `clientInfoFromContext`: `X-Real-IP` от доверенного прокси (матчер в `cmd/evening_detective_server/main.go`), иначе последний элемент `X-Forwarded-For`; UA — `grpcgateway-user-agent` | + +## 3. Удаление аккаунта и данных (ст. 14, 21 152-ФЗ) + +| № | Задача | Статус | Где | +|---|---|---|---| +| 3.1 | Эндпоинт `DELETE /api/auth/delete-account` (авторизован JWT) | ✅ | `api/main.proto` (`DeleteAccount`), `internal/app/server.go` | +| 3.2 | Удаление аккаунта: ПДн удаляются (refresh-токены, учётная запись); записи об акцептах СОХРАНЯЮТСЯ обезличенными (факт/версия/время; `user_id` отвязывается через FK `ON DELETE SET NULL`, `ip`/`user_agent` обнуляются — бремя доказывания согласия на операторе, ст. 9 ч. 4 152-ФЗ) | ✅ | `internal/repos/users_repo/repo.go` → `DeleteUser` (транзакция); миграции `20260818231943_create_user_agreements_table.sql`, `20260818232725_keep_content_on_user_delete.sql` | +| 3.2а | Подтверждение паролем при удалении аккаунта (защита от удаления чужим обладателем украденного access-токена) | ✅ | HTTP-заголовок `X-Password` (матчер в `cmd/evening_detective_server/main.go`) → `users_service.DeleteAccount` (bcrypt-сверка); пароль не попадает в URL/query | +| 3.3 | Судьба контента при удалении аккаунта | ✅ | Выбран вариант «отчуждение исключительного права на опубликованные Сценарии»: контент сохраняется, автор не вправе требовать удаления (п. 7.2, 7.6, 7.8 TERMS; ст. 1234, 1269 ГК РФ) | +| 3.4 | NULL-safe чтение сценариев с обезличенным автором | ✅ | `scenarios_repo` (scan через указатели), `mapUser` возвращает nil → `author: null` в API (клиент показывает «Автор удалён») | +| 3.5 | Удаление файлов из S3 при удалении аккаунта | ⬜ | Сейчас удаляются только записи в БД; файлы пользователя в S3 (`file_service`) остаются — добавить вызов `fileStorage.Delete` для файлов автора | +| 3.6 | UI-кнопка «Удалить аккаунт» + подтверждение | ⬜ | Фронтенд | +| 3.7 | Отзыв согласия без удаления аккаунта (ст. 9 ч. 2, 152-ФЗ) | ⬜ | Опционально: отдельный эндпоинт «отозвать согласие» → прекращение обработки, блокировка аккаунта | +| 3.8 | Инвалидация выданных access-токенов после удаления аккаунта | 🟡 | JWT без revoke-листа: refresh-токен удаляется сразу, access-токен действует до истечения TTL (3 ч, `processor_jwt`); запросы с устаревшим токеном после удаления получат ошибку FK/«Пользователь не найден». Защита: короткий TTL; при необходимости — версия токена/чёрный список | + +**Примечание по акцептам (п. 3.2):** решение владельца — хранить записи об акцептах обезличенными после удаления аккаунта (факт/версия/время без `user_id`/`ip`/`user_agent`): ст. 9 ч. 4 152-ФЗ возлагает на оператора бремя доказывания получения согласия. Альтернатива, если позже решат уничтожать и их (ст. 21 152-ФЗ): вернуть FK `ON DELETE CASCADE` в миграции `20260818231943` и `DELETE FROM user_agreements WHERE user_id = $1` в `DeleteUser`. + +## 3а. Отчуждение исключительных прав на сценарии (ст. 1234, 1269 ГК РФ) + +| № | Задача | Статус | Где | +|---|---|---|---| +| 3а.1 | Пункт TERMS об отчуждении исключительного права при публикации (безвозмездно, в полном объёме) | ✅ | `docs/TERMS.md` п. 7.2–7.4 | +| 3а.2 | Запрет автору удалять / снимать с публикации опубликованный сценарий (`ErrScenarioPublished`); ПРАВКА КОНТЕНТА опубликованного сценария РАЗРЕШЕНА владельцу (решение владельца продукта) | ✅ | `internal/services/scenarios_service/service.go`; админ — исключение; guard в SQL от гонки «чтение → запись» для status/delete | +| 3а.3 | Проверка владельца сценария при всех изменениях (public/draft/delete/update/места) (`ErrScenarioNotOwner`) | ✅ | `internal/services/scenarios_service/service.go` → `getScenarioForChange` | +| 3а.4 | Право на отзыв ограничено моментом обнародования (ст. 1269 ГК РФ) | ✅ | `docs/TERMS.md` п. 7.6 | +| 3а.5 | Отдельный чекбокс «передаю исключительные права» при первой публикации + серверная проверка | ⬜ | Фронтенд + бэкенд (сейчас публикация доступна владельцу без доп. подтверждения; добавить `confirm_transfer` в `PublicScenarioReq` при необходимости) | +| 3а.6 | Проверка владельца при редактировании сценария (UpdateScenario, AddScenarioPlace и др.) | ✅ | `getScenarioForChange` в `internal/services/scenarios_service/service.go`; правка опубликованного разрешена (решение владельца, см. 3а.2) | +| 3а.7 | Оценка рисков ЗоЗПП (ст. 16) для безвозмездного отчуждения в договоре присоединения | 🟡 | См. «Риски» ниже; при запуске для широкой аудитории — консультация юриста и судебная практика | + +**Риски отчуждения прав в договоре присоединения:** + +- **ЗоЗПП, ст. 16**: безвозмездное отчуждение исключительного права на пользовательский контент в оферте для потребителя может быть оспорено как условие, ущемляющее права потребителя. Снижение риска: отдельное явное подтверждение при публикации, возможность отозвать Сценарий до публикации (черновики не отчуждаются), прозрачное выделение условия. +- **Личные неимущественные права** (ст. 1265 ГК РФ) не отчуждаются: автор сохраняет право авторства и может требовать его признания — отчуждается только имущественное (исключительное) право. +- **Право на отзыв** (ст. 1269 ГК РФ) действует только до обнародования — после публикации требования автора об удалении не подлежат удовлетворению (кроме случаев, предусмотренных законом, напр. признание сценария нарушающим права третьих лиц). +- **Коммерческие организации**: п. 3.1 ст. 1234 ГК РФ запрещает безвозмездное отчуждение исключительного права между коммерческими организациями — не применяется, т.к. пользователи — физические лица. + +## 4. Регистрация в Роскомнадзоре (ст. 22 152-ФЗ) + +| № | Задача | Статус | Примечание | +|---|---|---|---| +| 4.1 | Оценить необходимость уведомления РКН о начале обработки ПДн | 🟡 | Интернет-сервис с автоматизированной обработкой обычно требует уведомления; исключения ч. 2 ст. 22 вряд ли применимы. Подать до запуска в прод | +| 4.2 | Подать уведомление (портал РКН, форма «оператор ПДн») | ⬜ | Внешняя процедура; оператор — физлицо | +| 4.3 | Получить и хранить номер уведомления / решение | ⬜ | Приложить к документации | + +## 5. Локализация баз данных (ст. 18 ч. 5 152-ФЗ) + +| № | Задача | Статус | Где | +|---|---|---|---| +| 5.1 | PostgreSQL в РФ | ✅ | `docker-compose-db.yml` / прод-конфигурация — проверить, что БД в РФ | +| 5.2 | S3 (RustFS) — файлы пользователей | 🟡 | Проверить, где физически находится `S3_HOST` в проде | +| 5.3 | SMTP-логи переписки | 🟡 | Проверить, не сохраняются ли письма/логи за пределами РФ | + +## 6. Безопасность (ст. 19 152-ФЗ) + +| № | Задача | Статус | Где | +|---|---|---|---| +| 6.1 | Хеширование паролей (bcrypt) | ✅ | `users_service/service.go` | +| 6.2 | JWT access (3 ч) + refresh (7 дн) с ротацией | ✅ | `processor_jwt` | +| 6.3 | HTTPS на проде | 🟡 | Через обратный прокси (не в репозитории) | +| 6.4 | Назначить ответственного за обработку ПДн (ст. 22.1) | ⬜ | Организационный шаг (для физлица-оператора — сам владелец) | +| 6.5 | Внутренний документ: сроки хранения логов, порядок реагирования на утечки (ст. 21 ч. 3.1 — уведомление РКН за 24 ч) | ⬜ | Организационный шаг | +| 6.6 | Gateway только за доверенным обратным прокси, перезаписывающим `X-Real-IP` (иначе клиент спуфит IP при акцепте; значения валидируются `netip.ParseAddr`) | 🟡 | Требование к прод-развёртыванию: nginx/Caddy перед `:8090`; настройка не в репозитории | + +## 7. Права субъекта (ст. 14, 17, 20 152-ФЗ) + +| № | Задача | Статус | Где | +|---|---|---|---| +| 7.1 | Эндпоинт «получить свои данные» (GDPR-стиль / ст. 14) | 🟡 | Частично есть `GET /api/users/me`; полная выгрузка ПДн (все таблицы) — добавить | +| 7.2 | Эндпоинт «изменить email/ник» | ⬜ | Сейчас нет; без него нельзя исполнить «уточнение ПДн» | +| 7.3 | Эндпоинт «удалить аккаунт» | ✅ | П. 3.1 | +| 7.4 | Процедура ответа на запросы (10 раб. дней, ст. 20) | ⬜ | Организационный шаг + адрес `[email]` из документов | + +## 8. Прочее + +| № | Задача | Статус | Примечание | +|---|---|---|---| +| 8.1 | Обновление swagger (`cmd/evening_detective_server/main.swagger.json`) | ✅ | Перегенерирован `make generate` | +| 8.2 | Прогон миграции на реальной БД (`goose up`) | ⬜ | Выполнить на staging перед продом | +| 8.3 | Интеграционный тест: signup без акцепта → ошибка; delete-account → данные удалены | ⬜ | `go test` (сейчас тестов нет) | +| 8.4 | Обновить README: новые эндпоинты, документы | ⬜ | — | +| 8.5 | GDPR (если появятся пользователи из ЕС) | ⬜ | Политика + DPA + механизмы прав субъекта — отдельный этап | + +--- + +## Порядок действий перед запуском в прод + +1. Заполнить плейсхолдеры в `docs/TERMS.md`, `docs/PRIVACY.md`, `docs/CONSENT.md` и утвердить у юриста. +2. Вставить в тексты документов реальные домены (`/terms`, `/privacy`, `/consent`); вставить чекбоксы акцепта, подтверждение отчуждения прав при публикации сценария и кнопку «Удалить аккаунт» во фронтенд. +3. Подать уведомление в Роскомнадзор (п. 4.2) до начала обработки. +4. Проверить локализацию: БД, S3, SMTP — в РФ. +5. Прогнать `goose up` на staging; добавить интеграционный тест (п. 8.3) — включая сценарий: публикация → удаление запрещено; удаление аккаунта → сценарий остаётся с `author: null`. +6. Решить задачу удаления файлов из S3 (п. 3.5) и «изменить email/ник» (п. 7.2) — по остаточному принципу после запуска. diff --git a/docs/CONSENT.md b/docs/CONSENT.md new file mode 100644 index 0000000..847bb08 --- /dev/null +++ b/docs/CONSENT.md @@ -0,0 +1,54 @@ +# СОГЛАСИЕ НА ОБРАБОТКУ ПЕРСОНАЛЬНЫХ ДАННЫХ + +**Сервис «Вечерний детектив»** · **Редакция от «__» ________ 20__ года** + +*Настоящий документ является шаблоном и носит информационный характер. Перед использованием текст должен быть адаптирован и утверждён квалифицированным юристом.* + +--- + +## Текст согласия (для регистрационной формы) + +Я, свободно, своей волей и в своём интересе, являясь дееспособным лицом, достигшим возраста 18 лет, даю своё согласие **[ФИО Оператора]** (далее — **Оператор**), зарегистрированному по адресу: **[адрес]**, на обработку моих персональных данных (далее — **ПДн**) в соответствии с Федеральным законом от 27.07.2006 № 152-ФЗ «О персональных данных» (далее — **152-ФЗ**), а именно на совершение действий, предусмотренных п. 3 ч. 1 ст. 3 152-ФЗ, со следующими ПДн: + +1. адрес электронной почты; +2. имя пользователя (никнейм / псевдоним); +3. сведения об учётной записи (включая роли и права); +4. данные об участии в играх, командах, поданных заявках; +5. создаваемые мной материалы (сценарии, тексты, иной контент); +6. загружаемые мной файлы; +7. технические данные (IP-адрес, сведения об устройстве и браузере, файлы cookie); +8. иные данные, добровольно предоставляемые мной при использовании Сервиса. + +**Цели обработки** ПДн: идентификация и аутентификация при использовании Сервиса «Вечерний детектив»; предоставление доступа к Сервису и его функциям; связь со мной (направление пароля, уведомлений); обеспечение безопасности Сервиса; улучшение качества Сервиса; исполнение требований законодательства РФ. + +**Перечень действий с ПДн:** сбор, запись, систематизация, накопление, хранение, уточнение (обновление, изменение), извлечение, использование, обезличивание, блокирование, удаление, уничтожение, — как с использованием средств автоматизации, так и без их использования. + +Настоящее согласие действует со дня его предоставления до дня его отзыва. Согласие может быть отозвано мной в любое время путём направления Оператору письменного требования (в т.ч. в форме электронного документа) на адрес: **[email]**. При отзыве согласия Оператор обязан прекратить обработку ПДн и уничтожить их в срок, не превышающий 30 (тридцати) календарных дней с даты получения отзыва, если иное не предусмотрено законодательством РФ. + +Я ознакомлен(а) с Политикой конфиденциальности и обработки персональных данных, размещённой по адресу: **[адрес политики]**, и Пользовательским соглашением, размещённым по адресу: **[адрес соглашения]**, и согласен(на) с их условиями. + +«___» ________ 20___ года + +Подпись: ____________________ / ____________________ + +--- + +## Техническая реализация в форме регистрации + +Для юридической значимости согласие должно быть получено до начала обработки и подтверждаемо: + +1. **Чекбоксы с явным согласием** (не предустановленные): + - [ ] Я принимаю условия [Пользовательского соглашения] + - [ ] Я даю согласие на обработку персональных данных в соответствии с [Политикой конфиденциальности] +2. **Блокировка отправки** формы при неотмеченных чекбоксах (клиентская и серверная проверка). +3. **Серверная проверка**: `POST /api/auth/signup` отклоняет запрос (`accept_terms=false` или `accept_privacy=false`) с ошибкой — уже реализовано в бэкенде (см. `docs/COMPLIANCE.md`). +4. **Фиксация факта акцепта**: сервер сохраняет запись в таблице `user_agreements` (тип документа, версия, дата, IP, user-agent) — уже реализовано. +5. **Возраст 18+**: подтверждение возраста включается в текст согласия и регистрационную форму. +6. **Отдельное подтверждение при публикации Сценария** (рекомендуется): при первом переводе сценария в статус «опубликован» — чекбокс «Я передаю Оператору исключительные права на этот сценарий безвозмездно в полном объёме» с указанием, что после публикации отозвать сценарий нельзя (ст. 1269 ГК РФ). Серверная проверка: `PUT /api/scenarios/{id}/public` отклоняет запрос без этого подтверждения (см. раздел «Риски» в `docs/COMPLIANCE.md`). + +## Примечания + +- **Отдельное согласие vs соглашение**: согласие на обработку ПДн (ст. 9 152-ФЗ) и акцепт пользовательского соглашения (ст. 428, 1286 ГК РФ) — разные юридические факты, поэтому в форме два отдельных чекбокса. +- Для несовершеннолетних (до 18 лет) использование Сервиса запрещено (п. 4.1 Пользовательского соглашения); согласие родителей не предусмотрено, т.к. доступ запрещён полностью. +- При введении платных услуг и изменении целей обработки согласие должно быть переактуализировано. +- **Удаление аккаунта и контент**: отзыв согласия / удаление Учётной записи влечёт удаление персональных данных, но не прекращает отчуждение исключительного права на опубликованные Сценарии: они остаются в Сервисе, атрибуция обезличивается (п. 7.8 Пользовательского соглашения, ст. 1234 ГК РФ). diff --git a/docs/PRIVACY.md b/docs/PRIVACY.md new file mode 100644 index 0000000..780476e --- /dev/null +++ b/docs/PRIVACY.md @@ -0,0 +1,185 @@ +# ПОЛИТИКА КОНФИДЕНЦИАЛЬНОСТИ И ОБРАБОТКИ ПЕРСОНАЛЬНЫХ ДАННЫХ + +Сервис «Вечерний детектив» + +**Редакция от «__» ________ 20__ года** + +*Настоящий документ является шаблоном и носит информационный характер. Перед публикацией документ должен быть адаптирован и утверждён квалифицированным юристом.* + +--- + +## 1. Общие положения + +1.1. Настоящая Политика конфиденциальности и обработки персональных данных (далее — **Политика**) определяет порядок и условия обработки персональных данных (далее — **ПДн**) Пользователей Сервиса «Вечерний детектив» (далее — **Сервис**), размещённого в сети Интернет по адресу: **[адрес сайта]**. + +1.2. Оператором ПДн (ст. 3 Федерального закона от 27.07.2006 № 152-ФЗ «О персональных данных», далее — **152-ФЗ**) является **[ФИО Оператора]** (далее — **Оператор**). Реквизиты Оператора указаны в разделе 14 Политики. + +1.3. Политика разработана во исполнение требований ст. 18.1 152-ФЗ и действует в отношении всех ПДн, которые Оператор может получить о Пользователе при использовании Сервиса. + +1.4. Политика является неотъемлемой частью Пользовательского соглашения (далее — **Соглашение**), размещённого по адресу: **[адрес соглашения]**. Термины, используемые в Политике, применяются в значениях, определённых Соглашением, если иное не установлено Политикой или законодательством РФ. + +1.5. Используя Сервис (регистрируясь, авторизуясь, осуществляя доступ к Сервису), Пользователь выражает согласие с условиями Политики и согласие на обработку своих ПДн в порядке и на условиях, изложенных в Политике. + +1.6. Если Пользователь не согласен с условиями Политики, он обязан прекратить использование Сервиса. + +## 2. Состав обрабатываемых ПДн + +2.1. Оператор обрабатывает следующие ПДн Пользователей: + +2.1.1. **Данные, предоставляемые Пользователем при регистрации и использовании Сервиса:** +- адрес электронной почты; +- имя пользователя (никнейм / псевдоним); +- пароль (в захешированном виде, недоступном для прочтения); +- иные данные, которые Пользователь добровольно указывает при использовании Сервиса. + +2.1.2. **Данные, создаваемые в процессе использования Сервиса:** +- сведения об Учётной записи и её настройках; +- сведения о ролях и правах Пользователя в Сервисе; +- данные об участии в Играх, о Командах, о поданных заявках; +- создаваемые Пользователем материалы (Сценарии, тексты, иной Пользовательский контент); +- загружаемые Пользователем файлы (изображения и иные материалы), в т.ч. при подаче заявок; +- история действий Пользователя в Сервисе (в т.ч. сведения о входе в Учётную запись). + +2.1.3. **Технические данные, собираемые автоматически:** +- IP-адрес устройства; +- данные об устройстве и браузере (тип, версия, язык, разрешение экрана); +- файлы cookie и аналогичные технологии; +- сведения о времени и длительности сеансов; +- иные технические данные, передаваемые устройством Пользователя при обращении к Сервису. + +2.1.4. Оператор не обрабатывает специальные категории ПДн (ст. 10 152-ФЗ: раса, национальность, политические взгляды, религиозные убеждения, состояние здоровья, интимная жизнь) и биометрические ПДн (ст. 11 152-ФЗ), за исключением случаев, прямо предусмотренных законодательством РФ. + +2.1.5. Загружая файлы и размещая Пользовательский контент, Пользователь самостоятельно несёт ответственность за то, чтобы такие материалы не содержали ПДн третьих лиц без их согласия, а также иных сведений, обработка которых не допускается. + +## 3. Цели обработки ПДн + +3.1. Оператор обрабатывает ПДн Пользователей исключительно в следующих целях: + +- идентификация и аутентификация Пользователя при регистрации и входе в Сервис; +- предоставление доступа к Сервису и его функциям; +- обеспечение функционирования Сервиса (в т.ч. создание Игр, Команд, Сценариев, обработка заявок); +- связь с Пользователем: направление пароля при регистрации, уведомлений о восстановлении пароля, иных служебных сообщений, связанных с использованием Сервиса; +- обеспечение безопасности Сервиса, защита от несанкционированного доступа, мошенничества и злоупотреблений; +- улучшение качества Сервиса, анализ использования его функций; +- исполнение требований законодательства РФ. + +3.2. Оператор не использует ПДн для целей, несовместимых с целями, указанными в п. 3.1 Политики. + +## 4. Правовые основания обработки ПДн + +4.1. Обработка ПДн Пользователя осуществляется на следующих основаниях (ст. 6 152-ФЗ): + +- **согласие Пользователя** на обработку ПДн, выраженное при регистрации и/или использовании Сервиса (акцепт Политики и Соглашения); +- **исполнение Соглашения**, стороной которого является Пользователь (в т.ч. предоставление доступа к Сервису, исполнение обязательств Оператора); +- **исполнение требований законодательства РФ**, возложенных на Оператора; +- **защита прав и законных интересов** Оператора и третьих лиц (в т.ч. предотвращение злоупотреблений и нарушений). + +4.2. Согласие Пользователя на обработку ПДн является конкретным, информированным и сознательным (ст. 9 152-ФЗ). Согласие может быть отозвано Пользователем в любое время в порядке, предусмотренном разделом 12 Политики. + +## 5. Порядок и условия обработки ПДн + +5.1. Обработка ПДн осуществляется с использованием средств автоматизации и без использования средств автоматизации, в т.ч. путём сбора, записи, систематизации, накопления, хранения, уточнения (обновления, изменения), извлечения, использования, передачи, обезличивания, блокирования, удаления, уничтожения (ст. 3 152-ФЗ). + +5.2. Обработка ПДн осуществляется с соблюдением принципов, установленных ст. 5 152-ФЗ: законности и справедливости, соответствия целям обработки, минимизации, точности и достаточности, ограничения сроков хранения. + +5.3. Оператор не раскрывает ПДн Пользователей третьим лицам и не распространяет их без согласия Пользователя, за исключением случаев, предусмотренных законодательством РФ. + +5.4. Для обеспечения функционирования Сервиса Оператор может привлекать третьих лиц (технических подрядчиков): поставщиков хостинга и вычислительных мощностей, почтового сервиса для отправки сообщений, сервиса облачного хранения файлов, сервисов аналитики. Передача ПДн таким лицам осуществляется в объёме, необходимом для оказания соответствующих услуг, на основании договоров, содержащих обязательства о конфиденциальности и обеспечении безопасности ПДн (ст. 6, 19 152-ФЗ). + +5.5. ПДн Пользователей не передаются третьим лицам в целях маркетинга и рекламы без отдельного согласия Пользователя. + +## 6. Файлы cookie и аналитика + +6.1. Сервис может использовать файлы cookie и аналогичные технологии (localStorage, sessionStorage, идентификаторы устройств) для: + +- обеспечения корректной работы Сервиса (технически необходимые cookie); +- запоминания настроек и предпочтений Пользователя; +- сбора статистики использования Сервиса (аналитические cookie). + +6.2. Технически необходимые cookie не требуют согласия Пользователя. Использование аналитических и иных необязательных cookie осуществляется с согласия Пользователя, выраженного через настройки браузера и/или элементы интерфейса Сервиса. + +6.3. Пользователь может в любой момент отключить или ограничить использование cookie в настройках браузера. Отключение cookie может повлиять на доступность отдельных функций Сервиса. + +6.4. Данные аналитики могут обрабатываться в обезличенном виде и использоваться для улучшения Сервиса. + +## 7. Трансграничная передача ПДн + +7.1. На дату вступления Политики в силу трансграничная передача ПДн (ст. 12 152-ФЗ) Оператором не осуществляется. + +7.2. В случае необходимости трансграничной передачи ПДн Оператор обеспечит соблюдение требований ст. 12 152-ФЗ, включая (при необходимости) уведомление или получение разрешения уполномоченного органа (Роскомнадзора) в соответствии с действующим законодательством РФ, и соответствующим образом актуализирует настоящую Политику. + +## 8. Локализация баз данных + +8.1. Оператор обеспечивает запись, систематизацию, накопление, хранение, уточнение, извлечение ПДн граждан Российской Федерации с использованием баз данных, находящихся на территории Российской Федерации (ст. 18 ч. 5 152-ФЗ). + +## 9. Меры по защите ПДн + +9.1. Оператор принимает правовые, организационные и технические меры, необходимые и достаточные для обеспечения безопасности ПДн (ст. 19 152-ФЗ), включая: + +- назначение лица, ответственного за организацию обработки ПДн (ст. 22.1 152-ФЗ); +- применение правовых, организационных и технических мер защиты информации (шифрование паролей, ограничение и разграничение доступа к ПДн, защита каналов передачи данных, резервное копирование); +- внутренний контроль за соответствием обработки ПДн требованиям законодательства; +- оценку вреда, который может быть причинён субъектам ПДн в случае нарушения требований 152-ФЗ; +- ознакомление лиц, допущенных к обработке ПДн, с требованиями законодательства и Политики. + +9.2. Пароли Пользователей хранятся в захешированном виде и недоступны для чтения никому, включая работников и подрядчиков Оператора. + +9.3. При выявлении фактов неправомерной или случайной передачи (предоставления, распространения, доступа) ПДн, повлёкшей нарушение прав субъектов ПДн, Оператор в срок, не превышающий 24 часов, уведомляет уполномоченный орган по защите прав субъектов персональных данных (Роскомнадзор) о произошедшем инциденте, а также в установленных законодательством случаях уведомляет субъектов ПДн (ст. 21 ч. 3.1 152-ФЗ). + +## 10. Сроки обработки и хранения ПДн + +10.1. ПДн обрабатываются в течение срока, необходимого для достижения целей обработки, либо в течение срока действия Соглашения, если иное не предусмотрено законодательством РФ. + +10.2. ПДн уничтожаются либо обезличиваются по достижении целей обработки, при отзыве Пользователем согласия на обработку ПДн, при удалении Учётной записи, при прекращении Соглашения, а также по требованию Пользователя (ст. 21 152-ФЗ), за исключением случаев, когда законодательством РФ предусмотрено обязательное хранение таких данных в течение определённого срока. + +10.3. При удалении Учётной записи ПДн Пользователя удаляются в срок не более **[30]** календарных дней с момента получения соответствующего требования, если иное не предусмотрено законодательством. Публичный контент Пользователя (опубликованные Сценарии и т.п.) при этом сохраняется в Сервисе: исключительное право на него отчуждено Оператору (п. 7.2 Пользовательского соглашения, ст. 1234 ГК РФ), а связь контента с персональными данными Пользователя прекращается (обезличивание, ст. 3 152-ФЗ). + +## 11. Защита прав несовершеннолетних + +11.1. Сервис предназначен для лиц, достигших 18 лет (п. 4.1 Соглашения). Регистрация и использование Сервиса лицами, не достигшими 18 лет, запрещены. + +11.2. Оператор не собирает сознательно ПДн лиц, не достигших 18 лет. При обнаружении факта обработки ПДн несовершеннолетнего Оператор незамедлительно прекращает такую обработку и удаляет соответствующие данные. + +## 12. Права субъекта ПДн и порядок их реализации + +12.1. Пользователь (субъект ПДн) вправе (ст. 14, 17 152-ФЗ): + +- получать информацию, касающуюся обработки его ПДн (сведения, предусмотренные ст. 14 152-ФЗ); +- требовать уточнения, блокирования или уничтожения своих ПДн, если они являются неполными, устаревшими, неточными, незаконно полученными или не являются необходимыми для заявленной цели обработки (ст. 14, 21 152-ФЗ); +- отозвать согласие на обработку ПДн в любое время; +- обжаловать действия (бездействие) Оператора в уполномоченном органе по защите прав субъектов персональных данных (Роскомнадзор) и/или в судебном порядке (ст. 17 152-ФЗ). + +12.2. Для реализации прав, предусмотренных п. 12.1 Политики, Пользователь направляет Оператору запрос в письменной форме (в т.ч. в форме электронного документа) на адрес: **[email]**. + +12.3. Запрос должен содержать (ст. 14 ч. 3, 152-ФЗ): + +- номер основного документа, удостоверяющего личность Пользователя (или его представителя), сведения о дате выдачи и выдавшем органе; +- сведения, подтверждающие участие Пользователя в отношениях с Оператором (например, адрес электронной почты, использованный при регистрации); +- подпись Пользователя (или его представителя). + +12.4. Оператор рассматривает запрос и направляет ответ в срок, не превышающий **10 рабочих дней** с даты получения запроса (ст. 20 ч. 1 152-ФЗ). В случае отказа в удовлетворении запроса Оператор направляет мотивированный ответ. + +12.5. Отзыв согласия на обработку ПДн (ст. 9 ч. 2, 152-ФЗ) влечёт прекращение обработки и уничтожение ПДн в срок, не превышающий **30 календарных дней** с даты получения отзыва (ст. 21 ч. 5, 152-ФЗ). Отзыв согласия может сделать невозможным дальнейшее использование Сервиса. + +## 13. Заключительные положения + +13.1. Оператор вправе в одностороннем порядке изменять условия Политики. Новая редакция Политики вступает в силу с момента её опубликования в Сервисе, если иной срок не указан при опубликовании. Продолжение использования Сервиса после вступления в силу новой редакции Политики означает согласие Пользователя с изменениями. + +13.2. В случае внесения существенных изменений в Политику, затрагивающих права Пользователей, Оператор уведомляет Пользователей способами, доступными в Сервисе (в т.ч. путём направления уведомления на адрес электронной почты). + +13.3. Контроль за соблюдением Политики осуществляет лицо, ответственное за организацию обработки ПДн (п. 9.1 Политики). + +13.4. По всем вопросам, связанным с обработкой ПДн и реализацией прав субъектов ПДн, Пользователь может обратиться к Оператору по адресу: **[email]**. + +13.5. Настоящая Политика регулируется и толкуется в соответствии с законодательством Российской Федерации. + +## 14. Реквизиты Оператора + +**Оператор Сервиса «Вечерний детектив»:** + +- ФИО: **[ФИО Оператора]** +- Адрес: **[адрес]** +- Адрес электронной почты: **[email]** +- Иные реквизиты: **[ИНН (при наличии), иные сведения]** + +**Адрес для обращений по вопросам обработки персональных данных: [email].** diff --git a/docs/TERMS.md b/docs/TERMS.md new file mode 100644 index 0000000..286b2db --- /dev/null +++ b/docs/TERMS.md @@ -0,0 +1,245 @@ +# ПОЛЬЗОВАТЕЛЬСКОЕ СОГЛАШЕНИЕ (ОФЕРТА) + +Сервис «Вечерний детектив» + +**Редакция от «__» ________ 20__ года** + +*Настоящий документ является шаблоном и носит информационный характер. Перед публикацией документ должен быть адаптирован и утверждён квалифицированным юристом.* + +--- + +## 1. Общие положения + +1.1. Настоящее Пользовательское соглашение (далее — **Соглашение**) является публичной офертой (ст. 435, 437 Гражданского кодекса РФ, далее — ГК РФ) и определяет условия использования Сервиса «Вечерний детектив» (далее — **Сервис**), размещённого в сети Интернет по адресу: **[адрес сайта]**. + +1.2. Оператор Сервиса и правообладатель — **[ФИО Оператора]** (далее — **Оператор**). Реквизиты Оператора указаны в разделе 14 Соглашения. + +1.3. Использование Сервиса регулируется: + +- настоящим Соглашением; +- Политикой конфиденциальности и обработки персональных данных (далее — **Политика конфиденциальности**), размещённой по адресу: **[адрес политики]**; +- законодательством Российской Федерации. + +1.4. Соглашение является договором присоединения (ст. 428 ГК РФ). Акцептом Соглашения признаётся совершение Пользователем любого из следующих действий (ст. 438 ГК РФ, ст. 1286 ГК РФ): + +- регистрация учётной записи в Сервисе; +- начало использования Сервиса (в т.ч. вход в Сервис, создание игры, подача заявки на участие, загрузка материалов); +- иное действие, свидетельствующее о принятии условий Соглашения. + +1.5. С момента акцепта Соглашение считается заключённым между Пользователем и Оператором в письменной форме (путём обмена документами в электронном виде) на условиях, изложенных в Соглашении, и действует до прекращения в порядке, предусмотренном Соглашением. + +1.6. Оператор вправе в одностороннем порядке изменять условия Соглашения. Новая редакция Соглашения вступает в силу с момента её опубликования в Сервисе, если иной срок не указан при опубликовании. Продолжение использования Сервиса после вступления в силу новой редакции означает согласие Пользователя с изменениями. + +1.7. Если Пользователь не согласен с условиями Соглашения или его изменениями, он обязан прекратить использование Сервиса. + +1.8. Оператор вправе в любое время без уведомления Пользователя вносить изменения в функциональность Сервиса, добавлять или удалять отдельные функции, изменять их содержание. + +## 2. Термины + +2.1. В целях настоящего Соглашения применяются следующие термины: + +- **Пользователь** — дееспособное физическое лицо, достигшее возраста 18 лет, акцептовавшее Соглашение и использующее Сервис; +- **Учётная запись (аккаунт)** — совокупность данных Пользователя, создаваемая при регистрации в Сервисе, позволяющая идентифицировать Пользователя; +- **Игра** — организованное Оператором или Пользователем мероприятие (детективная игра) в рамках Сервиса; +- **Сценарий** — текстовая и/или мультимедийная основа Игры, создаваемая Оператором или Пользователем; +- **Команда** — объединение Пользователей для участия в Игре; +- **Пользовательский контент** — материалы (тексты, изображения, аудио, видео, сценарии, иные объекты), созданные Пользователем и размещённые им в Сервисе; +- **Личный кабинет** — персонализированный раздел Сервиса, доступный Пользователю после авторизации. + +2.2. Иные термины, не определённые в Соглашении, используются в значениях, установленных законодательством Российской Федерации и Политикой конфиденциальности. + +## 3. Предмет Соглашения + +3.1. Оператор предоставляет Пользователю доступ к Сервису на условиях простой (неисключительной) лицензии (ст. 1235, 1236 ГК РФ), а Пользователь обязуется использовать Сервис способами, предусмотренными Соглашением. + +3.2. Сервис предоставляет Пользователю возможность: + +- регистрироваться и использовать Учётную запись; +- создавать Команды и Игры, подавать заявки на участие в Играх; +- создавать, загружать и использовать Сценарии и иной Пользовательский контент; +- взаимодействовать с другими Пользователями в рамках Сервиса; +- использовать иные функции Сервиса по мере их появления. + +3.3. Способы использования Сервиса (ст. 1235 п. 2 ГК РФ): воспроизведение программного обеспечения Сервиса в объёме, необходимом для доступа к Сервису через сеть Интернет, и использование функций Сервиса в соответствии с его назначением. Пользователю не предоставляются права на изменение, распространение, модификацию программного обеспечения Сервиса. + +## 4. Условия регистрации и Учётная запись + +4.1. Регистрация в Сервисе возможна только для физических лиц, достигших возраста 18 лет. Использование Сервиса лицами, не достигшими 18 лет, запрещено. Регистрируясь, Пользователь подтверждает, что достиг 18 лет и имеет право заключать Соглашение. + +4.2. При регистрации Пользователь предоставляет достоверные данные: адрес электронной почты и иные сведения, запрашиваемые Сервисом. Пользователь несёт ответственность за достоверность предоставленных данных. + +4.3. Пароль для доступа к Учётной записи направляется Пользователю на адрес электронной почты, указанный при регистрации. Пользователь обязан: + +- обеспечить сохранность пароля и не передавать его третьим лицам; +- незамедлительно уведомить Оператора о любом несанкционированном доступе к Учётной записи; +- принимать разумные меры для защиты Учётной записи от несанкционированного доступа. + +4.4. Пользователь несёт ответственность за все действия, совершённые с использованием его Учётной записи, если он не докажет, что действия совершены без его участия вследствие обстоятельств непреодолимой силы или вины Оператора. + +4.5. Оператор вправе заблокировать или удалить Учётную запись Пользователя (полностью или частично), а также ограничить доступ к Сервису, в случае нарушения Пользователем условий Соглашения, требований законодательства, а также по иным основаниям, предусмотренным Соглашением. Оператор вправе удалить Учётную запись, не использовавшуюся Пользователем в течение **[12]** месяцев. + +4.6. Учётная запись не может быть передана или отчуждена третьим лицам, за исключением случаев, предусмотренных законом или прямо разрешённых Оператором. + +## 5. Права и обязанности Пользователя + +5.1. Пользователь вправе: + +- использовать Сервис в соответствии с Соглашением и его назначением; +- создавать Пользовательский контент и размещать его в Сервисе; +- обращаться к Оператору по вопросам функционирования Сервиса; +- реализовывать иные права, предусмотренные Соглашением и законодательством. + +5.2. Пользователь обязуется: + +- соблюдать условия Соглашения, Политики конфиденциальности и требования законодательства РФ; +- не использовать Сервис для целей, противоречащих законодательству; +- не совершать действий, направленных на нарушение функционирования Сервиса, его программного обеспечения, баз данных; +- не пытаться получить несанкционированный доступ к Сервису, его системам и данным других Пользователей; +- не использовать автоматизированные средства (боты, скрипты, парсеры) для взаимодействия с Сервисом без предварительного письменного разрешения Оператора; +- не размещать в Сервисе материалы, перечисленные в разделе 6 Соглашения; +- не воспроизводить, не копировать, не изменять, не декомпилировать, не дизассемблировать программное обеспечение Сервиса, за исключением случаев, прямо разрешённых законом (ст. 1280 ГК РФ); +- не использовать Сервис для обхода или нарушения прав третьих лиц, включая права на объекты интеллектуальной собственности. + +## 6. Запрещённый контент и правила поведения + +6.1. В Сервисе запрещено размещение Пользовательского контента, который: + +- нарушает законодательство РФ, в т.ч. авторские и смежные права, права на товарные знаки, иные права третьих лиц; +- содержит порнографические материалы, а также материалы сексуального характера с участием несовершеннолетних; +- содержит призывы к насилию, экстремизму, терроризму, разжигание национальной, расовой, религиозной или иной розни; +- содержит клевету, оскорбления, угрозы, преследование или иным образом нарушает права других лиц; +- содержит пропаганду наркотических средств, алкоголя, азартных игр (в запрещённых законом формах); +- содержит вредоносные программы, вирусы, ссылки на них; +- нарушает права несовершеннолетних; +- иным образом противоречит целям Сервиса и принципам добросовестности. + +6.2. Оператор вправе, но не обязан, осуществлять модерацию Пользовательского контента. Оператор вправе удалить любой Пользовательский контент, нарушающий условия Соглашения или законодательство, без предварительного уведомления Пользователя, а также заблокировать или удалить Учётную запись нарушителя. + +6.3. Пользователь самостоятельно несёт ответственность за размещаемый им Пользовательский контент, включая его законность, достоверность и соответствие правам третьих лиц. + +## 7. Пользовательский контент и права на него + +7.1. Личные неимущественные права на Пользовательский контент (право авторства, право на имя) сохраняются за автором и не могут быть отчуждены (ст. 1228, 1265 ГК РФ). + +7.2. Переводя Сценарий в статус «опубликован» (публикуя Сценарий в Сервисе), Пользователь безвозмездно отчуждает Оператору принадлежащее ему исключительное право на такой Сценарий в полном объёме (ст. 1234 ГК РФ). Настоящий договор об отчуждении исключительного права является **безвозмездным**. Исключительное право переходит к Оператору в момент перевода Сценария в статус «опубликован» (ст. 1234 п. 4 ГК РФ), на весь срок действия исключительного права, на территории всего мира. Ограничение п. 3.1 ст. 1234 ГК РФ не применяется, поскольку Пользователь не является коммерческой организацией. + +7.3. Пользователь соглашается с использованием опубликованных Сценариев Оператором без указания имени автора (анонимно) либо под псевдонимом (никнеймом), указанным Пользователем при регистрации (ст. 1265 п. 1 ГК РФ), в т.ч. после удаления Учётной записи Пользователя. + +7.4. Сценарии, не переведённые в статус «опубликован» (черновики), не отчуждаются: Пользователь сохраняет исключительное право на такие Сценарии и вправе свободно их редактировать, изменять и удалять. + +7.5. Пользователь гарантирует, что: + +- он обладает достаточными правами на размещаемый Пользовательский контент (является автором и/или правообладателем либо имеет разрешение правообладателя); +- размещение контента не нарушает прав третьих лиц и законодательства РФ; +- контент не содержит персональных данных третьих лиц без их согласия; +- на момент публикации Сценария он вправе отчуждать исключительное право на него Оператору. + +7.6. Право на отзыв (ст. 1269 ГК РФ) действует только **до фактического обнародования** Сценария. После перевода Сценария в статус «опубликован» Пользователь не вправе отозвать Сценарий, требовать прекращения его использования, удаления или снятия с публикации. Оператор вправе использовать опубликованный Сценарий любыми способами, включая воспроизведение, распространение, переработку, включение в составные и сложные объекты, доведение до всеобщего сведения, предоставление доступа третьим лицам, — без дополнительного согласия Пользователя. + +7.7. При получении претензий третьих лиц в отношении Пользовательского контента Оператор вправе временно ограничить доступ к такому контенту до урегулирования спора и уведомить об этом Пользователя. + +7.8. Удаление Учётной записи Пользователя не прекращает отчуждение исключительного права на опубликованные Сценарии (ст. 1234 п. 1 ГК РФ). При удалении Учётной записи Оператор удаляет персональные данные Пользователя, при этом опубликованные Сценарии сохраняются в Сервисе, а атрибуция автора обезличивается (ст. 3 152-ФЗ, обезличивание) в порядке, предусмотренном п. 7.3 Соглашения. + +## 8. Платные услуги + +8.1. На дату вступления Соглашения в силу Сервис предоставляется Пользователям бесплатно. Отдельные функции Сервиса могут стать платными в будущем. + +8.2. Оператор вправе вводить платные услуги (функции) Сервиса, а также изменять стоимость платных услуг, уведомив Пользователей не менее чем за **[14]** дней путём опубликования соответствующей информации в Сервисе и/или направления уведомления на адрес электронной почты Пользователя. + +8.3. При введении платных услуг условия их предоставления, включая порядок оплаты, сроки, порядок возврата денежных средств, определяются отдельными документами (правилами), размещаемыми в Сервисе. Использование платных услуг означает согласие Пользователя с соответствующими правилами. + +8.4. Если Сервис будет предоставлять платные услуги, отношения между Оператором и Пользователем в части таких услуг регулируются, в т.ч., Законом РФ от 07.02.1992 № 2300-1 «О защите прав потребителей» (далее — Закон о защите прав потребителей) в части, применимой к отношениям сторон. + +## 9. Персональные данные + +9.1. При использовании Сервиса Оператор обрабатывает персональные данные Пользователя (ст. 3 Федерального закона от 27.07.2006 № 152-ФЗ «О персональных данных», далее — 152-ФЗ): адрес электронной почты, имя (псевдоним), данные Учётной записи, сведения о действиях Пользователя в Сервисе, технические данные (IP-адрес, файлы cookie, данные об устройстве), иные данные, указанные в Политике конфиденциальности. + +9.2. Обработка персональных данных осуществляется на основании (ст. 6 152-ФЗ): + +- согласия Пользователя, выраженного при регистрации и/или использовании Сервиса (акцепт Политики конфиденциальности); +- необходимости исполнения Соглашения, стороной которого является Пользователь; +- иных законных оснований. + +9.3. Цели обработки персональных данных: идентификация Пользователя, предоставление доступа к Сервису, обеспечение функционирования Сервиса, связь с Пользователем (в т.ч. направление пароля и уведомлений), улучшение качества Сервиса, исполнение требований законодательства. + +9.4. Оператор обрабатывает персональные данные в соответствии с принципами законности, справедливости, минимизации и ограничения сроков хранения (ст. 5 152-ФЗ), принимает правовые, организационные и технические меры защиты (ст. 19 152-ФЗ). + +9.5. Пользователь вправе: + +- получать информацию о своих персональных данных и их обработке (ст. 14 152-ФЗ); +- требовать уточнения, блокирования, уничтожения персональных данных (ст. 14, 21 152-ФЗ); +- отозвать согласие на обработку персональных данных в любое время (ст. 9 152-ФЗ), направив соответствующее требование Оператору. Отзыв согласия может повлечь невозможность использования Сервиса; +- обжаловать действия Оператора в уполномоченный орган (Роскомнадзор) и в суд (ст. 17 152-ФЗ). + +9.6. Порядок, сроки и условия обработки персональных данных, включая сведения о cookies и аналитике, подробно изложены в Политике конфиденциальности, размещённой по адресу: **[адрес политики]**. + +9.7. Оператор не передаёт персональные данные Пользователя третьим лицам, за исключением случаев, предусмотренных законодательством РФ или прямо указанных в Политике конфиденциальности (в т.ч. техническим подрядчикам, обеспечивающим функционирование Сервиса). + +9.8. Оператор обеспечивает запись, систематизацию, накопление, хранение, уточнение, извлечение персональных данных граждан Российской Федерации с использованием баз данных, находящихся на территории Российской Федерации (ст. 18 ч. 5 152-ФЗ). + +## 10. Интеллектуальная собственность + +10.1. Исключительные права на программное обеспечение Сервиса, его дизайн, интерфейс, логотипы, товарные знаки, тексты, базы данных и иные материалы, созданные Оператором (за исключением Пользовательского контента), принадлежат Оператору (ст. 1225, 1229, 1261 ГК РФ). + +10.2. Использование материалов, указанных в п. 10.1, допускается только в пределах функций Сервиса. Запрещается копирование, распространение, переработка, использование материалов Сервиса вне Сервиса без письменного согласия Оператора, за исключением случаев, предусмотренных законодательством. + +10.3. Пользователь обязуется не нарушать исключительные права Оператора и третьих лиц при использовании Сервиса. При нарушении исключительных прав правообладатель вправе требовать защиты способами, предусмотренными ст. 1252, 1301 ГК РФ. + +10.4. Нарушение условий Соглашения о способах использования Сервиса (раздел 3) является нарушением условий лицензии и может являться основанием для её одностороннего прекращения Оператором (ст. 450.1, 1286.1 ГК РФ). + +## 11. Ответственность сторон + +11.1. За неисполнение или ненадлежащее исполнение обязательств по Соглашению стороны несут ответственность в соответствии с законодательством РФ (ст. 393, 401 ГК РФ). + +11.2. Сервис предоставляется «как есть» (as is). Оператор не гарантирует: + +- бесперебойную и безошибочную работу Сервиса; +- соответствие Сервиса ожиданиям Пользователя; +- сохранность Пользовательского контента (Пользователю рекомендуется создавать резервные копии значимых материалов); +- отсутствие технических сбоев, в т.ч. связанных с работой сети Интернет, хостинга, оборудования. + +11.3. Оператор не несёт ответственности за убытки Пользователя, возникшие в результате: + +- невозможности использования Сервиса по причинам, не зависящим от Оператора; +- действий (бездействия) Пользователя, включая передачу пароля третьим лицам и нарушение требований безопасности; +- действий третьих лиц, включая неправомерный доступ к Учётной записи; +- использования Пользователем Сервиса в целях, не предусмотренных Соглашением. + +11.4. Размер ответственности Оператора по Соглашению ограничивается суммой **[размер, например: фактически уплаченных Пользователем средств за последние 12 месяцев / 10 000 (десять тысяч) рублей]**, за исключением случаев причинения вреда, за которые ограничение ответственности не допускается законом. + +11.5. Оператор не несёт ответственности за действия Пользователей в рамках Игр и за содержание Пользовательского контента. + +11.6. В части платных услуг (раздел 8) положения настоящего раздела применяются с учётом императивных требований Закона о защите прав потребителей. + +## 12. Изменение, приостановление и прекращение Соглашения + +12.1. Оператор вправе приостановить или прекратить предоставление Сервиса (полностью или частично) в любое время, в т.ч. в связи с техническими, юридическими или коммерческими причинами, уведомив Пользователей способами, доступными в Сервисе. + +12.2. Пользователь вправе в одностороннем порядке отказаться от Соглашения в любое время, прекратив использование Сервиса и (или) удалив Учётную запись. + +12.3. Оператор вправе расторгнуть Соглашение в одностороннем порядке при нарушении Пользователем условий Соглашения, в т.ч. в случаях, указанных в п. 4.5 и п. 6.2 Соглашения, без возмещения каких-либо убытков Пользователю, за исключением случаев, предусмотренных законом. + +12.4. При прекращении Соглашения Пользователь утрачивает право использования Сервиса. Положения Соглашения, которые по своему характеру должны продолжать действовать после прекращения (в т.ч. разделы 7, 9, 10, 11, 13), сохраняют силу. + +## 13. Разрешение споров + +13.1. Все споры и разногласия, возникающие из Соглашения или в связи с ним, стороны разрешают путём переговоров. Претензионный порядок обязателен: срок рассмотрения претензии — **[30]** календарных дней с момента её получения. + +13.2. При недостижении согласия спор подлежит рассмотрению в суде по месту нахождения Оператора, за исключением случаев, когда в соответствии с законодательством РФ, в т.ч. Законом о защите прав потребителей, предусмотрена подсудность по выбору Пользователя-потребителя (ст. 17 Закона о защите прав потребителей, ст. 29 ГПК РФ). + +13.3. Применимым правом является право Российской Федерации. + +## 14. Реквизиты Оператора + +**Оператор Сервиса «Вечерний детектив»:** + +- ФИО: **[ФИО Оператора]** +- Адрес: **[адрес]** +- Адрес электронной почты: **[email]** +- Иные реквизиты: **[ИНН (при наличии), иные сведения]** + +**Адрес для обращений по вопросам, связанным с Соглашением и обработкой персональных данных: [email].** + +--- + +*Пользователь подтверждает, что ознакомился с условиями Соглашения, Политикой конфиденциальности, понимает их значение и согласен с ними.* diff --git a/docs/embed.go b/docs/embed.go new file mode 100644 index 0000000..0e3b0cb --- /dev/null +++ b/docs/embed.go @@ -0,0 +1,9 @@ +// Package docs встраивает юридические документы в бинарник и раздаёт их +// по постоянным URL (/terms, /privacy, /consent), на которые сервис +// ссылается при фиксации акцептов соглашений (user_agreements). +package docs + +import "embed" + +//go:embed TERMS.md PRIVACY.md CONSENT.md +var FS embed.FS diff --git a/docs/embed_test.go b/docs/embed_test.go new file mode 100644 index 0000000..08c9d30 --- /dev/null +++ b/docs/embed_test.go @@ -0,0 +1,16 @@ +package docs + +import "testing" + +func TestLegalDocsEmbedded(t *testing.T) { + for _, name := range []string{"TERMS.md", "PRIVACY.md", "CONSENT.md"} { + data, err := FS.ReadFile(name) + if err != nil { + t.Errorf("документ %s не встроен: %v", name, err) + continue + } + if len(data) == 0 { + t.Errorf("документ %s пустой", name) + } + } +} diff --git a/internal/app/client_info_test.go b/internal/app/client_info_test.go new file mode 100644 index 0000000..27a03e1 --- /dev/null +++ b/internal/app/client_info_test.go @@ -0,0 +1,96 @@ +package app + +import ( + "context" + "testing" + + "google.golang.org/grpc/metadata" +) + +func TestClientInfoFromContext(t *testing.T) { + tests := []struct { + name string + md metadata.MD + wantIP string + wantUserAgent string + }{ + { + name: "нет метаданных", + wantIP: "", + wantUserAgent: "", + }, + { + name: "x-forwarded-for через gateway: берём последний элемент", + md: metadata.MD{ + "x-forwarded-for": []string{"203.0.113.1, 198.51.100.7"}, + "grpcgateway-user-agent": []string{"Mozilla/5.0 (test)"}, + }, + wantIP: "198.51.100.7", + wantUserAgent: "Mozilla/5.0 (test)", + }, + { + name: "x-real-ip от доверенного прокси приоритетнее x-forwarded-for", + md: metadata.MD{ + "x-real-ip": []string{"192.0.2.10"}, + "x-forwarded-for": []string{"203.0.113.1, 10.0.0.1"}, + "grpcgateway-user-agent": []string{"curl/8.0"}, + }, + wantIP: "192.0.2.10", + wantUserAgent: "curl/8.0", + }, + { + name: "x-real-ip пустой — фолбэк на x-forwarded-for", + md: metadata.MD{ + "x-real-ip": []string{" "}, + "x-forwarded-for": []string{"203.0.113.5"}, + }, + wantIP: "203.0.113.5", + }, + { + name: "user-agent для прямого gRPC-клиента", + md: metadata.MD{ + "user-agent": []string{"grpc-go/1.60"}, + }, + wantUserAgent: "grpc-go/1.60", + }, + { + name: "x-forwarded-for с пробелами после запятых", + md: metadata.MD{ + "x-forwarded-for": []string{"203.0.113.1 , 198.51.100.7 "}, + }, + wantIP: "198.51.100.7", + }, + { + name: "невалидный x-real-ip — фолбэк на валидный x-forwarded-for", + md: metadata.MD{ + "x-real-ip": []string{"not-an-ip; drop me"}, + "x-forwarded-for": []string{"203.0.113.1, 198.51.100.7"}, + }, + wantIP: "198.51.100.7", + }, + { + name: "все источники невалидны — IP пустой (спуфинг)", + md: metadata.MD{ + "x-real-ip": []string{"not-an-ip; drop me"}, + "x-forwarded-for": []string{"256.256.256.256"}, + }, + wantIP: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var ctx context.Context = context.Background() + if tt.md != nil { + ctx = metadata.NewIncomingContext(ctx, tt.md) + } + ip, userAgent := clientInfoFromContext(ctx) + if ip != tt.wantIP { + t.Errorf("ip = %q, want %q", ip, tt.wantIP) + } + if userAgent != tt.wantUserAgent { + t.Errorf("userAgent = %q, want %q", userAgent, tt.wantUserAgent) + } + }) + } +} diff --git a/internal/app/legal_docs_test.go b/internal/app/legal_docs_test.go new file mode 100644 index 0000000..84a3c84 --- /dev/null +++ b/internal/app/legal_docs_test.go @@ -0,0 +1,65 @@ +package app + +import ( + "context" + "strings" + "testing" + + proto "evening_detective_server/proto" +) + +func TestGetLegalDocs(t *testing.T) { + s := &server{} + + tests := []struct { + name string + call func() (text, errText string) + wantPart string + }{ + { + name: "GetTerms отдаёт Пользовательское соглашение", + call: func() (string, string) { + rsp, err := s.GetTerms(context.Background(), &proto.GetTermsReq{}) + if err != nil { + t.Fatalf("GetTerms error: %v", err) + } + return rsp.Text, rsp.Error + }, + wantPart: "СОГЛАШЕНИЕ", + }, + { + name: "GetPrivacy отдаёт Политику конфиденциальности", + call: func() (string, string) { + rsp, err := s.GetPrivacy(context.Background(), &proto.GetPrivacyReq{}) + if err != nil { + t.Fatalf("GetPrivacy error: %v", err) + } + return rsp.Text, rsp.Error + }, + wantPart: "КОНФИДЕНЦИАЛЬНОСТИ", + }, + { + name: "GetConsent отдаёт текст согласия на обработку ПДн", + call: func() (string, string) { + rsp, err := s.GetConsent(context.Background(), &proto.GetConsentReq{}) + if err != nil { + t.Fatalf("GetConsent error: %v", err) + } + return rsp.Text, rsp.Error + }, + wantPart: "СОГЛАСИЕ", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + text, errText := tt.call() + if errText != "" { + t.Fatalf("ожидался успех, получена ошибка: %s", errText) + } + if !strings.Contains(text, tt.wantPart) { + t.Errorf("текст документа не содержит %q", tt.wantPart) + } + }) + } +} diff --git a/internal/app/server.go b/internal/app/server.go index aec0061..aea5d1f 100644 --- a/internal/app/server.go +++ b/internal/app/server.go @@ -2,6 +2,10 @@ package app import ( "context" + "net/netip" + "strings" + + "evening_detective_server/docs" "evening_detective_server/internal/modules/file_storage" "evening_detective_server/internal/modules/processor_jwt" "evening_detective_server/internal/modules/roles" @@ -14,6 +18,7 @@ import ( "google.golang.org/genproto/googleapis/api/httpbody" "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" ) @@ -52,7 +57,16 @@ func (s *server) Echo(_ context.Context, req *proto.EchoReq) (*proto.EchoRsp, er } func (s *server) Signup(ctx context.Context, req *proto.SignupReq) (*proto.SignupRsp, error) { - err := s.usersService.AddUser(ctx, req.Username, req.Email) + ip, userAgent := clientInfoFromContext(ctx) + err := s.usersService.AddUser( + ctx, + req.Username, + req.Email, + req.AcceptTerms, + req.AcceptPrivacy, + ip, + userAgent, + ) if err != nil { return &proto.SignupRsp{ Error: err.Error(), @@ -61,6 +75,115 @@ func (s *server) Signup(ctx context.Context, req *proto.SignupReq) (*proto.Signu return &proto.SignupRsp{}, nil } +func (s *server) DeleteAccount(ctx context.Context, req *proto.DeleteAccountReq) (*proto.DeleteAccountRsp, error) { + claims, ok := ctx.Value("claims").(*processor_jwt.JWTClaims) + if !ok { + return nil, status.Errorf(codes.Unauthenticated, "claims is not provided") + } + // Пароль приходит HTTP-заголовком X-Password (пробрасывается матчером + // в main.go), чтобы креденшел не попадал в URL и логи. Для прямых + // gRPC-клиентов заголовок передаётся в metadata под тем же ключом. + password := "" + if md, ok := metadata.FromIncomingContext(ctx); ok { + if values := md.Get("x-password"); len(values) > 0 { + password = values[0] + } + } + err := s.usersService.DeleteAccount(ctx, claims.UserID, password) + if err != nil { + return &proto.DeleteAccountRsp{ + Error: err.Error(), + }, nil + } + return &proto.DeleteAccountRsp{}, nil +} + +// GetTerms возвращает текст Пользовательского соглашения (постоянный URL +// /terms, на который ссылается форма регистрации при акцепте). +func (s *server) GetTerms(_ context.Context, _ *proto.GetTermsReq) (*proto.GetTermsRsp, error) { + text, err := docs.FS.ReadFile("TERMS.md") + if err != nil { + return &proto.GetTermsRsp{Error: "Не удалось получить документ"}, nil + } + return &proto.GetTermsRsp{Text: string(text)}, nil +} + +// GetPrivacy возвращает текст Политики конфиденциальности (постоянный URL +// /privacy). +func (s *server) GetPrivacy(_ context.Context, _ *proto.GetPrivacyReq) (*proto.GetPrivacyRsp, error) { + text, err := docs.FS.ReadFile("PRIVACY.md") + if err != nil { + return &proto.GetPrivacyRsp{Error: "Не удалось получить документ"}, nil + } + return &proto.GetPrivacyRsp{Text: string(text)}, nil +} + +// GetConsent возвращает текст согласия на обработку персональных данных +// (постоянный URL /consent). +func (s *server) GetConsent(_ context.Context, _ *proto.GetConsentReq) (*proto.GetConsentRsp, error) { + text, err := docs.FS.ReadFile("CONSENT.md") + if err != nil { + return &proto.GetConsentRsp{Error: "Не удалось получить документ"}, nil + } + return &proto.GetConsentRsp{Text: string(text)}, nil +} + +// clientInfoFromContext извлекает IP-адрес и user-agent из gRPC-метаданных. +// +// grpc-gateway пробрасывает HTTP-заголовки в метаданные так +// (runtime.annotateContext / runtime.DefaultHeaderMatcher): +// - x-forwarded-for — всегда, при этом gateway дописывает реальный RemoteAddr +// клиента последним элементом списка; +// - постоянные HTTP-заголовки (включая User-Agent) — с префиксом +// grpcgateway-; +// - остальные заголовки по умолчанию не пробрасываются: X-Real-IP и +// X-Password включаются явным матчером в main.go. +// +// Полученный IP валидируется netip.ParseAddr: при прямой экспозиции gateway +// клиент может подделать эти заголовки, поэтому в БД попадает только +// корректный адрес. +func clientInfoFromContext(ctx context.Context) (ip string, userAgent string) { + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return "", "" + } + + // X-Real-IP от доверенного прокси — приоритетен: в этом случае последним + // элементом X-Forwarded-For является адрес прокси, а не клиента. + if values := md.Get("x-real-ip"); len(values) > 0 { + if v := strings.TrimSpace(values[0]); v != "" { + if _, err := netip.ParseAddr(v); err == nil { + ip = v + } + } + } + if ip == "" { + if values := md.Get("x-forwarded-for"); len(values) > 0 { + parts := strings.Split(values[0], ",") + // Идём с конца списка: последний элемент — реальный RemoteAddr + // клиента (первые элементы мог подделать сам клиент). + for i := len(parts) - 1; i >= 0; i-- { + v := strings.TrimSpace(parts[i]) + if v == "" { + continue + } + if _, err := netip.ParseAddr(v); err == nil { + ip = v + break + } + } + } + } + + if values := md.Get("grpcgateway-user-agent"); len(values) > 0 { + userAgent = values[0] + } else if values := md.Get("user-agent"); len(values) > 0 { + userAgent = values[0] + } + + return ip, userAgent +} + func (s *server) RefreshPassword(ctx context.Context, req *proto.RefreshPasswordReq) (*proto.RefreshPasswordRsp, error) { err := s.usersService.RefreshPassword(ctx, req.Email) if err != nil { @@ -299,6 +422,8 @@ func (s *server) UpdateScenario(ctx context.Context, req *proto.UpdateScenarioRe req.Name, req.Description, req.Image, + claims.UserID, + roles.HasRole(claims, roles.Admin), ) if err != nil { return &proto.UpdateScenarioRsp{ @@ -319,6 +444,8 @@ func (s *server) PublicScenario(ctx context.Context, req *proto.PublicScenarioRe ctx, int(req.Id), "public", + claims.UserID, + roles.HasRole(claims, roles.Admin), // публикация = момент отчуждения прав ) if err != nil { return &proto.PublicScenarioRsp{ @@ -331,7 +458,10 @@ func (s *server) PublicScenario(ctx context.Context, req *proto.PublicScenarioRe func (s *server) DraftScenario(ctx context.Context, req *proto.DraftScenarioReq) (*proto.DraftScenarioRsp, error) { claims := ctx.Value("claims").(*processor_jwt.JWTClaims) - if !roles.HasRole(claims, roles.Author) { + // Снять с публикации опубликованный сценарий может только админ: + // исключительное право отчуждено Оператору в момент публикации + // (п. 7.2 Пользовательского соглашения, ст. 1234, 1269 ГК РФ). + if !roles.HasRole(claims, roles.Admin) { return nil, status.Errorf(codes.PermissionDenied, "permission denied") } @@ -339,6 +469,8 @@ func (s *server) DraftScenario(ctx context.Context, req *proto.DraftScenarioReq) ctx, int(req.Id), "draft", + claims.UserID, + true, ) if err != nil { return &proto.DraftScenarioRsp{ @@ -355,9 +487,13 @@ func (s *server) DeleteScenario(ctx context.Context, req *proto.DeleteScenarioRe return nil, status.Errorf(codes.PermissionDenied, "permission denied") } + // Автор не может удалить опубликованный сценарий (исключительное право + // отчуждено); админ может. err := s.scenarioService.DeleteScenarioByID( ctx, int(req.Id), + claims.UserID, + roles.HasRole(claims, roles.Admin), ) if err != nil { return &proto.DeleteScenarioRsp{ @@ -378,6 +514,8 @@ func (s *server) AddScenarioPlace(ctx context.Context, req *proto.AddScenarioPla ctx, int(req.Id), convertPlace(req.Place), + claims.UserID, + roles.HasRole(claims, roles.Admin), ) if err != nil { return &proto.AddScenarioPlaceRsp{ @@ -399,6 +537,8 @@ func (s *server) UpdateScenarioPlace(ctx context.Context, req *proto.UpdateScena int(req.Id), req.Code, convertPlace(req.Place), + claims.UserID, + roles.HasRole(claims, roles.Admin), ) if err != nil { return &proto.UpdateScenarioPlaceRsp{ @@ -419,6 +559,8 @@ func (s *server) DeleteScenarioPlace(ctx context.Context, req *proto.DeleteScena ctx, int(req.Id), req.Code, + claims.UserID, + roles.HasRole(claims, roles.Admin), ) if err != nil { return &proto.DeleteScenarioPlaceRsp{ diff --git a/internal/app/user_mapper.go b/internal/app/user_mapper.go index 89dabda..59e7cf0 100644 --- a/internal/app/user_mapper.go +++ b/internal/app/user_mapper.go @@ -7,7 +7,13 @@ import ( "google.golang.org/protobuf/types/known/timestamppb" ) +// mapUser преобразует пользователя в proto-структуру. Возвращает nil для +// обезличенного автора (аккаунт удалён, контент сохранён) — клиент отображает +// такого автора как «Автор удалён». func mapUser(o *repos.User) *proto.User { + if o == nil { + return nil + } return &proto.User{ Id: int32(o.ID), Username: o.Username, diff --git a/internal/app/user_mapper_test.go b/internal/app/user_mapper_test.go new file mode 100644 index 0000000..d69710c --- /dev/null +++ b/internal/app/user_mapper_test.go @@ -0,0 +1,37 @@ +package app + +import ( + "testing" + "time" + + "evening_detective_server/internal/repos" +) + +func TestMapUser(t *testing.T) { + t.Run("nil — обезличенный автор, возвращает nil", func(t *testing.T) { + if got := mapUser(nil); got != nil { + t.Errorf("mapUser(nil) = %v, want nil", got) + } + }) + + t.Run("обычный пользователь маппится полностью", func(t *testing.T) { + u := &repos.User{ + ID: 42, + Username: "detective", + Email: "d@example.com", + Roles: []string{"user"}, + IsActive: true, + CreatedAt: time.Date(2026, 8, 18, 12, 0, 0, 0, time.UTC), + } + got := mapUser(u) + if got == nil { + t.Fatal("mapUser вернул nil для не-nil пользователя") + } + if got.Id != 42 || got.Username != "detective" || got.Email != "d@example.com" { + t.Errorf("неожиданный маппинг: %+v", got) + } + if len(got.Roles) != 1 || got.Roles[0] != "user" { + t.Errorf("roles = %v, want [user]", got.Roles) + } + }) +} diff --git a/internal/repos/scenarios_repo/repo.go b/internal/repos/scenarios_repo/repo.go index 639b468..228b91e 100644 --- a/internal/repos/scenarios_repo/repo.go +++ b/internal/repos/scenarios_repo/repo.go @@ -75,17 +75,17 @@ func (r *ScenariosRepo) GetScenariosByAuthorID( var scenarios []*repos.Scenario for rows.Next() { - scenario := &repos.Scenario{ - Author: &repos.User{}, - } + scenario := &repos.Scenario{} + var authorID *int + var authorUsername *string err := rows.Scan( &scenario.ID, &scenario.Name, &scenario.Description, &scenario.Image, &scenario.Scenario, - &scenario.Author.ID, - &scenario.Author.Username, + &authorID, + &authorUsername, &scenario.Status, &scenario.UpdatedAt, &scenario.CreatedAt, @@ -94,6 +94,9 @@ func (r *ScenariosRepo) GetScenariosByAuthorID( if err != nil { return nil, err } + if authorID != nil && authorUsername != nil { + scenario.Author = &repos.User{ID: *authorID, Username: *authorUsername} + } scenarios = append(scenarios, scenario) } if err := rows.Err(); err != nil { @@ -134,17 +137,17 @@ func (r *ScenariosRepo) GetScenariosByStatus( var scenarios []*repos.Scenario for rows.Next() { - scenario := &repos.Scenario{ - Author: &repos.User{}, - } + scenario := &repos.Scenario{} + var authorID *int + var authorUsername *string err := rows.Scan( &scenario.ID, &scenario.Name, &scenario.Description, &scenario.Image, &scenario.Scenario, - &scenario.Author.ID, - &scenario.Author.Username, + &authorID, + &authorUsername, &scenario.Status, &scenario.UpdatedAt, &scenario.CreatedAt, @@ -153,6 +156,9 @@ func (r *ScenariosRepo) GetScenariosByStatus( if err != nil { return nil, err } + if authorID != nil && authorUsername != nil { + scenario.Author = &repos.User{ID: *authorID, Username: *authorUsername} + } scenarios = append(scenarios, scenario) } if err := rows.Err(); err != nil { @@ -166,9 +172,9 @@ func (r *ScenariosRepo) GetScenarioByID( ctx context.Context, id int, ) (*repos.Scenario, error) { - scenario := &repos.Scenario{ - Author: &repos.User{}, - } + scenario := &repos.Scenario{} + var authorID *int + var authorUsername *string row := r.pool.QueryRow( ctx, `SELECT @@ -195,8 +201,8 @@ func (r *ScenariosRepo) GetScenarioByID( &scenario.Description, &scenario.Image, &scenario.Scenario, - &scenario.Author.ID, - &scenario.Author.Username, + &authorID, + &authorUsername, &scenario.Status, &scenario.UpdatedAt, &scenario.CreatedAt, @@ -210,9 +216,15 @@ func (r *ScenariosRepo) GetScenarioByID( return nil, err } + // Автор может отсутствовать (обезличен после удаления аккаунта). + if authorID != nil && authorUsername != nil { + scenario.Author = &repos.User{ID: *authorID, Username: *authorUsername} + } + return scenario, nil } +// UpdateScenarioByID меняет основные поля сценария. func (r *ScenariosRepo) UpdateScenarioByID( ctx context.Context, id int, @@ -243,50 +255,61 @@ func (r *ScenariosRepo) UpdateScenarioByID( return nil } +// UpdateScenarioStatusByID меняет статус сценария. allowPublished=true +// разрешает менять статус опубликованного сценария (только для админа). +// Возвращает false, если строка не обновлена (например, не-админ пытается +// снять с публикации опубликованный сценарий). published_at фиксируется +// только при ПЕРВОЙ публикации: повторная публикация не двигает «момент +// отчуждения» исключительного права (п. 7.2 Пользовательского соглашения). func (r *ScenariosRepo) UpdateScenarioStatusByID( ctx context.Context, id int, status string, -) error { + allowPublished bool, +) (bool, error) { tag, err := r.pool.Exec( ctx, `UPDATE scenarios SET status = $1, - published_at = NOW(), + published_at = CASE + WHEN $1 = 'public' AND published_at IS NULL THEN NOW() + ELSE published_at + END, updated_at = NOW() - WHERE id = $2`, + WHERE id = $2 AND ($3 OR status <> 'public')`, status, id, + allowPublished, ) if err != nil { - return err + return false, err } - if tag.RowsAffected() == 0 { - return ErrScenarioNotFound - } - return nil + return tag.RowsAffected() > 0, nil } +// DeleteScenarioByID помечает сценарий удалённым (soft delete). +// allowPublished=true разрешает удаление опубликованного сценария +// (только для админа). Возвращает false, если строка не обновлена +// (например, не-админ пытается удалить опубликованный сценарий). func (r *ScenariosRepo) DeleteScenarioByID( ctx context.Context, id int, -) error { + allowPublished bool, +) (bool, error) { tag, err := r.pool.Exec( ctx, `UPDATE scenarios SET is_deleted = TRUE - WHERE id = $1`, + WHERE id = $1 AND ($2 OR status <> 'public')`, id, + allowPublished, ) if err != nil { - return err + return false, err } - if tag.RowsAffected() == 0 { - return ErrScenarioNotFound - } - return nil + return tag.RowsAffected() > 0, nil } func (r *ScenariosRepo) GetStoryByScenarioID( @@ -315,6 +338,7 @@ func (r *ScenariosRepo) GetStoryByScenarioID( return story, nil } +// UpdateStoryByScenarioID обновляет содержимое (историю) сценария. func (r *ScenariosRepo) UpdateStoryByScenarioID( ctx context.Context, id int, diff --git a/internal/repos/user_agreements_repo/repo.go b/internal/repos/user_agreements_repo/repo.go new file mode 100644 index 0000000..f920259 --- /dev/null +++ b/internal/repos/user_agreements_repo/repo.go @@ -0,0 +1,18 @@ +package user_agreements_repo + +// AgreementType — типы документов, акцептуемых пользователем. +const ( + AgreementTypeTerms = "terms" // Пользовательское соглашение + AgreementTypePrivacy = "privacy" // Политика конфиденциальности +) + +// Agreement — фиксируемый факт акцепта документа (ст. 9 152-ФЗ — согласие в +// форме, позволяющей подтвердить факт его получения). Version должна +// соответствовать опубликованной редакции документа; при изменении текста +// документа версия обязана увеличиваться. +type Agreement struct { + AgreementType string + Version string + IP string + UserAgent string +} diff --git a/internal/repos/users_repo/repo.go b/internal/repos/users_repo/repo.go index cc64048..cb8e46a 100644 --- a/internal/repos/users_repo/repo.go +++ b/internal/repos/users_repo/repo.go @@ -4,9 +4,11 @@ import ( "context" "errors" "evening_detective_server/internal/repos" + "evening_detective_server/internal/repos/user_agreements_repo" "fmt" "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgconn" "github.com/jackc/pgx/v5/pgxpool" ) @@ -24,21 +26,40 @@ func NewUserRepo(pool *pgxpool.Pool) *UsersRepo { } } -func (s *UsersRepo) AddUser( +// AddUserWithAgreements создаёт пользователя и фиксирует акцепты документов +// (user_agreements) в одной транзакции: пользователь либо существует вместе с +// записями о согласиях, либо не существует вовсе (доказуемое согласие, +// ст. 9 152-ФЗ). Возвращает id созданного пользователя. +func (s *UsersRepo) AddUserWithAgreements( ctx context.Context, username string, email string, passwordHash string, roles []string, -) error { - tag, err := s.pool.Exec( + agreements []user_agreements_repo.Agreement, +) (int, error) { + // Инвариант «пользователь не существует без записей о согласиях» + // держится на том, что акцепты передаются всегда. + if len(agreements) == 0 { + return 0, errors.New("Не переданы записи об акцепте соглашений") + } + + tx, err := s.pool.Begin(ctx) + if err != nil { + return 0, err + } + defer tx.Rollback(ctx) //nolint:errcheck + + var id int + err = tx.QueryRow( ctx, `INSERT INTO users (username, email, password_hash, roles) SELECT $1, $2, $3, $4 WHERE NOT EXISTS ( SELECT 1 FROM users WHERE username = $5 OR email = $6 - )`, + ) + RETURNING id`, username, email, passwordHash, @@ -46,14 +67,41 @@ func (s *UsersRepo) AddUser( username, email, - ) + ).Scan(&id) if err != nil { - return err + // Ничего не вставлено — занят username или email. + if errors.Is(err, pgx.ErrNoRows) { + return 0, errors.New("Username или email уже используется") + } + // Гонка: между проверкой NOT EXISTS и INSERT другой запрос успел + // создать пользователя с тем же username/email — нарушение + // уникальности. Возвращаем тот же понятный клиенту ответ. + var pgErr *pgconn.PgError + if errors.As(err, &pgErr) && pgErr.Code == "23505" { // unique_violation + return 0, errors.New("Username или email уже используется") + } + return 0, err } - if tag.RowsAffected() == 0 { - return errors.New("username или email уже используется") + + for _, agreement := range agreements { + if _, err = tx.Exec( + ctx, + `INSERT INTO user_agreements (user_id, agreement_type, version, ip, user_agent) + VALUES ($1, $2, $3, $4, $5)`, + id, + agreement.AgreementType, + agreement.Version, + agreement.IP, + agreement.UserAgent, + ); err != nil { + return 0, err + } } - return nil + + if err = tx.Commit(ctx); err != nil { + return 0, err + } + return id, nil } func (s *UsersRepo) UpdateUserPassword( @@ -207,3 +255,62 @@ func (s *UsersRepo) DeleteUserRole( ) return err } + +// DeleteUser удаляет учётную запись и персональные данные пользователя +// (ст. 21 152-ФЗ — уничтожение ПДн при удалении аккаунта). Выполняется в одной +// транзакции. Публичный контент пользователя (сценарии, команды) сохраняется: +// FK-ограничения с ON DELETE SET NULL (миграция +// 20260818232725_keep_content_on_user_delete.sql) обнуляют привязку к автору — +// контент остаётся в обезличенном виде. +func (s *UsersRepo) DeleteUser( + ctx context.Context, + userId int, +) error { + tx, err := s.pool.Begin(ctx) + if err != nil { + return err + } + defer tx.Rollback(ctx) //nolint:errcheck + + // Refresh-токены (FK CASCADE, удаляем явно для предсказуемости). + if _, err = tx.Exec( + ctx, + `DELETE FROM refresh_tokens WHERE user_id = $1`, + userId, + ); err != nil { + return err + } + + // Зафиксированные акцепты соглашений НЕ удаляются: ст. 9 ч. 4 152-ФЗ + // возлагает на оператора бремя доказывания получения согласия, поэтому + // факт акцепта (документ, версия, время) сохраняется в обезличенном виде: + // ссылка на пользователя и персональные данные внутри записи (ip, + // user_agent) обнуляются. FK ON DELETE SET NULL (миграция + // 20260818231943_create_user_agreements_table.sql) гарантирует, что при + // удалении users строки акцептов остаются с user_id = NULL. + if _, err = tx.Exec( + ctx, + `UPDATE user_agreements + SET user_id = NULL, ip = NULL, user_agent = NULL + WHERE user_id = $1`, + userId, + ); err != nil { + return err + } + + // Пользователь. Связанные сценарии (author_id) и команды (creator_id) + // обнуляются автоматически через ON DELETE SET NULL. + tag, err := tx.Exec( + ctx, + `DELETE FROM users WHERE id = $1`, + userId, + ) + if err != nil { + return err + } + if tag.RowsAffected() == 0 { + return ErrUserNotFound + } + + return tx.Commit(ctx) +} diff --git a/internal/services/scenarios_service/service.go b/internal/services/scenarios_service/service.go index 878802e..e0106c8 100644 --- a/internal/services/scenarios_service/service.go +++ b/internal/services/scenarios_service/service.go @@ -5,6 +5,7 @@ import ( "errors" "evening_detective_server/internal/modules/cleaner" "evening_detective_server/internal/modules/storytelling" + "evening_detective_server/internal/repos" "evening_detective_server/internal/repos/scenarios_repo" "strings" ) @@ -88,30 +89,111 @@ func (s *ScenarioService) UpdateScenarioByID( name string, description string, image string, + actorId int, + isAdmin bool, ) error { + if _, err := s.getScenarioForChange(ctx, id, actorId, isAdmin); err != nil { + return err + } return s.scenariosRepo.UpdateScenarioByID(ctx, id, name, description, image) } +// ErrScenarioPublished — опубликованный сценарий нельзя снять с публикации +// или удалить: при публикации исключительное право отчуждается Оператору +// (п. 7.2 Пользовательского соглашения, ст. 1234 ГК РФ), а право на отзыв +// действует только до обнародования (ст. 1269 ГК РФ). +var ErrScenarioPublished = errors.New("Опубликованный сценарий нельзя снять с публикации или удалить: исключительное право отчуждено Оператору") + +// ErrScenarioNotOwner — сценарий принадлежит другому пользователю. +var ErrScenarioNotOwner = errors.New("Сценарий принадлежит другому пользователю") + +// getScenarioForChange проверяет права актора на изменение сценария: +// не-админ должен быть автором сценария, сценарий не должен быть удалён. +// Возвращает сценарий, чтобы вызывающий код не делал повторное чтение. +func (s *ScenarioService) getScenarioForChange( + ctx context.Context, + id int, + actorId int, + isAdmin bool, +) (*repos.Scenario, error) { + scenario, err := s.scenariosRepo.GetScenarioByID(ctx, id) + if err != nil { + return nil, err + } + if scenario.IsDeleted { + return nil, scenarios_repo.ErrScenarioNotFound + } + if isAdmin { + return scenario, nil + } + if scenario.Author == nil || scenario.Author.ID != actorId { + return nil, ErrScenarioNotOwner + } + return scenario, nil +} + func (s *ScenarioService) UpdateScenarioStatusByID( ctx context.Context, id int, status string, + actorId int, + isAdmin bool, ) error { - return s.scenariosRepo.UpdateScenarioStatusByID(ctx, id, status) + scenario, err := s.getScenarioForChange(ctx, id, actorId, isAdmin) + if err != nil { + return err + } + if !isAdmin && scenario.Status == "public" { + // Повторная публикация уже опубликованного — идемпотентный успех + // (published_at не двигается: CASE WHEN published_at IS NULL). + if status == "public" { + return nil + } + return ErrScenarioPublished + } + // Guard в SQL защищает от гонки «чтение статуса → запись»: не-админ не + // сможет перевести в draft сценарий, опубликованный между чтением и UPDATE. + updated, err := s.scenariosRepo.UpdateScenarioStatusByID(ctx, id, status, isAdmin) + if err != nil { + return err + } + if !updated { + return ErrScenarioPublished + } + return nil } func (s *ScenarioService) DeleteScenarioByID( ctx context.Context, id int, + actorId int, + isAdmin bool, ) error { - return s.scenariosRepo.DeleteScenarioByID(ctx, id) + if _, err := s.getScenarioForChange(ctx, id, actorId, isAdmin); err != nil { + return err + } + // Guard в SQL защищает от гонки «чтение статуса → запись»: не-админ не + // сможет удалить сценарий, опубликованный между чтением и UPDATE. + updated, err := s.scenariosRepo.DeleteScenarioByID(ctx, id, isAdmin) + if err != nil { + return err + } + if !updated { + return ErrScenarioPublished + } + return nil } func (s *ScenarioService) AddScenarioPlace( ctx context.Context, id int, place *storytelling.Place, + actorId int, + isAdmin bool, ) error { + if _, err := s.getScenarioForChange(ctx, id, actorId, isAdmin); err != nil { + return err + } story, err := s.getStory(ctx, id) if err != nil { return err @@ -128,7 +210,12 @@ func (s *ScenarioService) UpdateScenarioPlace( id int, code string, place *storytelling.Place, + actorId int, + isAdmin bool, ) error { + if _, err := s.getScenarioForChange(ctx, id, actorId, isAdmin); err != nil { + return err + } story, err := s.getStory(ctx, id) if err != nil { return err @@ -146,7 +233,12 @@ func (s *ScenarioService) DeleteScenarioPlace( ctx context.Context, id int, code string, + actorId int, + isAdmin bool, ) error { + if _, err := s.getScenarioForChange(ctx, id, actorId, isAdmin); err != nil { + return err + } story, err := s.getStory(ctx, id) if err != nil { return err diff --git a/internal/services/users_service/service.go b/internal/services/users_service/service.go index ae38e7e..8681a0d 100644 --- a/internal/services/users_service/service.go +++ b/internal/services/users_service/service.go @@ -9,6 +9,7 @@ import ( "evening_detective_server/internal/modules/roles" "evening_detective_server/internal/repos" "evening_detective_server/internal/repos/refresh_tokens_repo" + "evening_detective_server/internal/repos/user_agreements_repo" "evening_detective_server/internal/repos/users_repo" "fmt" "slices" @@ -17,6 +18,17 @@ import ( "golang.org/x/crypto/bcrypt" ) +// Версии документов, акцепт которых фиксируется. Должны совпадать с +// редакциями, опубликованными по постоянным URL (/terms и /privacy, +// rpc GetTerms/GetPrivacy, текст встраивается из пакета docs): при изменении +// текста документа версия ОБЯЗАНА увеличиваться, иначе повторный акцепт +// не будет зафиксирован как согласие с новой редакцией +// (UNIQUE (user_id, agreement_type, version)). +const ( + termsVersion = "1.0" + privacyVersion = "1.0" +) + type UsersService struct { usersRepo *users_repo.UsersRepo passwordGenerator password_generator.IPasswordGenerator @@ -41,11 +53,22 @@ func NewUsersService( } } +// ErrTermsNotAccepted — регистрация невозможна без акцепта соглашений. +var ErrTermsNotAccepted = errors.New("Необходимо принять Пользовательское соглашение и Политику конфиденциальности") + func (s *UsersService) AddUser( ctx context.Context, username string, email string, + acceptTerms bool, + acceptPrivacy bool, + ip string, + userAgent string, ) error { + if !acceptTerms || !acceptPrivacy { + return ErrTermsNotAccepted + } + password, err := s.passwordGenerator.Generate() if err != nil { return err @@ -54,12 +77,28 @@ func (s *UsersService) AddUser( if err != nil { return err } - err = s.usersRepo.AddUser( + // Создание пользователя и фиксация акцептов — в одной транзакции: + // без записей о согласиях пользователь не существует. + _, err = s.usersRepo.AddUserWithAgreements( ctx, username, email, string(hashedPassword), []string{"user"}, + []user_agreements_repo.Agreement{ + { + AgreementType: user_agreements_repo.AgreementTypeTerms, + Version: termsVersion, + IP: ip, + UserAgent: userAgent, + }, + { + AgreementType: user_agreements_repo.AgreementTypePrivacy, + Version: privacyVersion, + IP: ip, + UserAgent: userAgent, + }, + }, ) if err != nil { return err @@ -74,6 +113,24 @@ func (s *UsersService) AddUser( return err } +// DeleteAccount удаляет учётную запись и все персональные данные пользователя +// (ст. 21 152-ФЗ). Требует подтверждения паролем: обладатель украденного +// access-токена не должен мочь удалить чужой аккаунт. +func (s *UsersService) DeleteAccount( + ctx context.Context, + userId int, + password string, +) error { + user, err := s.usersRepo.GetUserByID(ctx, userId) + if err != nil { + return err + } + if err = bcrypt.CompareHashAndPassword([]byte(user.PasswordHash), []byte(password)); err != nil { + return errors.New("Неверный пароль") + } + return s.usersRepo.DeleteUser(ctx, userId) +} + func (s *UsersService) RefreshPassword( ctx context.Context, email string, diff --git a/migrations/20260818231943_create_user_agreements_table.sql b/migrations/20260818231943_create_user_agreements_table.sql new file mode 100644 index 0000000..5078128 --- /dev/null +++ b/migrations/20260818231943_create_user_agreements_table.sql @@ -0,0 +1,26 @@ +-- +goose Up +CREATE TABLE + IF NOT EXISTS user_agreements ( + id SERIAL PRIMARY KEY, + -- user_id NULL-able: при удалении аккаунта FK-ограничение обнуляет + -- ссылку (ON DELETE SET NULL), а сама запись об акцепте остаётся в + -- обезличенном виде (факт согласия, ст. 9 ч. 4 152-ФЗ — бремя + -- доказывания на операторе). Персональные данные внутри записи + -- (ip, user_agent) обнуляет users_repo.DeleteUser. + user_id INTEGER, + agreement_type VARCHAR(50) NOT NULL, + version VARCHAR(50) NOT NULL, + accepted_at TIMESTAMP NOT NULL DEFAULT NOW (), + ip VARCHAR(45), + user_agent TEXT, + + CONSTRAINT fk_user_agreements_user FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE SET NULL, + CONSTRAINT uq_user_agreement UNIQUE (user_id, agreement_type, version), + CONSTRAINT chk_user_agreement_type CHECK (agreement_type IN ('terms', 'privacy')) + ); + +-- Отдельный индекс по user_id не нужен: UNIQUE (user_id, agreement_type, version) +-- уже покрывает выборки по префиксу user_id. + +-- +goose Down +DROP TABLE IF EXISTS user_agreements; diff --git a/migrations/20260818232725_keep_content_on_user_delete.sql b/migrations/20260818232725_keep_content_on_user_delete.sql new file mode 100644 index 0000000..da3df20 --- /dev/null +++ b/migrations/20260818232725_keep_content_on_user_delete.sql @@ -0,0 +1,39 @@ +-- +goose Up +-- Сценарии и команды сохраняются при удалении аккаунта автора: +-- привязка к пользователю обнуляется (обезличивание, ст. 3 152-ФЗ), +-- сам контент остаётся в Сервисе (лицензия по п. 7.2 Пользовательского соглашения). +ALTER TABLE scenarios ALTER COLUMN author_id DROP NOT NULL; + +ALTER TABLE scenarios DROP CONSTRAINT IF EXISTS fk_scenarios_author; +ALTER TABLE scenarios ADD CONSTRAINT fk_scenarios_author + FOREIGN KEY (author_id) REFERENCES users (id) ON DELETE SET NULL; + +ALTER TABLE teams ALTER COLUMN creator_id DROP NOT NULL; + +ALTER TABLE teams DROP CONSTRAINT IF EXISTS fk_teams_creator; +ALTER TABLE teams ADD CONSTRAINT fk_teams_creator + FOREIGN KEY (creator_id) REFERENCES users (id) ON DELETE SET NULL; + +-- status у сценариев всегда задан (default 'draft'): NULL-значение сломало бы +-- guard'ы вида "status <> 'public'" в scenarios_repo (NULL даёт NULL, т.е. ложь). +-- На БД с историческими NULL-данными сначала приводим их к default'у. +UPDATE scenarios SET status = 'draft' WHERE status IS NULL; +ALTER TABLE scenarios ALTER COLUMN status SET NOT NULL; + +-- +goose Down +-- Восстановление прежней схемы: автор обязателен, при удалении пользователя — +-- удаление его контента запрещено (RESTRICT). +DELETE FROM scenarios WHERE author_id IS NULL; +DELETE FROM teams WHERE creator_id IS NULL; + +ALTER TABLE scenarios ALTER COLUMN status DROP NOT NULL; + +ALTER TABLE scenarios DROP CONSTRAINT IF EXISTS fk_scenarios_author; +ALTER TABLE scenarios ADD CONSTRAINT fk_scenarios_author + FOREIGN KEY (author_id) REFERENCES users (id) ON DELETE RESTRICT; +ALTER TABLE scenarios ALTER COLUMN author_id SET NOT NULL; + +ALTER TABLE teams DROP CONSTRAINT IF EXISTS fk_teams_creator; +ALTER TABLE teams ADD CONSTRAINT fk_teams_creator + FOREIGN KEY (creator_id) REFERENCES users (id) ON DELETE RESTRICT; +ALTER TABLE teams ALTER COLUMN creator_id SET NOT NULL; diff --git a/proto/main.pb.go b/proto/main.pb.go index 07e9e18..fbcc610 100644 --- a/proto/main.pb.go +++ b/proto/main.pb.go @@ -189,6 +189,8 @@ type SignupReq struct { state protoimpl.MessageState `protogen:"open.v1"` Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` Email string `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"` + AcceptTerms bool `protobuf:"varint,3,opt,name=accept_terms,json=acceptTerms,proto3" json:"accept_terms,omitempty"` + AcceptPrivacy bool `protobuf:"varint,4,opt,name=accept_privacy,json=acceptPrivacy,proto3" json:"accept_privacy,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -237,6 +239,20 @@ func (x *SignupReq) GetEmail() string { return "" } +func (x *SignupReq) GetAcceptTerms() bool { + if x != nil { + return x.AcceptTerms + } + return false +} + +func (x *SignupReq) GetAcceptPrivacy() bool { + if x != nil { + return x.AcceptPrivacy + } + return false +} + type SignupRsp struct { state protoimpl.MessageState `protogen:"open.v1"` Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` @@ -585,6 +601,356 @@ func (x *RefreshRsp) GetRefreshToken() string { return "" } +// Пароль подтверждает, что удаляет аккаунт его владелец, а не обладатель +// украденного access-токена (ст. 21 152-ФЗ). Передаётся HTTP-заголовком +// X-Password (пробрасывается матчером в cmd/evening_detective_server/main.go), +// чтобы креденшел не попадал в URL/query-параметры и логи. +type DeleteAccountReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteAccountReq) Reset() { + *x = DeleteAccountReq{} + mi := &file_main_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteAccountReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteAccountReq) ProtoMessage() {} + +func (x *DeleteAccountReq) ProtoReflect() protoreflect.Message { + mi := &file_main_proto_msgTypes[12] + 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 DeleteAccountReq.ProtoReflect.Descriptor instead. +func (*DeleteAccountReq) Descriptor() ([]byte, []int) { + return file_main_proto_rawDescGZIP(), []int{12} +} + +type DeleteAccountRsp struct { + state protoimpl.MessageState `protogen:"open.v1"` + Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *DeleteAccountRsp) Reset() { + *x = DeleteAccountRsp{} + mi := &file_main_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *DeleteAccountRsp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteAccountRsp) ProtoMessage() {} + +func (x *DeleteAccountRsp) ProtoReflect() protoreflect.Message { + mi := &file_main_proto_msgTypes[13] + 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 DeleteAccountRsp.ProtoReflect.Descriptor instead. +func (*DeleteAccountRsp) Descriptor() ([]byte, []int) { + return file_main_proto_rawDescGZIP(), []int{13} +} + +func (x *DeleteAccountRsp) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +// Документы раздаются по постоянным URL, на которые ссылается сервис при +// фиксации акцептов соглашений (user_agreements) и форма регистрации. +type GetTermsReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetTermsReq) Reset() { + *x = GetTermsReq{} + mi := &file_main_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetTermsReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTermsReq) ProtoMessage() {} + +func (x *GetTermsReq) ProtoReflect() protoreflect.Message { + mi := &file_main_proto_msgTypes[14] + 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 GetTermsReq.ProtoReflect.Descriptor instead. +func (*GetTermsReq) Descriptor() ([]byte, []int) { + return file_main_proto_rawDescGZIP(), []int{14} +} + +type GetTermsRsp struct { + state protoimpl.MessageState `protogen:"open.v1"` + Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` + Text string `protobuf:"bytes,2,opt,name=text,proto3" json:"text,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetTermsRsp) Reset() { + *x = GetTermsRsp{} + mi := &file_main_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetTermsRsp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTermsRsp) ProtoMessage() {} + +func (x *GetTermsRsp) ProtoReflect() protoreflect.Message { + mi := &file_main_proto_msgTypes[15] + 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 GetTermsRsp.ProtoReflect.Descriptor instead. +func (*GetTermsRsp) Descriptor() ([]byte, []int) { + return file_main_proto_rawDescGZIP(), []int{15} +} + +func (x *GetTermsRsp) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +func (x *GetTermsRsp) GetText() string { + if x != nil { + return x.Text + } + return "" +} + +type GetPrivacyReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetPrivacyReq) Reset() { + *x = GetPrivacyReq{} + mi := &file_main_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetPrivacyReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetPrivacyReq) ProtoMessage() {} + +func (x *GetPrivacyReq) ProtoReflect() protoreflect.Message { + mi := &file_main_proto_msgTypes[16] + 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 GetPrivacyReq.ProtoReflect.Descriptor instead. +func (*GetPrivacyReq) Descriptor() ([]byte, []int) { + return file_main_proto_rawDescGZIP(), []int{16} +} + +type GetPrivacyRsp struct { + state protoimpl.MessageState `protogen:"open.v1"` + Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` + Text string `protobuf:"bytes,2,opt,name=text,proto3" json:"text,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetPrivacyRsp) Reset() { + *x = GetPrivacyRsp{} + mi := &file_main_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetPrivacyRsp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetPrivacyRsp) ProtoMessage() {} + +func (x *GetPrivacyRsp) ProtoReflect() protoreflect.Message { + mi := &file_main_proto_msgTypes[17] + 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 GetPrivacyRsp.ProtoReflect.Descriptor instead. +func (*GetPrivacyRsp) Descriptor() ([]byte, []int) { + return file_main_proto_rawDescGZIP(), []int{17} +} + +func (x *GetPrivacyRsp) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +func (x *GetPrivacyRsp) GetText() string { + if x != nil { + return x.Text + } + return "" +} + +type GetConsentReq struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetConsentReq) Reset() { + *x = GetConsentReq{} + mi := &file_main_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetConsentReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetConsentReq) ProtoMessage() {} + +func (x *GetConsentReq) ProtoReflect() protoreflect.Message { + mi := &file_main_proto_msgTypes[18] + 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 GetConsentReq.ProtoReflect.Descriptor instead. +func (*GetConsentReq) Descriptor() ([]byte, []int) { + return file_main_proto_rawDescGZIP(), []int{18} +} + +type GetConsentRsp struct { + state protoimpl.MessageState `protogen:"open.v1"` + Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` + Text string `protobuf:"bytes,2,opt,name=text,proto3" json:"text,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetConsentRsp) Reset() { + *x = GetConsentRsp{} + mi := &file_main_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetConsentRsp) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetConsentRsp) ProtoMessage() {} + +func (x *GetConsentRsp) ProtoReflect() protoreflect.Message { + mi := &file_main_proto_msgTypes[19] + 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 GetConsentRsp.ProtoReflect.Descriptor instead. +func (*GetConsentRsp) Descriptor() ([]byte, []int) { + return file_main_proto_rawDescGZIP(), []int{19} +} + +func (x *GetConsentRsp) GetError() string { + if x != nil { + return x.Error + } + return "" +} + +func (x *GetConsentRsp) GetText() string { + if x != nil { + return x.Text + } + return "" +} + type GetUsersReq struct { state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields @@ -593,7 +959,7 @@ type GetUsersReq struct { func (x *GetUsersReq) Reset() { *x = GetUsersReq{} - mi := &file_main_proto_msgTypes[12] + mi := &file_main_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -605,7 +971,7 @@ func (x *GetUsersReq) String() string { func (*GetUsersReq) ProtoMessage() {} func (x *GetUsersReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[12] + mi := &file_main_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -618,7 +984,7 @@ func (x *GetUsersReq) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUsersReq.ProtoReflect.Descriptor instead. func (*GetUsersReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{12} + return file_main_proto_rawDescGZIP(), []int{20} } type GetUsersRsp struct { @@ -631,7 +997,7 @@ type GetUsersRsp struct { func (x *GetUsersRsp) Reset() { *x = GetUsersRsp{} - mi := &file_main_proto_msgTypes[13] + mi := &file_main_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -643,7 +1009,7 @@ func (x *GetUsersRsp) String() string { func (*GetUsersRsp) ProtoMessage() {} func (x *GetUsersRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[13] + mi := &file_main_proto_msgTypes[21] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -656,7 +1022,7 @@ func (x *GetUsersRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUsersRsp.ProtoReflect.Descriptor instead. func (*GetUsersRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{13} + return file_main_proto_rawDescGZIP(), []int{21} } func (x *GetUsersRsp) GetError() string { @@ -687,7 +1053,7 @@ type User struct { func (x *User) Reset() { *x = User{} - mi := &file_main_proto_msgTypes[14] + mi := &file_main_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -699,7 +1065,7 @@ func (x *User) String() string { func (*User) ProtoMessage() {} func (x *User) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[14] + mi := &file_main_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -712,7 +1078,7 @@ func (x *User) ProtoReflect() protoreflect.Message { // Deprecated: Use User.ProtoReflect.Descriptor instead. func (*User) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{14} + return file_main_proto_rawDescGZIP(), []int{22} } func (x *User) GetId() int32 { @@ -766,7 +1132,7 @@ type GetUserByIdReq struct { func (x *GetUserByIdReq) Reset() { *x = GetUserByIdReq{} - mi := &file_main_proto_msgTypes[15] + mi := &file_main_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -778,7 +1144,7 @@ func (x *GetUserByIdReq) String() string { func (*GetUserByIdReq) ProtoMessage() {} func (x *GetUserByIdReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[15] + mi := &file_main_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -791,7 +1157,7 @@ func (x *GetUserByIdReq) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUserByIdReq.ProtoReflect.Descriptor instead. func (*GetUserByIdReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{15} + return file_main_proto_rawDescGZIP(), []int{23} } func (x *GetUserByIdReq) GetId() int32 { @@ -811,7 +1177,7 @@ type GetUserByIdRsp struct { func (x *GetUserByIdRsp) Reset() { *x = GetUserByIdRsp{} - mi := &file_main_proto_msgTypes[16] + mi := &file_main_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -823,7 +1189,7 @@ func (x *GetUserByIdRsp) String() string { func (*GetUserByIdRsp) ProtoMessage() {} func (x *GetUserByIdRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[16] + mi := &file_main_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -836,7 +1202,7 @@ func (x *GetUserByIdRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUserByIdRsp.ProtoReflect.Descriptor instead. func (*GetUserByIdRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{16} + return file_main_proto_rawDescGZIP(), []int{24} } func (x *GetUserByIdRsp) GetError() string { @@ -861,7 +1227,7 @@ type GetMeReq struct { func (x *GetMeReq) Reset() { *x = GetMeReq{} - mi := &file_main_proto_msgTypes[17] + mi := &file_main_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -873,7 +1239,7 @@ func (x *GetMeReq) String() string { func (*GetMeReq) ProtoMessage() {} func (x *GetMeReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[17] + mi := &file_main_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -886,7 +1252,7 @@ func (x *GetMeReq) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMeReq.ProtoReflect.Descriptor instead. func (*GetMeReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{17} + return file_main_proto_rawDescGZIP(), []int{25} } type GetMeRsp struct { @@ -899,7 +1265,7 @@ type GetMeRsp struct { func (x *GetMeRsp) Reset() { *x = GetMeRsp{} - mi := &file_main_proto_msgTypes[18] + mi := &file_main_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -911,7 +1277,7 @@ func (x *GetMeRsp) String() string { func (*GetMeRsp) ProtoMessage() {} func (x *GetMeRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[18] + mi := &file_main_proto_msgTypes[26] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -924,7 +1290,7 @@ func (x *GetMeRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMeRsp.ProtoReflect.Descriptor instead. func (*GetMeRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{18} + return file_main_proto_rawDescGZIP(), []int{26} } func (x *GetMeRsp) GetError() string { @@ -951,7 +1317,7 @@ type AddUserRoleReq struct { func (x *AddUserRoleReq) Reset() { *x = AddUserRoleReq{} - mi := &file_main_proto_msgTypes[19] + mi := &file_main_proto_msgTypes[27] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -963,7 +1329,7 @@ func (x *AddUserRoleReq) String() string { func (*AddUserRoleReq) ProtoMessage() {} func (x *AddUserRoleReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[19] + mi := &file_main_proto_msgTypes[27] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -976,7 +1342,7 @@ func (x *AddUserRoleReq) ProtoReflect() protoreflect.Message { // Deprecated: Use AddUserRoleReq.ProtoReflect.Descriptor instead. func (*AddUserRoleReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{19} + return file_main_proto_rawDescGZIP(), []int{27} } func (x *AddUserRoleReq) GetId() int32 { @@ -1002,7 +1368,7 @@ type AddUserRoleRsp struct { func (x *AddUserRoleRsp) Reset() { *x = AddUserRoleRsp{} - mi := &file_main_proto_msgTypes[20] + mi := &file_main_proto_msgTypes[28] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1014,7 +1380,7 @@ func (x *AddUserRoleRsp) String() string { func (*AddUserRoleRsp) ProtoMessage() {} func (x *AddUserRoleRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[20] + mi := &file_main_proto_msgTypes[28] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1027,7 +1393,7 @@ func (x *AddUserRoleRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use AddUserRoleRsp.ProtoReflect.Descriptor instead. func (*AddUserRoleRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{20} + return file_main_proto_rawDescGZIP(), []int{28} } func (x *AddUserRoleRsp) GetError() string { @@ -1047,7 +1413,7 @@ type DeleteUserRoleReq struct { func (x *DeleteUserRoleReq) Reset() { *x = DeleteUserRoleReq{} - mi := &file_main_proto_msgTypes[21] + mi := &file_main_proto_msgTypes[29] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1059,7 +1425,7 @@ func (x *DeleteUserRoleReq) String() string { func (*DeleteUserRoleReq) ProtoMessage() {} func (x *DeleteUserRoleReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[21] + mi := &file_main_proto_msgTypes[29] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1072,7 +1438,7 @@ func (x *DeleteUserRoleReq) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteUserRoleReq.ProtoReflect.Descriptor instead. func (*DeleteUserRoleReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{21} + return file_main_proto_rawDescGZIP(), []int{29} } func (x *DeleteUserRoleReq) GetId() int32 { @@ -1098,7 +1464,7 @@ type DeleteUserRoleRsp struct { func (x *DeleteUserRoleRsp) Reset() { *x = DeleteUserRoleRsp{} - mi := &file_main_proto_msgTypes[22] + mi := &file_main_proto_msgTypes[30] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1110,7 +1476,7 @@ func (x *DeleteUserRoleRsp) String() string { func (*DeleteUserRoleRsp) ProtoMessage() {} func (x *DeleteUserRoleRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[22] + mi := &file_main_proto_msgTypes[30] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1123,7 +1489,7 @@ func (x *DeleteUserRoleRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteUserRoleRsp.ProtoReflect.Descriptor instead. func (*DeleteUserRoleRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{22} + return file_main_proto_rawDescGZIP(), []int{30} } func (x *DeleteUserRoleRsp) GetError() string { @@ -1141,7 +1507,7 @@ type GetPermissionsReq struct { func (x *GetPermissionsReq) Reset() { *x = GetPermissionsReq{} - mi := &file_main_proto_msgTypes[23] + mi := &file_main_proto_msgTypes[31] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1153,7 +1519,7 @@ func (x *GetPermissionsReq) String() string { func (*GetPermissionsReq) ProtoMessage() {} func (x *GetPermissionsReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[23] + mi := &file_main_proto_msgTypes[31] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1166,7 +1532,7 @@ func (x *GetPermissionsReq) ProtoReflect() protoreflect.Message { // Deprecated: Use GetPermissionsReq.ProtoReflect.Descriptor instead. func (*GetPermissionsReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{23} + return file_main_proto_rawDescGZIP(), []int{31} } type GetPermissionsRsp struct { @@ -1179,7 +1545,7 @@ type GetPermissionsRsp struct { func (x *GetPermissionsRsp) Reset() { *x = GetPermissionsRsp{} - mi := &file_main_proto_msgTypes[24] + mi := &file_main_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1191,7 +1557,7 @@ func (x *GetPermissionsRsp) String() string { func (*GetPermissionsRsp) ProtoMessage() {} func (x *GetPermissionsRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[24] + mi := &file_main_proto_msgTypes[32] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1204,7 +1570,7 @@ func (x *GetPermissionsRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use GetPermissionsRsp.ProtoReflect.Descriptor instead. func (*GetPermissionsRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{24} + return file_main_proto_rawDescGZIP(), []int{32} } func (x *GetPermissionsRsp) GetError() string { @@ -1231,7 +1597,7 @@ type UploadFileReq struct { func (x *UploadFileReq) Reset() { *x = UploadFileReq{} - mi := &file_main_proto_msgTypes[25] + mi := &file_main_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1243,7 +1609,7 @@ func (x *UploadFileReq) String() string { func (*UploadFileReq) ProtoMessage() {} func (x *UploadFileReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[25] + mi := &file_main_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1256,7 +1622,7 @@ func (x *UploadFileReq) ProtoReflect() protoreflect.Message { // Deprecated: Use UploadFileReq.ProtoReflect.Descriptor instead. func (*UploadFileReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{25} + return file_main_proto_rawDescGZIP(), []int{33} } func (x *UploadFileReq) GetFilename() string { @@ -1283,7 +1649,7 @@ type UploadFileRsp struct { func (x *UploadFileRsp) Reset() { *x = UploadFileRsp{} - mi := &file_main_proto_msgTypes[26] + mi := &file_main_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1295,7 +1661,7 @@ func (x *UploadFileRsp) String() string { func (*UploadFileRsp) ProtoMessage() {} func (x *UploadFileRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[26] + mi := &file_main_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1308,7 +1674,7 @@ func (x *UploadFileRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use UploadFileRsp.ProtoReflect.Descriptor instead. func (*UploadFileRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{26} + return file_main_proto_rawDescGZIP(), []int{34} } func (x *UploadFileRsp) GetError() string { @@ -1334,7 +1700,7 @@ type DownloadFileReq struct { func (x *DownloadFileReq) Reset() { *x = DownloadFileReq{} - mi := &file_main_proto_msgTypes[27] + mi := &file_main_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1346,7 +1712,7 @@ func (x *DownloadFileReq) String() string { func (*DownloadFileReq) ProtoMessage() {} func (x *DownloadFileReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[27] + mi := &file_main_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1359,7 +1725,7 @@ func (x *DownloadFileReq) ProtoReflect() protoreflect.Message { // Deprecated: Use DownloadFileReq.ProtoReflect.Descriptor instead. func (*DownloadFileReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{27} + return file_main_proto_rawDescGZIP(), []int{35} } func (x *DownloadFileReq) GetFilename() string { @@ -1378,7 +1744,7 @@ type AddScenarioReq struct { func (x *AddScenarioReq) Reset() { *x = AddScenarioReq{} - mi := &file_main_proto_msgTypes[28] + mi := &file_main_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1390,7 +1756,7 @@ func (x *AddScenarioReq) String() string { func (*AddScenarioReq) ProtoMessage() {} func (x *AddScenarioReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[28] + mi := &file_main_proto_msgTypes[36] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1403,7 +1769,7 @@ func (x *AddScenarioReq) ProtoReflect() protoreflect.Message { // Deprecated: Use AddScenarioReq.ProtoReflect.Descriptor instead. func (*AddScenarioReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{28} + return file_main_proto_rawDescGZIP(), []int{36} } func (x *AddScenarioReq) GetName() string { @@ -1423,7 +1789,7 @@ type AddScenarioRsp struct { func (x *AddScenarioRsp) Reset() { *x = AddScenarioRsp{} - mi := &file_main_proto_msgTypes[29] + mi := &file_main_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1435,7 +1801,7 @@ func (x *AddScenarioRsp) String() string { func (*AddScenarioRsp) ProtoMessage() {} func (x *AddScenarioRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[29] + mi := &file_main_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1448,7 +1814,7 @@ func (x *AddScenarioRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use AddScenarioRsp.ProtoReflect.Descriptor instead. func (*AddScenarioRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{29} + return file_main_proto_rawDescGZIP(), []int{37} } func (x *AddScenarioRsp) GetError() string { @@ -1473,7 +1839,7 @@ type GetMyScenariosReq struct { func (x *GetMyScenariosReq) Reset() { *x = GetMyScenariosReq{} - mi := &file_main_proto_msgTypes[30] + mi := &file_main_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1485,7 +1851,7 @@ func (x *GetMyScenariosReq) String() string { func (*GetMyScenariosReq) ProtoMessage() {} func (x *GetMyScenariosReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[30] + mi := &file_main_proto_msgTypes[38] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1498,7 +1864,7 @@ func (x *GetMyScenariosReq) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMyScenariosReq.ProtoReflect.Descriptor instead. func (*GetMyScenariosReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{30} + return file_main_proto_rawDescGZIP(), []int{38} } type GetMyScenariosRsp struct { @@ -1511,7 +1877,7 @@ type GetMyScenariosRsp struct { func (x *GetMyScenariosRsp) Reset() { *x = GetMyScenariosRsp{} - mi := &file_main_proto_msgTypes[31] + mi := &file_main_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1523,7 +1889,7 @@ func (x *GetMyScenariosRsp) String() string { func (*GetMyScenariosRsp) ProtoMessage() {} func (x *GetMyScenariosRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[31] + mi := &file_main_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1536,7 +1902,7 @@ func (x *GetMyScenariosRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMyScenariosRsp.ProtoReflect.Descriptor instead. func (*GetMyScenariosRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{31} + return file_main_proto_rawDescGZIP(), []int{39} } func (x *GetMyScenariosRsp) GetError() string { @@ -1561,7 +1927,7 @@ type GetScenariosCatalogReq struct { func (x *GetScenariosCatalogReq) Reset() { *x = GetScenariosCatalogReq{} - mi := &file_main_proto_msgTypes[32] + mi := &file_main_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1573,7 +1939,7 @@ func (x *GetScenariosCatalogReq) String() string { func (*GetScenariosCatalogReq) ProtoMessage() {} func (x *GetScenariosCatalogReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[32] + mi := &file_main_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1586,7 +1952,7 @@ func (x *GetScenariosCatalogReq) ProtoReflect() protoreflect.Message { // Deprecated: Use GetScenariosCatalogReq.ProtoReflect.Descriptor instead. func (*GetScenariosCatalogReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{32} + return file_main_proto_rawDescGZIP(), []int{40} } type GetScenariosCatalogRsp struct { @@ -1599,7 +1965,7 @@ type GetScenariosCatalogRsp struct { func (x *GetScenariosCatalogRsp) Reset() { *x = GetScenariosCatalogRsp{} - mi := &file_main_proto_msgTypes[33] + mi := &file_main_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1611,7 +1977,7 @@ func (x *GetScenariosCatalogRsp) String() string { func (*GetScenariosCatalogRsp) ProtoMessage() {} func (x *GetScenariosCatalogRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[33] + mi := &file_main_proto_msgTypes[41] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1624,7 +1990,7 @@ func (x *GetScenariosCatalogRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use GetScenariosCatalogRsp.ProtoReflect.Descriptor instead. func (*GetScenariosCatalogRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{33} + return file_main_proto_rawDescGZIP(), []int{41} } func (x *GetScenariosCatalogRsp) GetError() string { @@ -1650,7 +2016,7 @@ type GetScenarioReq struct { func (x *GetScenarioReq) Reset() { *x = GetScenarioReq{} - mi := &file_main_proto_msgTypes[34] + mi := &file_main_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1662,7 +2028,7 @@ func (x *GetScenarioReq) String() string { func (*GetScenarioReq) ProtoMessage() {} func (x *GetScenarioReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[34] + mi := &file_main_proto_msgTypes[42] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1675,7 +2041,7 @@ func (x *GetScenarioReq) ProtoReflect() protoreflect.Message { // Deprecated: Use GetScenarioReq.ProtoReflect.Descriptor instead. func (*GetScenarioReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{34} + return file_main_proto_rawDescGZIP(), []int{42} } func (x *GetScenarioReq) GetId() int32 { @@ -1695,7 +2061,7 @@ type GetScenarioRsp struct { func (x *GetScenarioRsp) Reset() { *x = GetScenarioRsp{} - mi := &file_main_proto_msgTypes[35] + mi := &file_main_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1707,7 +2073,7 @@ func (x *GetScenarioRsp) String() string { func (*GetScenarioRsp) ProtoMessage() {} func (x *GetScenarioRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[35] + mi := &file_main_proto_msgTypes[43] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1720,7 +2086,7 @@ func (x *GetScenarioRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use GetScenarioRsp.ProtoReflect.Descriptor instead. func (*GetScenarioRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{35} + return file_main_proto_rawDescGZIP(), []int{43} } func (x *GetScenarioRsp) GetError() string { @@ -1755,7 +2121,7 @@ type Scenario struct { func (x *Scenario) Reset() { *x = Scenario{} - mi := &file_main_proto_msgTypes[36] + mi := &file_main_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1767,7 +2133,7 @@ func (x *Scenario) String() string { func (*Scenario) ProtoMessage() {} func (x *Scenario) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[36] + mi := &file_main_proto_msgTypes[44] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1780,7 +2146,7 @@ func (x *Scenario) ProtoReflect() protoreflect.Message { // Deprecated: Use Scenario.ProtoReflect.Descriptor instead. func (*Scenario) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{36} + return file_main_proto_rawDescGZIP(), []int{44} } func (x *Scenario) GetId() int32 { @@ -1862,7 +2228,7 @@ type Story struct { func (x *Story) Reset() { *x = Story{} - mi := &file_main_proto_msgTypes[37] + mi := &file_main_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1874,7 +2240,7 @@ func (x *Story) String() string { func (*Story) ProtoMessage() {} func (x *Story) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[37] + mi := &file_main_proto_msgTypes[45] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1887,7 +2253,7 @@ func (x *Story) ProtoReflect() protoreflect.Message { // Deprecated: Use Story.ProtoReflect.Descriptor instead. func (*Story) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{37} + return file_main_proto_rawDescGZIP(), []int{45} } func (x *Story) GetPlaces() []*Place { @@ -1913,7 +2279,7 @@ type Place struct { func (x *Place) Reset() { *x = Place{} - mi := &file_main_proto_msgTypes[38] + mi := &file_main_proto_msgTypes[46] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1925,7 +2291,7 @@ func (x *Place) String() string { func (*Place) ProtoMessage() {} func (x *Place) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[38] + mi := &file_main_proto_msgTypes[46] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1938,7 +2304,7 @@ func (x *Place) ProtoReflect() protoreflect.Message { // Deprecated: Use Place.ProtoReflect.Descriptor instead. func (*Place) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{38} + return file_main_proto_rawDescGZIP(), []int{46} } func (x *Place) GetCode() string { @@ -2007,7 +2373,7 @@ type Application struct { func (x *Application) Reset() { *x = Application{} - mi := &file_main_proto_msgTypes[39] + mi := &file_main_proto_msgTypes[47] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2019,7 +2385,7 @@ func (x *Application) String() string { func (*Application) ProtoMessage() {} func (x *Application) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[39] + mi := &file_main_proto_msgTypes[47] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2032,7 +2398,7 @@ func (x *Application) ProtoReflect() protoreflect.Message { // Deprecated: Use Application.ProtoReflect.Descriptor instead. func (*Application) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{39} + return file_main_proto_rawDescGZIP(), []int{47} } func (x *Application) GetName() string { @@ -2060,7 +2426,7 @@ type Door struct { func (x *Door) Reset() { *x = Door{} - mi := &file_main_proto_msgTypes[40] + mi := &file_main_proto_msgTypes[48] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2072,7 +2438,7 @@ func (x *Door) String() string { func (*Door) ProtoMessage() {} func (x *Door) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[40] + mi := &file_main_proto_msgTypes[48] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2085,7 +2451,7 @@ func (x *Door) ProtoReflect() protoreflect.Message { // Deprecated: Use Door.ProtoReflect.Descriptor instead. func (*Door) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{40} + return file_main_proto_rawDescGZIP(), []int{48} } func (x *Door) GetCode() string { @@ -2118,7 +2484,7 @@ type Key struct { func (x *Key) Reset() { *x = Key{} - mi := &file_main_proto_msgTypes[41] + mi := &file_main_proto_msgTypes[49] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2130,7 +2496,7 @@ func (x *Key) String() string { func (*Key) ProtoMessage() {} func (x *Key) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[41] + mi := &file_main_proto_msgTypes[49] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2143,7 +2509,7 @@ func (x *Key) ProtoReflect() protoreflect.Message { // Deprecated: Use Key.ProtoReflect.Descriptor instead. func (*Key) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{41} + return file_main_proto_rawDescGZIP(), []int{49} } func (x *Key) GetName() string { @@ -2165,7 +2531,7 @@ type UpdateScenarioReq struct { func (x *UpdateScenarioReq) Reset() { *x = UpdateScenarioReq{} - mi := &file_main_proto_msgTypes[42] + mi := &file_main_proto_msgTypes[50] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2177,7 +2543,7 @@ func (x *UpdateScenarioReq) String() string { func (*UpdateScenarioReq) ProtoMessage() {} func (x *UpdateScenarioReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[42] + mi := &file_main_proto_msgTypes[50] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2190,7 +2556,7 @@ func (x *UpdateScenarioReq) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateScenarioReq.ProtoReflect.Descriptor instead. func (*UpdateScenarioReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{42} + return file_main_proto_rawDescGZIP(), []int{50} } func (x *UpdateScenarioReq) GetId() int32 { @@ -2230,7 +2596,7 @@ type UpdateScenarioRsp struct { func (x *UpdateScenarioRsp) Reset() { *x = UpdateScenarioRsp{} - mi := &file_main_proto_msgTypes[43] + mi := &file_main_proto_msgTypes[51] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2242,7 +2608,7 @@ func (x *UpdateScenarioRsp) String() string { func (*UpdateScenarioRsp) ProtoMessage() {} func (x *UpdateScenarioRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[43] + mi := &file_main_proto_msgTypes[51] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2255,7 +2621,7 @@ func (x *UpdateScenarioRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateScenarioRsp.ProtoReflect.Descriptor instead. func (*UpdateScenarioRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{43} + return file_main_proto_rawDescGZIP(), []int{51} } func (x *UpdateScenarioRsp) GetError() string { @@ -2274,7 +2640,7 @@ type PublicScenarioReq struct { func (x *PublicScenarioReq) Reset() { *x = PublicScenarioReq{} - mi := &file_main_proto_msgTypes[44] + mi := &file_main_proto_msgTypes[52] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2286,7 +2652,7 @@ func (x *PublicScenarioReq) String() string { func (*PublicScenarioReq) ProtoMessage() {} func (x *PublicScenarioReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[44] + mi := &file_main_proto_msgTypes[52] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2299,7 +2665,7 @@ func (x *PublicScenarioReq) ProtoReflect() protoreflect.Message { // Deprecated: Use PublicScenarioReq.ProtoReflect.Descriptor instead. func (*PublicScenarioReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{44} + return file_main_proto_rawDescGZIP(), []int{52} } func (x *PublicScenarioReq) GetId() int32 { @@ -2318,7 +2684,7 @@ type PublicScenarioRsp struct { func (x *PublicScenarioRsp) Reset() { *x = PublicScenarioRsp{} - mi := &file_main_proto_msgTypes[45] + mi := &file_main_proto_msgTypes[53] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2330,7 +2696,7 @@ func (x *PublicScenarioRsp) String() string { func (*PublicScenarioRsp) ProtoMessage() {} func (x *PublicScenarioRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[45] + mi := &file_main_proto_msgTypes[53] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2343,7 +2709,7 @@ func (x *PublicScenarioRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use PublicScenarioRsp.ProtoReflect.Descriptor instead. func (*PublicScenarioRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{45} + return file_main_proto_rawDescGZIP(), []int{53} } func (x *PublicScenarioRsp) GetError() string { @@ -2362,7 +2728,7 @@ type DraftScenarioReq struct { func (x *DraftScenarioReq) Reset() { *x = DraftScenarioReq{} - mi := &file_main_proto_msgTypes[46] + mi := &file_main_proto_msgTypes[54] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2374,7 +2740,7 @@ func (x *DraftScenarioReq) String() string { func (*DraftScenarioReq) ProtoMessage() {} func (x *DraftScenarioReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[46] + mi := &file_main_proto_msgTypes[54] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2387,7 +2753,7 @@ func (x *DraftScenarioReq) ProtoReflect() protoreflect.Message { // Deprecated: Use DraftScenarioReq.ProtoReflect.Descriptor instead. func (*DraftScenarioReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{46} + return file_main_proto_rawDescGZIP(), []int{54} } func (x *DraftScenarioReq) GetId() int32 { @@ -2406,7 +2772,7 @@ type DraftScenarioRsp struct { func (x *DraftScenarioRsp) Reset() { *x = DraftScenarioRsp{} - mi := &file_main_proto_msgTypes[47] + mi := &file_main_proto_msgTypes[55] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2418,7 +2784,7 @@ func (x *DraftScenarioRsp) String() string { func (*DraftScenarioRsp) ProtoMessage() {} func (x *DraftScenarioRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[47] + mi := &file_main_proto_msgTypes[55] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2431,7 +2797,7 @@ func (x *DraftScenarioRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use DraftScenarioRsp.ProtoReflect.Descriptor instead. func (*DraftScenarioRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{47} + return file_main_proto_rawDescGZIP(), []int{55} } func (x *DraftScenarioRsp) GetError() string { @@ -2450,7 +2816,7 @@ type DeleteScenarioReq struct { func (x *DeleteScenarioReq) Reset() { *x = DeleteScenarioReq{} - mi := &file_main_proto_msgTypes[48] + mi := &file_main_proto_msgTypes[56] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2462,7 +2828,7 @@ func (x *DeleteScenarioReq) String() string { func (*DeleteScenarioReq) ProtoMessage() {} func (x *DeleteScenarioReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[48] + mi := &file_main_proto_msgTypes[56] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2475,7 +2841,7 @@ func (x *DeleteScenarioReq) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteScenarioReq.ProtoReflect.Descriptor instead. func (*DeleteScenarioReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{48} + return file_main_proto_rawDescGZIP(), []int{56} } func (x *DeleteScenarioReq) GetId() int32 { @@ -2494,7 +2860,7 @@ type DeleteScenarioRsp struct { func (x *DeleteScenarioRsp) Reset() { *x = DeleteScenarioRsp{} - mi := &file_main_proto_msgTypes[49] + mi := &file_main_proto_msgTypes[57] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2506,7 +2872,7 @@ func (x *DeleteScenarioRsp) String() string { func (*DeleteScenarioRsp) ProtoMessage() {} func (x *DeleteScenarioRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[49] + mi := &file_main_proto_msgTypes[57] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2519,7 +2885,7 @@ func (x *DeleteScenarioRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteScenarioRsp.ProtoReflect.Descriptor instead. func (*DeleteScenarioRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{49} + return file_main_proto_rawDescGZIP(), []int{57} } func (x *DeleteScenarioRsp) GetError() string { @@ -2539,7 +2905,7 @@ type AddScenarioPlaceReq struct { func (x *AddScenarioPlaceReq) Reset() { *x = AddScenarioPlaceReq{} - mi := &file_main_proto_msgTypes[50] + mi := &file_main_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2551,7 +2917,7 @@ func (x *AddScenarioPlaceReq) String() string { func (*AddScenarioPlaceReq) ProtoMessage() {} func (x *AddScenarioPlaceReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[50] + mi := &file_main_proto_msgTypes[58] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2564,7 +2930,7 @@ func (x *AddScenarioPlaceReq) ProtoReflect() protoreflect.Message { // Deprecated: Use AddScenarioPlaceReq.ProtoReflect.Descriptor instead. func (*AddScenarioPlaceReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{50} + return file_main_proto_rawDescGZIP(), []int{58} } func (x *AddScenarioPlaceReq) GetId() int32 { @@ -2590,7 +2956,7 @@ type AddScenarioPlaceRsp struct { func (x *AddScenarioPlaceRsp) Reset() { *x = AddScenarioPlaceRsp{} - mi := &file_main_proto_msgTypes[51] + mi := &file_main_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2602,7 +2968,7 @@ func (x *AddScenarioPlaceRsp) String() string { func (*AddScenarioPlaceRsp) ProtoMessage() {} func (x *AddScenarioPlaceRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[51] + mi := &file_main_proto_msgTypes[59] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2615,7 +2981,7 @@ func (x *AddScenarioPlaceRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use AddScenarioPlaceRsp.ProtoReflect.Descriptor instead. func (*AddScenarioPlaceRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{51} + return file_main_proto_rawDescGZIP(), []int{59} } func (x *AddScenarioPlaceRsp) GetError() string { @@ -2636,7 +3002,7 @@ type UpdateScenarioPlaceReq struct { func (x *UpdateScenarioPlaceReq) Reset() { *x = UpdateScenarioPlaceReq{} - mi := &file_main_proto_msgTypes[52] + mi := &file_main_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2648,7 +3014,7 @@ func (x *UpdateScenarioPlaceReq) String() string { func (*UpdateScenarioPlaceReq) ProtoMessage() {} func (x *UpdateScenarioPlaceReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[52] + mi := &file_main_proto_msgTypes[60] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2661,7 +3027,7 @@ func (x *UpdateScenarioPlaceReq) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateScenarioPlaceReq.ProtoReflect.Descriptor instead. func (*UpdateScenarioPlaceReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{52} + return file_main_proto_rawDescGZIP(), []int{60} } func (x *UpdateScenarioPlaceReq) GetId() int32 { @@ -2694,7 +3060,7 @@ type UpdateScenarioPlaceRsp struct { func (x *UpdateScenarioPlaceRsp) Reset() { *x = UpdateScenarioPlaceRsp{} - mi := &file_main_proto_msgTypes[53] + mi := &file_main_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2706,7 +3072,7 @@ func (x *UpdateScenarioPlaceRsp) String() string { func (*UpdateScenarioPlaceRsp) ProtoMessage() {} func (x *UpdateScenarioPlaceRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[53] + mi := &file_main_proto_msgTypes[61] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2719,7 +3085,7 @@ func (x *UpdateScenarioPlaceRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateScenarioPlaceRsp.ProtoReflect.Descriptor instead. func (*UpdateScenarioPlaceRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{53} + return file_main_proto_rawDescGZIP(), []int{61} } func (x *UpdateScenarioPlaceRsp) GetError() string { @@ -2739,7 +3105,7 @@ type DeleteScenarioPlaceReq struct { func (x *DeleteScenarioPlaceReq) Reset() { *x = DeleteScenarioPlaceReq{} - mi := &file_main_proto_msgTypes[54] + mi := &file_main_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2751,7 +3117,7 @@ func (x *DeleteScenarioPlaceReq) String() string { func (*DeleteScenarioPlaceReq) ProtoMessage() {} func (x *DeleteScenarioPlaceReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[54] + mi := &file_main_proto_msgTypes[62] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2764,7 +3130,7 @@ func (x *DeleteScenarioPlaceReq) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteScenarioPlaceReq.ProtoReflect.Descriptor instead. func (*DeleteScenarioPlaceReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{54} + return file_main_proto_rawDescGZIP(), []int{62} } func (x *DeleteScenarioPlaceReq) GetId() int32 { @@ -2790,7 +3156,7 @@ type DeleteScenarioPlaceRsp struct { func (x *DeleteScenarioPlaceRsp) Reset() { *x = DeleteScenarioPlaceRsp{} - mi := &file_main_proto_msgTypes[55] + mi := &file_main_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2802,7 +3168,7 @@ func (x *DeleteScenarioPlaceRsp) String() string { func (*DeleteScenarioPlaceRsp) ProtoMessage() {} func (x *DeleteScenarioPlaceRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[55] + mi := &file_main_proto_msgTypes[63] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2815,7 +3181,7 @@ func (x *DeleteScenarioPlaceRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteScenarioPlaceRsp.ProtoReflect.Descriptor instead. func (*DeleteScenarioPlaceRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{55} + return file_main_proto_rawDescGZIP(), []int{63} } func (x *DeleteScenarioPlaceRsp) GetError() string { @@ -2837,7 +3203,7 @@ type AddGameReq struct { func (x *AddGameReq) Reset() { *x = AddGameReq{} - mi := &file_main_proto_msgTypes[56] + mi := &file_main_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2849,7 +3215,7 @@ func (x *AddGameReq) String() string { func (*AddGameReq) ProtoMessage() {} func (x *AddGameReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[56] + mi := &file_main_proto_msgTypes[64] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2862,7 +3228,7 @@ func (x *AddGameReq) ProtoReflect() protoreflect.Message { // Deprecated: Use AddGameReq.ProtoReflect.Descriptor instead. func (*AddGameReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{56} + return file_main_proto_rawDescGZIP(), []int{64} } func (x *AddGameReq) GetName() string { @@ -2903,7 +3269,7 @@ type AddGameRsp struct { func (x *AddGameRsp) Reset() { *x = AddGameRsp{} - mi := &file_main_proto_msgTypes[57] + mi := &file_main_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2915,7 +3281,7 @@ func (x *AddGameRsp) String() string { func (*AddGameRsp) ProtoMessage() {} func (x *AddGameRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[57] + mi := &file_main_proto_msgTypes[65] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2928,7 +3294,7 @@ func (x *AddGameRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use AddGameRsp.ProtoReflect.Descriptor instead. func (*AddGameRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{57} + return file_main_proto_rawDescGZIP(), []int{65} } func (x *AddGameRsp) GetError() string { @@ -2953,7 +3319,7 @@ type GetGamesReq struct { func (x *GetGamesReq) Reset() { *x = GetGamesReq{} - mi := &file_main_proto_msgTypes[58] + mi := &file_main_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2965,7 +3331,7 @@ func (x *GetGamesReq) String() string { func (*GetGamesReq) ProtoMessage() {} func (x *GetGamesReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[58] + mi := &file_main_proto_msgTypes[66] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2978,7 +3344,7 @@ func (x *GetGamesReq) ProtoReflect() protoreflect.Message { // Deprecated: Use GetGamesReq.ProtoReflect.Descriptor instead. func (*GetGamesReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{58} + return file_main_proto_rawDescGZIP(), []int{66} } type GetGamesRsp struct { @@ -2991,7 +3357,7 @@ type GetGamesRsp struct { func (x *GetGamesRsp) Reset() { *x = GetGamesRsp{} - mi := &file_main_proto_msgTypes[59] + mi := &file_main_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3003,7 +3369,7 @@ func (x *GetGamesRsp) String() string { func (*GetGamesRsp) ProtoMessage() {} func (x *GetGamesRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[59] + mi := &file_main_proto_msgTypes[67] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3016,7 +3382,7 @@ func (x *GetGamesRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use GetGamesRsp.ProtoReflect.Descriptor instead. func (*GetGamesRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{59} + return file_main_proto_rawDescGZIP(), []int{67} } func (x *GetGamesRsp) GetError() string { @@ -3050,7 +3416,7 @@ type Game struct { func (x *Game) Reset() { *x = Game{} - mi := &file_main_proto_msgTypes[60] + mi := &file_main_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3062,7 +3428,7 @@ func (x *Game) String() string { func (*Game) ProtoMessage() {} func (x *Game) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[60] + mi := &file_main_proto_msgTypes[68] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3075,7 +3441,7 @@ func (x *Game) ProtoReflect() protoreflect.Message { // Deprecated: Use Game.ProtoReflect.Descriptor instead. func (*Game) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{60} + return file_main_proto_rawDescGZIP(), []int{68} } func (x *Game) GetId() int32 { @@ -3155,7 +3521,7 @@ type Team struct { func (x *Team) Reset() { *x = Team{} - mi := &file_main_proto_msgTypes[61] + mi := &file_main_proto_msgTypes[69] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3167,7 +3533,7 @@ func (x *Team) String() string { func (*Team) ProtoMessage() {} func (x *Team) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[61] + mi := &file_main_proto_msgTypes[69] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3180,7 +3546,7 @@ func (x *Team) ProtoReflect() protoreflect.Message { // Deprecated: Use Team.ProtoReflect.Descriptor instead. func (*Team) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{61} + return file_main_proto_rawDescGZIP(), []int{69} } func (x *Team) GetId() int32 { @@ -3234,7 +3600,7 @@ type GetGameReq struct { func (x *GetGameReq) Reset() { *x = GetGameReq{} - mi := &file_main_proto_msgTypes[62] + mi := &file_main_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3246,7 +3612,7 @@ func (x *GetGameReq) String() string { func (*GetGameReq) ProtoMessage() {} func (x *GetGameReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[62] + mi := &file_main_proto_msgTypes[70] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3259,7 +3625,7 @@ func (x *GetGameReq) ProtoReflect() protoreflect.Message { // Deprecated: Use GetGameReq.ProtoReflect.Descriptor instead. func (*GetGameReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{62} + return file_main_proto_rawDescGZIP(), []int{70} } func (x *GetGameReq) GetId() int32 { @@ -3279,7 +3645,7 @@ type GetGameRsp struct { func (x *GetGameRsp) Reset() { *x = GetGameRsp{} - mi := &file_main_proto_msgTypes[63] + mi := &file_main_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3291,7 +3657,7 @@ func (x *GetGameRsp) String() string { func (*GetGameRsp) ProtoMessage() {} func (x *GetGameRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[63] + mi := &file_main_proto_msgTypes[71] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3304,7 +3670,7 @@ func (x *GetGameRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use GetGameRsp.ProtoReflect.Descriptor instead. func (*GetGameRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{63} + return file_main_proto_rawDescGZIP(), []int{71} } func (x *GetGameRsp) GetError() string { @@ -3334,7 +3700,7 @@ type UpdateGameReq struct { func (x *UpdateGameReq) Reset() { *x = UpdateGameReq{} - mi := &file_main_proto_msgTypes[64] + mi := &file_main_proto_msgTypes[72] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3346,7 +3712,7 @@ func (x *UpdateGameReq) String() string { func (*UpdateGameReq) ProtoMessage() {} func (x *UpdateGameReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[64] + mi := &file_main_proto_msgTypes[72] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3359,7 +3725,7 @@ func (x *UpdateGameReq) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateGameReq.ProtoReflect.Descriptor instead. func (*UpdateGameReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{64} + return file_main_proto_rawDescGZIP(), []int{72} } func (x *UpdateGameReq) GetId() int32 { @@ -3406,7 +3772,7 @@ type UpdateGameRsp struct { func (x *UpdateGameRsp) Reset() { *x = UpdateGameRsp{} - mi := &file_main_proto_msgTypes[65] + mi := &file_main_proto_msgTypes[73] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3418,7 +3784,7 @@ func (x *UpdateGameRsp) String() string { func (*UpdateGameRsp) ProtoMessage() {} func (x *UpdateGameRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[65] + mi := &file_main_proto_msgTypes[73] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3431,7 +3797,7 @@ func (x *UpdateGameRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateGameRsp.ProtoReflect.Descriptor instead. func (*UpdateGameRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{65} + return file_main_proto_rawDescGZIP(), []int{73} } func (x *UpdateGameRsp) GetError() string { @@ -3450,7 +3816,7 @@ type StartGameReq struct { func (x *StartGameReq) Reset() { *x = StartGameReq{} - mi := &file_main_proto_msgTypes[66] + mi := &file_main_proto_msgTypes[74] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3462,7 +3828,7 @@ func (x *StartGameReq) String() string { func (*StartGameReq) ProtoMessage() {} func (x *StartGameReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[66] + mi := &file_main_proto_msgTypes[74] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3475,7 +3841,7 @@ func (x *StartGameReq) ProtoReflect() protoreflect.Message { // Deprecated: Use StartGameReq.ProtoReflect.Descriptor instead. func (*StartGameReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{66} + return file_main_proto_rawDescGZIP(), []int{74} } func (x *StartGameReq) GetId() int32 { @@ -3494,7 +3860,7 @@ type StartGameRsp struct { func (x *StartGameRsp) Reset() { *x = StartGameRsp{} - mi := &file_main_proto_msgTypes[67] + mi := &file_main_proto_msgTypes[75] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3506,7 +3872,7 @@ func (x *StartGameRsp) String() string { func (*StartGameRsp) ProtoMessage() {} func (x *StartGameRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[67] + mi := &file_main_proto_msgTypes[75] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3519,7 +3885,7 @@ func (x *StartGameRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use StartGameRsp.ProtoReflect.Descriptor instead. func (*StartGameRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{67} + return file_main_proto_rawDescGZIP(), []int{75} } func (x *StartGameRsp) GetError() string { @@ -3538,7 +3904,7 @@ type PauseGameReq struct { func (x *PauseGameReq) Reset() { *x = PauseGameReq{} - mi := &file_main_proto_msgTypes[68] + mi := &file_main_proto_msgTypes[76] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3550,7 +3916,7 @@ func (x *PauseGameReq) String() string { func (*PauseGameReq) ProtoMessage() {} func (x *PauseGameReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[68] + mi := &file_main_proto_msgTypes[76] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3563,7 +3929,7 @@ func (x *PauseGameReq) ProtoReflect() protoreflect.Message { // Deprecated: Use PauseGameReq.ProtoReflect.Descriptor instead. func (*PauseGameReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{68} + return file_main_proto_rawDescGZIP(), []int{76} } func (x *PauseGameReq) GetId() int32 { @@ -3582,7 +3948,7 @@ type PauseGameRsp struct { func (x *PauseGameRsp) Reset() { *x = PauseGameRsp{} - mi := &file_main_proto_msgTypes[69] + mi := &file_main_proto_msgTypes[77] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3594,7 +3960,7 @@ func (x *PauseGameRsp) String() string { func (*PauseGameRsp) ProtoMessage() {} func (x *PauseGameRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[69] + mi := &file_main_proto_msgTypes[77] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3607,7 +3973,7 @@ func (x *PauseGameRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use PauseGameRsp.ProtoReflect.Descriptor instead. func (*PauseGameRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{69} + return file_main_proto_rawDescGZIP(), []int{77} } func (x *PauseGameRsp) GetError() string { @@ -3626,7 +3992,7 @@ type PlayGameReq struct { func (x *PlayGameReq) Reset() { *x = PlayGameReq{} - mi := &file_main_proto_msgTypes[70] + mi := &file_main_proto_msgTypes[78] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3638,7 +4004,7 @@ func (x *PlayGameReq) String() string { func (*PlayGameReq) ProtoMessage() {} func (x *PlayGameReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[70] + mi := &file_main_proto_msgTypes[78] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3651,7 +4017,7 @@ func (x *PlayGameReq) ProtoReflect() protoreflect.Message { // Deprecated: Use PlayGameReq.ProtoReflect.Descriptor instead. func (*PlayGameReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{70} + return file_main_proto_rawDescGZIP(), []int{78} } func (x *PlayGameReq) GetId() int32 { @@ -3670,7 +4036,7 @@ type PlayGameRsp struct { func (x *PlayGameRsp) Reset() { *x = PlayGameRsp{} - mi := &file_main_proto_msgTypes[71] + mi := &file_main_proto_msgTypes[79] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3682,7 +4048,7 @@ func (x *PlayGameRsp) String() string { func (*PlayGameRsp) ProtoMessage() {} func (x *PlayGameRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[71] + mi := &file_main_proto_msgTypes[79] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3695,7 +4061,7 @@ func (x *PlayGameRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use PlayGameRsp.ProtoReflect.Descriptor instead. func (*PlayGameRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{71} + return file_main_proto_rawDescGZIP(), []int{79} } func (x *PlayGameRsp) GetError() string { @@ -3714,7 +4080,7 @@ type FinishGameReq struct { func (x *FinishGameReq) Reset() { *x = FinishGameReq{} - mi := &file_main_proto_msgTypes[72] + mi := &file_main_proto_msgTypes[80] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3726,7 +4092,7 @@ func (x *FinishGameReq) String() string { func (*FinishGameReq) ProtoMessage() {} func (x *FinishGameReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[72] + mi := &file_main_proto_msgTypes[80] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3739,7 +4105,7 @@ func (x *FinishGameReq) ProtoReflect() protoreflect.Message { // Deprecated: Use FinishGameReq.ProtoReflect.Descriptor instead. func (*FinishGameReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{72} + return file_main_proto_rawDescGZIP(), []int{80} } func (x *FinishGameReq) GetId() int32 { @@ -3758,7 +4124,7 @@ type FinishGameRsp struct { func (x *FinishGameRsp) Reset() { *x = FinishGameRsp{} - mi := &file_main_proto_msgTypes[73] + mi := &file_main_proto_msgTypes[81] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3770,7 +4136,7 @@ func (x *FinishGameRsp) String() string { func (*FinishGameRsp) ProtoMessage() {} func (x *FinishGameRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[73] + mi := &file_main_proto_msgTypes[81] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3783,7 +4149,7 @@ func (x *FinishGameRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use FinishGameRsp.ProtoReflect.Descriptor instead. func (*FinishGameRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{73} + return file_main_proto_rawDescGZIP(), []int{81} } func (x *FinishGameRsp) GetError() string { @@ -3802,7 +4168,7 @@ type ResetGameReq struct { func (x *ResetGameReq) Reset() { *x = ResetGameReq{} - mi := &file_main_proto_msgTypes[74] + mi := &file_main_proto_msgTypes[82] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3814,7 +4180,7 @@ func (x *ResetGameReq) String() string { func (*ResetGameReq) ProtoMessage() {} func (x *ResetGameReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[74] + mi := &file_main_proto_msgTypes[82] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3827,7 +4193,7 @@ func (x *ResetGameReq) ProtoReflect() protoreflect.Message { // Deprecated: Use ResetGameReq.ProtoReflect.Descriptor instead. func (*ResetGameReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{74} + return file_main_proto_rawDescGZIP(), []int{82} } func (x *ResetGameReq) GetId() int32 { @@ -3846,7 +4212,7 @@ type ResetGameRsp struct { func (x *ResetGameRsp) Reset() { *x = ResetGameRsp{} - mi := &file_main_proto_msgTypes[75] + mi := &file_main_proto_msgTypes[83] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3858,7 +4224,7 @@ func (x *ResetGameRsp) String() string { func (*ResetGameRsp) ProtoMessage() {} func (x *ResetGameRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[75] + mi := &file_main_proto_msgTypes[83] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3871,7 +4237,7 @@ func (x *ResetGameRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use ResetGameRsp.ProtoReflect.Descriptor instead. func (*ResetGameRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{75} + return file_main_proto_rawDescGZIP(), []int{83} } func (x *ResetGameRsp) GetError() string { @@ -3890,7 +4256,7 @@ type DeleteGameReq struct { func (x *DeleteGameReq) Reset() { *x = DeleteGameReq{} - mi := &file_main_proto_msgTypes[76] + mi := &file_main_proto_msgTypes[84] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3902,7 +4268,7 @@ func (x *DeleteGameReq) String() string { func (*DeleteGameReq) ProtoMessage() {} func (x *DeleteGameReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[76] + mi := &file_main_proto_msgTypes[84] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3915,7 +4281,7 @@ func (x *DeleteGameReq) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteGameReq.ProtoReflect.Descriptor instead. func (*DeleteGameReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{76} + return file_main_proto_rawDescGZIP(), []int{84} } func (x *DeleteGameReq) GetId() int32 { @@ -3934,7 +4300,7 @@ type DeleteGameRsp struct { func (x *DeleteGameRsp) Reset() { *x = DeleteGameRsp{} - mi := &file_main_proto_msgTypes[77] + mi := &file_main_proto_msgTypes[85] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3946,7 +4312,7 @@ func (x *DeleteGameRsp) String() string { func (*DeleteGameRsp) ProtoMessage() {} func (x *DeleteGameRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[77] + mi := &file_main_proto_msgTypes[85] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3959,7 +4325,7 @@ func (x *DeleteGameRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteGameRsp.ProtoReflect.Descriptor instead. func (*DeleteGameRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{77} + return file_main_proto_rawDescGZIP(), []int{85} } func (x *DeleteGameRsp) GetError() string { @@ -3979,7 +4345,7 @@ type AddTeamReq struct { func (x *AddTeamReq) Reset() { *x = AddTeamReq{} - mi := &file_main_proto_msgTypes[78] + mi := &file_main_proto_msgTypes[86] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3991,7 +4357,7 @@ func (x *AddTeamReq) String() string { func (*AddTeamReq) ProtoMessage() {} func (x *AddTeamReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[78] + mi := &file_main_proto_msgTypes[86] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4004,7 +4370,7 @@ func (x *AddTeamReq) ProtoReflect() protoreflect.Message { // Deprecated: Use AddTeamReq.ProtoReflect.Descriptor instead. func (*AddTeamReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{78} + return file_main_proto_rawDescGZIP(), []int{86} } func (x *AddTeamReq) GetGameId() int32 { @@ -4032,7 +4398,7 @@ type AddTeamRsp struct { func (x *AddTeamRsp) Reset() { *x = AddTeamRsp{} - mi := &file_main_proto_msgTypes[79] + mi := &file_main_proto_msgTypes[87] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4044,7 +4410,7 @@ func (x *AddTeamRsp) String() string { func (*AddTeamRsp) ProtoMessage() {} func (x *AddTeamRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[79] + mi := &file_main_proto_msgTypes[87] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4057,7 +4423,7 @@ func (x *AddTeamRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use AddTeamRsp.ProtoReflect.Descriptor instead. func (*AddTeamRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{79} + return file_main_proto_rawDescGZIP(), []int{87} } func (x *AddTeamRsp) GetError() string { @@ -4091,7 +4457,7 @@ type UpdateTeamReq struct { func (x *UpdateTeamReq) Reset() { *x = UpdateTeamReq{} - mi := &file_main_proto_msgTypes[80] + mi := &file_main_proto_msgTypes[88] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4103,7 +4469,7 @@ func (x *UpdateTeamReq) String() string { func (*UpdateTeamReq) ProtoMessage() {} func (x *UpdateTeamReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[80] + mi := &file_main_proto_msgTypes[88] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4116,7 +4482,7 @@ func (x *UpdateTeamReq) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateTeamReq.ProtoReflect.Descriptor instead. func (*UpdateTeamReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{80} + return file_main_proto_rawDescGZIP(), []int{88} } func (x *UpdateTeamReq) GetId() int32 { @@ -4142,7 +4508,7 @@ type UpdateTeamRsp struct { func (x *UpdateTeamRsp) Reset() { *x = UpdateTeamRsp{} - mi := &file_main_proto_msgTypes[81] + mi := &file_main_proto_msgTypes[89] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4154,7 +4520,7 @@ func (x *UpdateTeamRsp) String() string { func (*UpdateTeamRsp) ProtoMessage() {} func (x *UpdateTeamRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[81] + mi := &file_main_proto_msgTypes[89] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4167,7 +4533,7 @@ func (x *UpdateTeamRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateTeamRsp.ProtoReflect.Descriptor instead. func (*UpdateTeamRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{81} + return file_main_proto_rawDescGZIP(), []int{89} } func (x *UpdateTeamRsp) GetError() string { @@ -4186,7 +4552,7 @@ type DeleteTeamReq struct { func (x *DeleteTeamReq) Reset() { *x = DeleteTeamReq{} - mi := &file_main_proto_msgTypes[82] + mi := &file_main_proto_msgTypes[90] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4198,7 +4564,7 @@ func (x *DeleteTeamReq) String() string { func (*DeleteTeamReq) ProtoMessage() {} func (x *DeleteTeamReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[82] + mi := &file_main_proto_msgTypes[90] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4211,7 +4577,7 @@ func (x *DeleteTeamReq) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteTeamReq.ProtoReflect.Descriptor instead. func (*DeleteTeamReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{82} + return file_main_proto_rawDescGZIP(), []int{90} } func (x *DeleteTeamReq) GetId() int64 { @@ -4230,7 +4596,7 @@ type DeleteTeamRsp struct { func (x *DeleteTeamRsp) Reset() { *x = DeleteTeamRsp{} - mi := &file_main_proto_msgTypes[83] + mi := &file_main_proto_msgTypes[91] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4242,7 +4608,7 @@ func (x *DeleteTeamRsp) String() string { func (*DeleteTeamRsp) ProtoMessage() {} func (x *DeleteTeamRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[83] + mi := &file_main_proto_msgTypes[91] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4255,7 +4621,7 @@ func (x *DeleteTeamRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteTeamRsp.ProtoReflect.Descriptor instead. func (*DeleteTeamRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{83} + return file_main_proto_rawDescGZIP(), []int{91} } func (x *DeleteTeamRsp) GetError() string { @@ -4275,7 +4641,7 @@ type GiveTeamApplicationsReq struct { func (x *GiveTeamApplicationsReq) Reset() { *x = GiveTeamApplicationsReq{} - mi := &file_main_proto_msgTypes[84] + mi := &file_main_proto_msgTypes[92] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4287,7 +4653,7 @@ func (x *GiveTeamApplicationsReq) String() string { func (*GiveTeamApplicationsReq) ProtoMessage() {} func (x *GiveTeamApplicationsReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[84] + mi := &file_main_proto_msgTypes[92] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4300,7 +4666,7 @@ func (x *GiveTeamApplicationsReq) ProtoReflect() protoreflect.Message { // Deprecated: Use GiveTeamApplicationsReq.ProtoReflect.Descriptor instead. func (*GiveTeamApplicationsReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{84} + return file_main_proto_rawDescGZIP(), []int{92} } func (x *GiveTeamApplicationsReq) GetId() int64 { @@ -4326,7 +4692,7 @@ type GiveTeamApplicationsRsp struct { func (x *GiveTeamApplicationsRsp) Reset() { *x = GiveTeamApplicationsRsp{} - mi := &file_main_proto_msgTypes[85] + mi := &file_main_proto_msgTypes[93] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4338,7 +4704,7 @@ func (x *GiveTeamApplicationsRsp) String() string { func (*GiveTeamApplicationsRsp) ProtoMessage() {} func (x *GiveTeamApplicationsRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[85] + mi := &file_main_proto_msgTypes[93] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4351,7 +4717,7 @@ func (x *GiveTeamApplicationsRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use GiveTeamApplicationsRsp.ProtoReflect.Descriptor instead. func (*GiveTeamApplicationsRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{85} + return file_main_proto_rawDescGZIP(), []int{93} } func (x *GiveTeamApplicationsRsp) GetError() string { @@ -4371,7 +4737,7 @@ type GetTeamStoryReq struct { func (x *GetTeamStoryReq) Reset() { *x = GetTeamStoryReq{} - mi := &file_main_proto_msgTypes[86] + mi := &file_main_proto_msgTypes[94] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4383,7 +4749,7 @@ func (x *GetTeamStoryReq) String() string { func (*GetTeamStoryReq) ProtoMessage() {} func (x *GetTeamStoryReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[86] + mi := &file_main_proto_msgTypes[94] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4396,7 +4762,7 @@ func (x *GetTeamStoryReq) ProtoReflect() protoreflect.Message { // Deprecated: Use GetTeamStoryReq.ProtoReflect.Descriptor instead. func (*GetTeamStoryReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{86} + return file_main_proto_rawDescGZIP(), []int{94} } func (x *GetTeamStoryReq) GetId() int64 { @@ -4424,7 +4790,7 @@ type GetTeamStoryRsp struct { func (x *GetTeamStoryRsp) Reset() { *x = GetTeamStoryRsp{} - mi := &file_main_proto_msgTypes[87] + mi := &file_main_proto_msgTypes[95] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4436,7 +4802,7 @@ func (x *GetTeamStoryRsp) String() string { func (*GetTeamStoryRsp) ProtoMessage() {} func (x *GetTeamStoryRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[87] + mi := &file_main_proto_msgTypes[95] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4449,7 +4815,7 @@ func (x *GetTeamStoryRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use GetTeamStoryRsp.ProtoReflect.Descriptor instead. func (*GetTeamStoryRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{87} + return file_main_proto_rawDescGZIP(), []int{95} } func (x *GetTeamStoryRsp) GetError() string { @@ -4484,7 +4850,7 @@ type AddTeamActionReq struct { func (x *AddTeamActionReq) Reset() { *x = AddTeamActionReq{} - mi := &file_main_proto_msgTypes[88] + mi := &file_main_proto_msgTypes[96] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4496,7 +4862,7 @@ func (x *AddTeamActionReq) String() string { func (*AddTeamActionReq) ProtoMessage() {} func (x *AddTeamActionReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[88] + mi := &file_main_proto_msgTypes[96] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4509,7 +4875,7 @@ func (x *AddTeamActionReq) ProtoReflect() protoreflect.Message { // Deprecated: Use AddTeamActionReq.ProtoReflect.Descriptor instead. func (*AddTeamActionReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{88} + return file_main_proto_rawDescGZIP(), []int{96} } func (x *AddTeamActionReq) GetId() int64 { @@ -4542,7 +4908,7 @@ type AddTeamActionRsp struct { func (x *AddTeamActionRsp) Reset() { *x = AddTeamActionRsp{} - mi := &file_main_proto_msgTypes[89] + mi := &file_main_proto_msgTypes[97] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4554,7 +4920,7 @@ func (x *AddTeamActionRsp) String() string { func (*AddTeamActionRsp) ProtoMessage() {} func (x *AddTeamActionRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[89] + mi := &file_main_proto_msgTypes[97] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4567,7 +4933,7 @@ func (x *AddTeamActionRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use AddTeamActionRsp.ProtoReflect.Descriptor instead. func (*AddTeamActionRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{89} + return file_main_proto_rawDescGZIP(), []int{97} } func (x *AddTeamActionRsp) GetError() string { @@ -4586,7 +4952,7 @@ type DeleteLastTeamActionReq struct { func (x *DeleteLastTeamActionReq) Reset() { *x = DeleteLastTeamActionReq{} - mi := &file_main_proto_msgTypes[90] + mi := &file_main_proto_msgTypes[98] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4598,7 +4964,7 @@ func (x *DeleteLastTeamActionReq) String() string { func (*DeleteLastTeamActionReq) ProtoMessage() {} func (x *DeleteLastTeamActionReq) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[90] + mi := &file_main_proto_msgTypes[98] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4611,7 +4977,7 @@ func (x *DeleteLastTeamActionReq) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteLastTeamActionReq.ProtoReflect.Descriptor instead. func (*DeleteLastTeamActionReq) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{90} + return file_main_proto_rawDescGZIP(), []int{98} } func (x *DeleteLastTeamActionReq) GetId() int64 { @@ -4630,7 +4996,7 @@ type DeleteLastTeamActionRsp struct { func (x *DeleteLastTeamActionRsp) Reset() { *x = DeleteLastTeamActionRsp{} - mi := &file_main_proto_msgTypes[91] + mi := &file_main_proto_msgTypes[99] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4642,7 +5008,7 @@ func (x *DeleteLastTeamActionRsp) String() string { func (*DeleteLastTeamActionRsp) ProtoMessage() {} func (x *DeleteLastTeamActionRsp) ProtoReflect() protoreflect.Message { - mi := &file_main_proto_msgTypes[91] + mi := &file_main_proto_msgTypes[99] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4655,7 +5021,7 @@ func (x *DeleteLastTeamActionRsp) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteLastTeamActionRsp.ProtoReflect.Descriptor instead. func (*DeleteLastTeamActionRsp) Descriptor() ([]byte, []int) { - return file_main_proto_rawDescGZIP(), []int{91} + return file_main_proto_rawDescGZIP(), []int{99} } func (x *DeleteLastTeamActionRsp) GetError() string { @@ -4676,10 +5042,12 @@ const file_main_proto_rawDesc = "" + "\aEchoReq\x12\x12\n" + "\x04text\x18\x01 \x01(\tR\x04text\"\x1d\n" + "\aEchoRsp\x12\x12\n" + - "\x04text\x18\x01 \x01(\tR\x04text\"=\n" + + "\x04text\x18\x01 \x01(\tR\x04text\"\x87\x01\n" + "\tSignupReq\x12\x1a\n" + "\busername\x18\x01 \x01(\tR\busername\x12\x14\n" + - "\x05email\x18\x02 \x01(\tR\x05email\"!\n" + + "\x05email\x18\x02 \x01(\tR\x05email\x12!\n" + + "\faccept_terms\x18\x03 \x01(\bR\vacceptTerms\x12%\n" + + "\x0eaccept_privacy\x18\x04 \x01(\bR\racceptPrivacy\"!\n" + "\tSignupRsp\x12\x14\n" + "\x05error\x18\x01 \x01(\tR\x05error\"*\n" + "\x12RefreshPasswordReq\x12\x14\n" + @@ -4700,7 +5068,22 @@ const file_main_proto_rawDesc = "" + "RefreshRsp\x12\x14\n" + "\x05error\x18\x01 \x01(\tR\x05error\x12 \n" + "\vaccessToken\x18\x02 \x01(\tR\vaccessToken\x12\"\n" + - "\frefreshToken\x18\x03 \x01(\tR\frefreshToken\"\r\n" + + "\frefreshToken\x18\x03 \x01(\tR\frefreshToken\"\x12\n" + + "\x10DeleteAccountReq\"(\n" + + "\x10DeleteAccountRsp\x12\x14\n" + + "\x05error\x18\x01 \x01(\tR\x05error\"\r\n" + + "\vGetTermsReq\"7\n" + + "\vGetTermsRsp\x12\x14\n" + + "\x05error\x18\x01 \x01(\tR\x05error\x12\x12\n" + + "\x04text\x18\x02 \x01(\tR\x04text\"\x0f\n" + + "\rGetPrivacyReq\"9\n" + + "\rGetPrivacyRsp\x12\x14\n" + + "\x05error\x18\x01 \x01(\tR\x05error\x12\x12\n" + + "\x04text\x18\x02 \x01(\tR\x04text\"\x0f\n" + + "\rGetConsentReq\"9\n" + + "\rGetConsentRsp\x12\x14\n" + + "\x05error\x18\x01 \x01(\tR\x05error\x12\x12\n" + + "\x04text\x18\x02 \x01(\tR\x04text\"\r\n" + "\vGetUsersReq\"_\n" + "\vGetUsersRsp\x12\x14\n" + "\x05error\x18\x01 \x01(\tR\x05error\x12:\n" + @@ -4948,7 +5331,7 @@ const file_main_proto_rawDesc = "" + "\x17DeleteLastTeamActionReq\x12\x0e\n" + "\x02id\x18\x01 \x01(\x03R\x02id\"/\n" + "\x17DeleteLastTeamActionRsp\x12\x14\n" + - "\x05error\x18\x01 \x01(\tR\x05error2\x82E\n" + + "\x05error\x18\x01 \x01(\tR\x05error2\xc8O\n" + "\x16EveningDetectiveServer\x12\xa6\x01\n" + "\x04Ping\x12'.crabs.evening_detective_server.PingReq\x1a'.crabs.evening_detective_server.PingRsp\"L\x92A3\x12)Проверить доступностьb\x06\n" + "\x04\n" + @@ -4971,7 +5354,19 @@ const file_main_proto_rawDesc = "" + "\aRefresh\x12*.crabs.evening_detective_server.RefreshReq\x1a*.crabs.evening_detective_server.RefreshRsp\"y\x92AZ\n" + "\"Регистрация и вход\x12,Обновить токена доступаb\x06\n" + "\x04\n" + - "\x00\x12\x00\x82\xd3\xe4\x93\x02\x16:\x01*\"\x11/api/auth/refresh\x12\xcb\x01\n" + + "\x00\x12\x00\x82\xd3\xe4\x93\x02\x16:\x01*\"\x11/api/auth/refresh\x12\xe3\x04\n" + + "\rDeleteAccount\x120.crabs.evening_detective_server.DeleteAccountReq\x1a0.crabs.evening_detective_server.DeleteAccountRsp\"\xed\x03\x92A\xc9\x03\n" + + "\"Регистрация и вход\x12SУдалить учётную запись и персональные данные\x1a\xcd\x02Удаляет учётную запись и персональные данные текущего пользователя (ст. 21 152-ФЗ). Требует заголовок X-Password с паролем учётной записи (подтверждение владельца; пароль не передаётся в URL).\x82\xd3\xe4\x93\x02\x1a*\x18/api/auth/delete-account\x12\xf0\x01\n" + + "\bGetTerms\x12+.crabs.evening_detective_server.GetTermsReq\x1a+.crabs.evening_detective_server.GetTermsRsp\"\x89\x01\x92Ax\n" + + "\x12Документы\x12bПолучить текст Пользовательского соглашения (оферты)\x82\xd3\xe4\x93\x02\b\x12\x06/terms\x12\xe6\x01\n" + + "\n" + + "GetPrivacy\x12-.crabs.evening_detective_server.GetPrivacyReq\x1a-.crabs.evening_detective_server.GetPrivacyRsp\"z\x92Ag\n" + + "\x12Документы\x12QПолучить текст Политики конфиденциальности\x82\xd3\xe4\x93\x02\n" + + "\x12\b/privacy\x12\x81\x02\n" + + "\n" + + "GetConsent\x12-.crabs.evening_detective_server.GetConsentReq\x1a-.crabs.evening_detective_server.GetConsentRsp\"\x94\x01\x92A\x80\x01\n" + + "\x12Документы\x12jПолучить текст согласия на обработку персональных данных\x82\xd3\xe4\x93\x02\n" + + "\x12\b/consent\x12\xcb\x01\n" + "\bGetUsers\x12+.crabs.evening_detective_server.GetUsersReq\x1a+.crabs.evening_detective_server.GetUsersRsp\"e\x92AP\n" + "\x18Пользователи\x124Получить всех пользователей\x82\xd3\xe4\x93\x02\f\x12\n" + "/api/users\x12\xd6\x01\n" + @@ -5082,7 +5477,7 @@ func file_main_proto_rawDescGZIP() []byte { return file_main_proto_rawDescData } -var file_main_proto_msgTypes = make([]protoimpl.MessageInfo, 92) +var file_main_proto_msgTypes = make([]protoimpl.MessageInfo, 100) var file_main_proto_goTypes = []any{ (*PingReq)(nil), // 0: crabs.evening_detective_server.PingReq (*PingRsp)(nil), // 1: crabs.evening_detective_server.PingRsp @@ -5096,212 +5491,228 @@ var file_main_proto_goTypes = []any{ (*LoginRsp)(nil), // 9: crabs.evening_detective_server.LoginRsp (*RefreshReq)(nil), // 10: crabs.evening_detective_server.RefreshReq (*RefreshRsp)(nil), // 11: crabs.evening_detective_server.RefreshRsp - (*GetUsersReq)(nil), // 12: crabs.evening_detective_server.GetUsersReq - (*GetUsersRsp)(nil), // 13: crabs.evening_detective_server.GetUsersRsp - (*User)(nil), // 14: crabs.evening_detective_server.User - (*GetUserByIdReq)(nil), // 15: crabs.evening_detective_server.GetUserByIdReq - (*GetUserByIdRsp)(nil), // 16: crabs.evening_detective_server.GetUserByIdRsp - (*GetMeReq)(nil), // 17: crabs.evening_detective_server.GetMeReq - (*GetMeRsp)(nil), // 18: crabs.evening_detective_server.GetMeRsp - (*AddUserRoleReq)(nil), // 19: crabs.evening_detective_server.AddUserRoleReq - (*AddUserRoleRsp)(nil), // 20: crabs.evening_detective_server.AddUserRoleRsp - (*DeleteUserRoleReq)(nil), // 21: crabs.evening_detective_server.DeleteUserRoleReq - (*DeleteUserRoleRsp)(nil), // 22: crabs.evening_detective_server.DeleteUserRoleRsp - (*GetPermissionsReq)(nil), // 23: crabs.evening_detective_server.GetPermissionsReq - (*GetPermissionsRsp)(nil), // 24: crabs.evening_detective_server.GetPermissionsRsp - (*UploadFileReq)(nil), // 25: crabs.evening_detective_server.UploadFileReq - (*UploadFileRsp)(nil), // 26: crabs.evening_detective_server.UploadFileRsp - (*DownloadFileReq)(nil), // 27: crabs.evening_detective_server.DownloadFileReq - (*AddScenarioReq)(nil), // 28: crabs.evening_detective_server.AddScenarioReq - (*AddScenarioRsp)(nil), // 29: crabs.evening_detective_server.AddScenarioRsp - (*GetMyScenariosReq)(nil), // 30: crabs.evening_detective_server.GetMyScenariosReq - (*GetMyScenariosRsp)(nil), // 31: crabs.evening_detective_server.GetMyScenariosRsp - (*GetScenariosCatalogReq)(nil), // 32: crabs.evening_detective_server.GetScenariosCatalogReq - (*GetScenariosCatalogRsp)(nil), // 33: crabs.evening_detective_server.GetScenariosCatalogRsp - (*GetScenarioReq)(nil), // 34: crabs.evening_detective_server.GetScenarioReq - (*GetScenarioRsp)(nil), // 35: crabs.evening_detective_server.GetScenarioRsp - (*Scenario)(nil), // 36: crabs.evening_detective_server.Scenario - (*Story)(nil), // 37: crabs.evening_detective_server.Story - (*Place)(nil), // 38: crabs.evening_detective_server.Place - (*Application)(nil), // 39: crabs.evening_detective_server.Application - (*Door)(nil), // 40: crabs.evening_detective_server.Door - (*Key)(nil), // 41: crabs.evening_detective_server.Key - (*UpdateScenarioReq)(nil), // 42: crabs.evening_detective_server.UpdateScenarioReq - (*UpdateScenarioRsp)(nil), // 43: crabs.evening_detective_server.UpdateScenarioRsp - (*PublicScenarioReq)(nil), // 44: crabs.evening_detective_server.PublicScenarioReq - (*PublicScenarioRsp)(nil), // 45: crabs.evening_detective_server.PublicScenarioRsp - (*DraftScenarioReq)(nil), // 46: crabs.evening_detective_server.DraftScenarioReq - (*DraftScenarioRsp)(nil), // 47: crabs.evening_detective_server.DraftScenarioRsp - (*DeleteScenarioReq)(nil), // 48: crabs.evening_detective_server.DeleteScenarioReq - (*DeleteScenarioRsp)(nil), // 49: crabs.evening_detective_server.DeleteScenarioRsp - (*AddScenarioPlaceReq)(nil), // 50: crabs.evening_detective_server.AddScenarioPlaceReq - (*AddScenarioPlaceRsp)(nil), // 51: crabs.evening_detective_server.AddScenarioPlaceRsp - (*UpdateScenarioPlaceReq)(nil), // 52: crabs.evening_detective_server.UpdateScenarioPlaceReq - (*UpdateScenarioPlaceRsp)(nil), // 53: crabs.evening_detective_server.UpdateScenarioPlaceRsp - (*DeleteScenarioPlaceReq)(nil), // 54: crabs.evening_detective_server.DeleteScenarioPlaceReq - (*DeleteScenarioPlaceRsp)(nil), // 55: crabs.evening_detective_server.DeleteScenarioPlaceRsp - (*AddGameReq)(nil), // 56: crabs.evening_detective_server.AddGameReq - (*AddGameRsp)(nil), // 57: crabs.evening_detective_server.AddGameRsp - (*GetGamesReq)(nil), // 58: crabs.evening_detective_server.GetGamesReq - (*GetGamesRsp)(nil), // 59: crabs.evening_detective_server.GetGamesRsp - (*Game)(nil), // 60: crabs.evening_detective_server.Game - (*Team)(nil), // 61: crabs.evening_detective_server.Team - (*GetGameReq)(nil), // 62: crabs.evening_detective_server.GetGameReq - (*GetGameRsp)(nil), // 63: crabs.evening_detective_server.GetGameRsp - (*UpdateGameReq)(nil), // 64: crabs.evening_detective_server.UpdateGameReq - (*UpdateGameRsp)(nil), // 65: crabs.evening_detective_server.UpdateGameRsp - (*StartGameReq)(nil), // 66: crabs.evening_detective_server.StartGameReq - (*StartGameRsp)(nil), // 67: crabs.evening_detective_server.StartGameRsp - (*PauseGameReq)(nil), // 68: crabs.evening_detective_server.PauseGameReq - (*PauseGameRsp)(nil), // 69: crabs.evening_detective_server.PauseGameRsp - (*PlayGameReq)(nil), // 70: crabs.evening_detective_server.PlayGameReq - (*PlayGameRsp)(nil), // 71: crabs.evening_detective_server.PlayGameRsp - (*FinishGameReq)(nil), // 72: crabs.evening_detective_server.FinishGameReq - (*FinishGameRsp)(nil), // 73: crabs.evening_detective_server.FinishGameRsp - (*ResetGameReq)(nil), // 74: crabs.evening_detective_server.ResetGameReq - (*ResetGameRsp)(nil), // 75: crabs.evening_detective_server.ResetGameRsp - (*DeleteGameReq)(nil), // 76: crabs.evening_detective_server.DeleteGameReq - (*DeleteGameRsp)(nil), // 77: crabs.evening_detective_server.DeleteGameRsp - (*AddTeamReq)(nil), // 78: crabs.evening_detective_server.AddTeamReq - (*AddTeamRsp)(nil), // 79: crabs.evening_detective_server.AddTeamRsp - (*UpdateTeamReq)(nil), // 80: crabs.evening_detective_server.UpdateTeamReq - (*UpdateTeamRsp)(nil), // 81: crabs.evening_detective_server.UpdateTeamRsp - (*DeleteTeamReq)(nil), // 82: crabs.evening_detective_server.DeleteTeamReq - (*DeleteTeamRsp)(nil), // 83: crabs.evening_detective_server.DeleteTeamRsp - (*GiveTeamApplicationsReq)(nil), // 84: crabs.evening_detective_server.GiveTeamApplicationsReq - (*GiveTeamApplicationsRsp)(nil), // 85: crabs.evening_detective_server.GiveTeamApplicationsRsp - (*GetTeamStoryReq)(nil), // 86: crabs.evening_detective_server.GetTeamStoryReq - (*GetTeamStoryRsp)(nil), // 87: crabs.evening_detective_server.GetTeamStoryRsp - (*AddTeamActionReq)(nil), // 88: crabs.evening_detective_server.AddTeamActionReq - (*AddTeamActionRsp)(nil), // 89: crabs.evening_detective_server.AddTeamActionRsp - (*DeleteLastTeamActionReq)(nil), // 90: crabs.evening_detective_server.DeleteLastTeamActionReq - (*DeleteLastTeamActionRsp)(nil), // 91: crabs.evening_detective_server.DeleteLastTeamActionRsp - (*timestamppb.Timestamp)(nil), // 92: google.protobuf.Timestamp - (*httpbody.HttpBody)(nil), // 93: google.api.HttpBody + (*DeleteAccountReq)(nil), // 12: crabs.evening_detective_server.DeleteAccountReq + (*DeleteAccountRsp)(nil), // 13: crabs.evening_detective_server.DeleteAccountRsp + (*GetTermsReq)(nil), // 14: crabs.evening_detective_server.GetTermsReq + (*GetTermsRsp)(nil), // 15: crabs.evening_detective_server.GetTermsRsp + (*GetPrivacyReq)(nil), // 16: crabs.evening_detective_server.GetPrivacyReq + (*GetPrivacyRsp)(nil), // 17: crabs.evening_detective_server.GetPrivacyRsp + (*GetConsentReq)(nil), // 18: crabs.evening_detective_server.GetConsentReq + (*GetConsentRsp)(nil), // 19: crabs.evening_detective_server.GetConsentRsp + (*GetUsersReq)(nil), // 20: crabs.evening_detective_server.GetUsersReq + (*GetUsersRsp)(nil), // 21: crabs.evening_detective_server.GetUsersRsp + (*User)(nil), // 22: crabs.evening_detective_server.User + (*GetUserByIdReq)(nil), // 23: crabs.evening_detective_server.GetUserByIdReq + (*GetUserByIdRsp)(nil), // 24: crabs.evening_detective_server.GetUserByIdRsp + (*GetMeReq)(nil), // 25: crabs.evening_detective_server.GetMeReq + (*GetMeRsp)(nil), // 26: crabs.evening_detective_server.GetMeRsp + (*AddUserRoleReq)(nil), // 27: crabs.evening_detective_server.AddUserRoleReq + (*AddUserRoleRsp)(nil), // 28: crabs.evening_detective_server.AddUserRoleRsp + (*DeleteUserRoleReq)(nil), // 29: crabs.evening_detective_server.DeleteUserRoleReq + (*DeleteUserRoleRsp)(nil), // 30: crabs.evening_detective_server.DeleteUserRoleRsp + (*GetPermissionsReq)(nil), // 31: crabs.evening_detective_server.GetPermissionsReq + (*GetPermissionsRsp)(nil), // 32: crabs.evening_detective_server.GetPermissionsRsp + (*UploadFileReq)(nil), // 33: crabs.evening_detective_server.UploadFileReq + (*UploadFileRsp)(nil), // 34: crabs.evening_detective_server.UploadFileRsp + (*DownloadFileReq)(nil), // 35: crabs.evening_detective_server.DownloadFileReq + (*AddScenarioReq)(nil), // 36: crabs.evening_detective_server.AddScenarioReq + (*AddScenarioRsp)(nil), // 37: crabs.evening_detective_server.AddScenarioRsp + (*GetMyScenariosReq)(nil), // 38: crabs.evening_detective_server.GetMyScenariosReq + (*GetMyScenariosRsp)(nil), // 39: crabs.evening_detective_server.GetMyScenariosRsp + (*GetScenariosCatalogReq)(nil), // 40: crabs.evening_detective_server.GetScenariosCatalogReq + (*GetScenariosCatalogRsp)(nil), // 41: crabs.evening_detective_server.GetScenariosCatalogRsp + (*GetScenarioReq)(nil), // 42: crabs.evening_detective_server.GetScenarioReq + (*GetScenarioRsp)(nil), // 43: crabs.evening_detective_server.GetScenarioRsp + (*Scenario)(nil), // 44: crabs.evening_detective_server.Scenario + (*Story)(nil), // 45: crabs.evening_detective_server.Story + (*Place)(nil), // 46: crabs.evening_detective_server.Place + (*Application)(nil), // 47: crabs.evening_detective_server.Application + (*Door)(nil), // 48: crabs.evening_detective_server.Door + (*Key)(nil), // 49: crabs.evening_detective_server.Key + (*UpdateScenarioReq)(nil), // 50: crabs.evening_detective_server.UpdateScenarioReq + (*UpdateScenarioRsp)(nil), // 51: crabs.evening_detective_server.UpdateScenarioRsp + (*PublicScenarioReq)(nil), // 52: crabs.evening_detective_server.PublicScenarioReq + (*PublicScenarioRsp)(nil), // 53: crabs.evening_detective_server.PublicScenarioRsp + (*DraftScenarioReq)(nil), // 54: crabs.evening_detective_server.DraftScenarioReq + (*DraftScenarioRsp)(nil), // 55: crabs.evening_detective_server.DraftScenarioRsp + (*DeleteScenarioReq)(nil), // 56: crabs.evening_detective_server.DeleteScenarioReq + (*DeleteScenarioRsp)(nil), // 57: crabs.evening_detective_server.DeleteScenarioRsp + (*AddScenarioPlaceReq)(nil), // 58: crabs.evening_detective_server.AddScenarioPlaceReq + (*AddScenarioPlaceRsp)(nil), // 59: crabs.evening_detective_server.AddScenarioPlaceRsp + (*UpdateScenarioPlaceReq)(nil), // 60: crabs.evening_detective_server.UpdateScenarioPlaceReq + (*UpdateScenarioPlaceRsp)(nil), // 61: crabs.evening_detective_server.UpdateScenarioPlaceRsp + (*DeleteScenarioPlaceReq)(nil), // 62: crabs.evening_detective_server.DeleteScenarioPlaceReq + (*DeleteScenarioPlaceRsp)(nil), // 63: crabs.evening_detective_server.DeleteScenarioPlaceRsp + (*AddGameReq)(nil), // 64: crabs.evening_detective_server.AddGameReq + (*AddGameRsp)(nil), // 65: crabs.evening_detective_server.AddGameRsp + (*GetGamesReq)(nil), // 66: crabs.evening_detective_server.GetGamesReq + (*GetGamesRsp)(nil), // 67: crabs.evening_detective_server.GetGamesRsp + (*Game)(nil), // 68: crabs.evening_detective_server.Game + (*Team)(nil), // 69: crabs.evening_detective_server.Team + (*GetGameReq)(nil), // 70: crabs.evening_detective_server.GetGameReq + (*GetGameRsp)(nil), // 71: crabs.evening_detective_server.GetGameRsp + (*UpdateGameReq)(nil), // 72: crabs.evening_detective_server.UpdateGameReq + (*UpdateGameRsp)(nil), // 73: crabs.evening_detective_server.UpdateGameRsp + (*StartGameReq)(nil), // 74: crabs.evening_detective_server.StartGameReq + (*StartGameRsp)(nil), // 75: crabs.evening_detective_server.StartGameRsp + (*PauseGameReq)(nil), // 76: crabs.evening_detective_server.PauseGameReq + (*PauseGameRsp)(nil), // 77: crabs.evening_detective_server.PauseGameRsp + (*PlayGameReq)(nil), // 78: crabs.evening_detective_server.PlayGameReq + (*PlayGameRsp)(nil), // 79: crabs.evening_detective_server.PlayGameRsp + (*FinishGameReq)(nil), // 80: crabs.evening_detective_server.FinishGameReq + (*FinishGameRsp)(nil), // 81: crabs.evening_detective_server.FinishGameRsp + (*ResetGameReq)(nil), // 82: crabs.evening_detective_server.ResetGameReq + (*ResetGameRsp)(nil), // 83: crabs.evening_detective_server.ResetGameRsp + (*DeleteGameReq)(nil), // 84: crabs.evening_detective_server.DeleteGameReq + (*DeleteGameRsp)(nil), // 85: crabs.evening_detective_server.DeleteGameRsp + (*AddTeamReq)(nil), // 86: crabs.evening_detective_server.AddTeamReq + (*AddTeamRsp)(nil), // 87: crabs.evening_detective_server.AddTeamRsp + (*UpdateTeamReq)(nil), // 88: crabs.evening_detective_server.UpdateTeamReq + (*UpdateTeamRsp)(nil), // 89: crabs.evening_detective_server.UpdateTeamRsp + (*DeleteTeamReq)(nil), // 90: crabs.evening_detective_server.DeleteTeamReq + (*DeleteTeamRsp)(nil), // 91: crabs.evening_detective_server.DeleteTeamRsp + (*GiveTeamApplicationsReq)(nil), // 92: crabs.evening_detective_server.GiveTeamApplicationsReq + (*GiveTeamApplicationsRsp)(nil), // 93: crabs.evening_detective_server.GiveTeamApplicationsRsp + (*GetTeamStoryReq)(nil), // 94: crabs.evening_detective_server.GetTeamStoryReq + (*GetTeamStoryRsp)(nil), // 95: crabs.evening_detective_server.GetTeamStoryRsp + (*AddTeamActionReq)(nil), // 96: crabs.evening_detective_server.AddTeamActionReq + (*AddTeamActionRsp)(nil), // 97: crabs.evening_detective_server.AddTeamActionRsp + (*DeleteLastTeamActionReq)(nil), // 98: crabs.evening_detective_server.DeleteLastTeamActionReq + (*DeleteLastTeamActionRsp)(nil), // 99: crabs.evening_detective_server.DeleteLastTeamActionRsp + (*timestamppb.Timestamp)(nil), // 100: google.protobuf.Timestamp + (*httpbody.HttpBody)(nil), // 101: google.api.HttpBody } var file_main_proto_depIdxs = []int32{ - 14, // 0: crabs.evening_detective_server.GetUsersRsp.users:type_name -> crabs.evening_detective_server.User - 92, // 1: crabs.evening_detective_server.User.created_at:type_name -> google.protobuf.Timestamp - 14, // 2: crabs.evening_detective_server.GetUserByIdRsp.user:type_name -> crabs.evening_detective_server.User - 14, // 3: crabs.evening_detective_server.GetMeRsp.user:type_name -> crabs.evening_detective_server.User - 36, // 4: crabs.evening_detective_server.GetMyScenariosRsp.scenarios:type_name -> crabs.evening_detective_server.Scenario - 36, // 5: crabs.evening_detective_server.GetScenariosCatalogRsp.scenarios:type_name -> crabs.evening_detective_server.Scenario - 36, // 6: crabs.evening_detective_server.GetScenarioRsp.scenario:type_name -> crabs.evening_detective_server.Scenario - 37, // 7: crabs.evening_detective_server.Scenario.story:type_name -> crabs.evening_detective_server.Story - 14, // 8: crabs.evening_detective_server.Scenario.author:type_name -> crabs.evening_detective_server.User - 92, // 9: crabs.evening_detective_server.Scenario.updated_at:type_name -> google.protobuf.Timestamp - 92, // 10: crabs.evening_detective_server.Scenario.created_at:type_name -> google.protobuf.Timestamp - 92, // 11: crabs.evening_detective_server.Scenario.published_at:type_name -> google.protobuf.Timestamp - 38, // 12: crabs.evening_detective_server.Story.places:type_name -> crabs.evening_detective_server.Place - 39, // 13: crabs.evening_detective_server.Place.applications:type_name -> crabs.evening_detective_server.Application - 40, // 14: crabs.evening_detective_server.Place.doors:type_name -> crabs.evening_detective_server.Door - 41, // 15: crabs.evening_detective_server.Place.keys:type_name -> crabs.evening_detective_server.Key - 41, // 16: crabs.evening_detective_server.Door.keys:type_name -> crabs.evening_detective_server.Key - 38, // 17: crabs.evening_detective_server.AddScenarioPlaceReq.place:type_name -> crabs.evening_detective_server.Place - 38, // 18: crabs.evening_detective_server.UpdateScenarioPlaceReq.place:type_name -> crabs.evening_detective_server.Place - 92, // 19: crabs.evening_detective_server.AddGameReq.start_at:type_name -> google.protobuf.Timestamp - 60, // 20: crabs.evening_detective_server.GetGamesRsp.games:type_name -> crabs.evening_detective_server.Game - 92, // 21: crabs.evening_detective_server.Game.start_at:type_name -> google.protobuf.Timestamp - 36, // 22: crabs.evening_detective_server.Game.scenario:type_name -> crabs.evening_detective_server.Scenario - 61, // 23: crabs.evening_detective_server.Game.teams:type_name -> crabs.evening_detective_server.Team - 92, // 24: crabs.evening_detective_server.Game.started_at:type_name -> google.protobuf.Timestamp - 92, // 25: crabs.evening_detective_server.Game.ended_at:type_name -> google.protobuf.Timestamp - 39, // 26: crabs.evening_detective_server.Team.applications:type_name -> crabs.evening_detective_server.Application - 60, // 27: crabs.evening_detective_server.GetGameRsp.game:type_name -> crabs.evening_detective_server.Game - 92, // 28: crabs.evening_detective_server.UpdateGameReq.start_at:type_name -> google.protobuf.Timestamp - 37, // 29: crabs.evening_detective_server.GetTeamStoryRsp.story:type_name -> crabs.evening_detective_server.Story - 60, // 30: crabs.evening_detective_server.GetTeamStoryRsp.game:type_name -> crabs.evening_detective_server.Game - 0, // 31: crabs.evening_detective_server.EveningDetectiveServer.Ping:input_type -> crabs.evening_detective_server.PingReq - 2, // 32: crabs.evening_detective_server.EveningDetectiveServer.Echo:input_type -> crabs.evening_detective_server.EchoReq - 4, // 33: crabs.evening_detective_server.EveningDetectiveServer.Signup:input_type -> crabs.evening_detective_server.SignupReq - 6, // 34: crabs.evening_detective_server.EveningDetectiveServer.RefreshPassword:input_type -> crabs.evening_detective_server.RefreshPasswordReq - 8, // 35: crabs.evening_detective_server.EveningDetectiveServer.Login:input_type -> crabs.evening_detective_server.LoginReq - 10, // 36: crabs.evening_detective_server.EveningDetectiveServer.Refresh:input_type -> crabs.evening_detective_server.RefreshReq - 12, // 37: crabs.evening_detective_server.EveningDetectiveServer.GetUsers:input_type -> crabs.evening_detective_server.GetUsersReq - 15, // 38: crabs.evening_detective_server.EveningDetectiveServer.GetUserById:input_type -> crabs.evening_detective_server.GetUserByIdReq - 17, // 39: crabs.evening_detective_server.EveningDetectiveServer.GetMe:input_type -> crabs.evening_detective_server.GetMeReq - 19, // 40: crabs.evening_detective_server.EveningDetectiveServer.AddUserRole:input_type -> crabs.evening_detective_server.AddUserRoleReq - 21, // 41: crabs.evening_detective_server.EveningDetectiveServer.DeleteUserRole:input_type -> crabs.evening_detective_server.DeleteUserRoleReq - 23, // 42: crabs.evening_detective_server.EveningDetectiveServer.GetPermissions:input_type -> crabs.evening_detective_server.GetPermissionsReq - 25, // 43: crabs.evening_detective_server.EveningDetectiveServer.UploadFile:input_type -> crabs.evening_detective_server.UploadFileReq - 27, // 44: crabs.evening_detective_server.EveningDetectiveServer.DownloadFile:input_type -> crabs.evening_detective_server.DownloadFileReq - 28, // 45: crabs.evening_detective_server.EveningDetectiveServer.AddScenario:input_type -> crabs.evening_detective_server.AddScenarioReq - 30, // 46: crabs.evening_detective_server.EveningDetectiveServer.GetMyScenarios:input_type -> crabs.evening_detective_server.GetMyScenariosReq - 32, // 47: crabs.evening_detective_server.EveningDetectiveServer.GetScenariosCatalog:input_type -> crabs.evening_detective_server.GetScenariosCatalogReq - 34, // 48: crabs.evening_detective_server.EveningDetectiveServer.GetFullScenario:input_type -> crabs.evening_detective_server.GetScenarioReq - 34, // 49: crabs.evening_detective_server.EveningDetectiveServer.GetScenario:input_type -> crabs.evening_detective_server.GetScenarioReq - 42, // 50: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenario:input_type -> crabs.evening_detective_server.UpdateScenarioReq - 44, // 51: crabs.evening_detective_server.EveningDetectiveServer.PublicScenario:input_type -> crabs.evening_detective_server.PublicScenarioReq - 46, // 52: crabs.evening_detective_server.EveningDetectiveServer.DraftScenario:input_type -> crabs.evening_detective_server.DraftScenarioReq - 48, // 53: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenario:input_type -> crabs.evening_detective_server.DeleteScenarioReq - 50, // 54: crabs.evening_detective_server.EveningDetectiveServer.AddScenarioPlace:input_type -> crabs.evening_detective_server.AddScenarioPlaceReq - 52, // 55: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioPlace:input_type -> crabs.evening_detective_server.UpdateScenarioPlaceReq - 54, // 56: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenarioPlace:input_type -> crabs.evening_detective_server.DeleteScenarioPlaceReq - 56, // 57: crabs.evening_detective_server.EveningDetectiveServer.AddGame:input_type -> crabs.evening_detective_server.AddGameReq - 58, // 58: crabs.evening_detective_server.EveningDetectiveServer.GetGames:input_type -> crabs.evening_detective_server.GetGamesReq - 62, // 59: crabs.evening_detective_server.EveningDetectiveServer.GetGame:input_type -> crabs.evening_detective_server.GetGameReq - 64, // 60: crabs.evening_detective_server.EveningDetectiveServer.UpdateGame:input_type -> crabs.evening_detective_server.UpdateGameReq - 66, // 61: crabs.evening_detective_server.EveningDetectiveServer.StartGame:input_type -> crabs.evening_detective_server.StartGameReq - 68, // 62: crabs.evening_detective_server.EveningDetectiveServer.PauseGame:input_type -> crabs.evening_detective_server.PauseGameReq - 70, // 63: crabs.evening_detective_server.EveningDetectiveServer.PlayGame:input_type -> crabs.evening_detective_server.PlayGameReq - 72, // 64: crabs.evening_detective_server.EveningDetectiveServer.FinishGame:input_type -> crabs.evening_detective_server.FinishGameReq - 74, // 65: crabs.evening_detective_server.EveningDetectiveServer.ResetGame:input_type -> crabs.evening_detective_server.ResetGameReq - 76, // 66: crabs.evening_detective_server.EveningDetectiveServer.DeleteGame:input_type -> crabs.evening_detective_server.DeleteGameReq - 78, // 67: crabs.evening_detective_server.EveningDetectiveServer.AddTeam:input_type -> crabs.evening_detective_server.AddTeamReq - 80, // 68: crabs.evening_detective_server.EveningDetectiveServer.UpdateTeam:input_type -> crabs.evening_detective_server.UpdateTeamReq - 82, // 69: crabs.evening_detective_server.EveningDetectiveServer.DeleteTeam:input_type -> crabs.evening_detective_server.DeleteTeamReq - 84, // 70: crabs.evening_detective_server.EveningDetectiveServer.GiveTeamApplications:input_type -> crabs.evening_detective_server.GiveTeamApplicationsReq - 86, // 71: crabs.evening_detective_server.EveningDetectiveServer.GetTeamStory:input_type -> crabs.evening_detective_server.GetTeamStoryReq - 88, // 72: crabs.evening_detective_server.EveningDetectiveServer.AddTeamAction:input_type -> crabs.evening_detective_server.AddTeamActionReq - 90, // 73: crabs.evening_detective_server.EveningDetectiveServer.DeleteLastTeamAction:input_type -> crabs.evening_detective_server.DeleteLastTeamActionReq - 1, // 74: crabs.evening_detective_server.EveningDetectiveServer.Ping:output_type -> crabs.evening_detective_server.PingRsp - 3, // 75: crabs.evening_detective_server.EveningDetectiveServer.Echo:output_type -> crabs.evening_detective_server.EchoRsp - 5, // 76: crabs.evening_detective_server.EveningDetectiveServer.Signup:output_type -> crabs.evening_detective_server.SignupRsp - 7, // 77: crabs.evening_detective_server.EveningDetectiveServer.RefreshPassword:output_type -> crabs.evening_detective_server.RefreshPasswordRsp - 9, // 78: crabs.evening_detective_server.EveningDetectiveServer.Login:output_type -> crabs.evening_detective_server.LoginRsp - 11, // 79: crabs.evening_detective_server.EveningDetectiveServer.Refresh:output_type -> crabs.evening_detective_server.RefreshRsp - 13, // 80: crabs.evening_detective_server.EveningDetectiveServer.GetUsers:output_type -> crabs.evening_detective_server.GetUsersRsp - 16, // 81: crabs.evening_detective_server.EveningDetectiveServer.GetUserById:output_type -> crabs.evening_detective_server.GetUserByIdRsp - 18, // 82: crabs.evening_detective_server.EveningDetectiveServer.GetMe:output_type -> crabs.evening_detective_server.GetMeRsp - 20, // 83: crabs.evening_detective_server.EveningDetectiveServer.AddUserRole:output_type -> crabs.evening_detective_server.AddUserRoleRsp - 22, // 84: crabs.evening_detective_server.EveningDetectiveServer.DeleteUserRole:output_type -> crabs.evening_detective_server.DeleteUserRoleRsp - 24, // 85: crabs.evening_detective_server.EveningDetectiveServer.GetPermissions:output_type -> crabs.evening_detective_server.GetPermissionsRsp - 26, // 86: crabs.evening_detective_server.EveningDetectiveServer.UploadFile:output_type -> crabs.evening_detective_server.UploadFileRsp - 93, // 87: crabs.evening_detective_server.EveningDetectiveServer.DownloadFile:output_type -> google.api.HttpBody - 29, // 88: crabs.evening_detective_server.EveningDetectiveServer.AddScenario:output_type -> crabs.evening_detective_server.AddScenarioRsp - 31, // 89: crabs.evening_detective_server.EveningDetectiveServer.GetMyScenarios:output_type -> crabs.evening_detective_server.GetMyScenariosRsp - 33, // 90: crabs.evening_detective_server.EveningDetectiveServer.GetScenariosCatalog:output_type -> crabs.evening_detective_server.GetScenariosCatalogRsp - 35, // 91: crabs.evening_detective_server.EveningDetectiveServer.GetFullScenario:output_type -> crabs.evening_detective_server.GetScenarioRsp - 35, // 92: crabs.evening_detective_server.EveningDetectiveServer.GetScenario:output_type -> crabs.evening_detective_server.GetScenarioRsp - 43, // 93: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenario:output_type -> crabs.evening_detective_server.UpdateScenarioRsp - 45, // 94: crabs.evening_detective_server.EveningDetectiveServer.PublicScenario:output_type -> crabs.evening_detective_server.PublicScenarioRsp - 47, // 95: crabs.evening_detective_server.EveningDetectiveServer.DraftScenario:output_type -> crabs.evening_detective_server.DraftScenarioRsp - 49, // 96: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenario:output_type -> crabs.evening_detective_server.DeleteScenarioRsp - 51, // 97: crabs.evening_detective_server.EveningDetectiveServer.AddScenarioPlace:output_type -> crabs.evening_detective_server.AddScenarioPlaceRsp - 53, // 98: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioPlace:output_type -> crabs.evening_detective_server.UpdateScenarioPlaceRsp - 55, // 99: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenarioPlace:output_type -> crabs.evening_detective_server.DeleteScenarioPlaceRsp - 57, // 100: crabs.evening_detective_server.EveningDetectiveServer.AddGame:output_type -> crabs.evening_detective_server.AddGameRsp - 59, // 101: crabs.evening_detective_server.EveningDetectiveServer.GetGames:output_type -> crabs.evening_detective_server.GetGamesRsp - 63, // 102: crabs.evening_detective_server.EveningDetectiveServer.GetGame:output_type -> crabs.evening_detective_server.GetGameRsp - 65, // 103: crabs.evening_detective_server.EveningDetectiveServer.UpdateGame:output_type -> crabs.evening_detective_server.UpdateGameRsp - 67, // 104: crabs.evening_detective_server.EveningDetectiveServer.StartGame:output_type -> crabs.evening_detective_server.StartGameRsp - 69, // 105: crabs.evening_detective_server.EveningDetectiveServer.PauseGame:output_type -> crabs.evening_detective_server.PauseGameRsp - 71, // 106: crabs.evening_detective_server.EveningDetectiveServer.PlayGame:output_type -> crabs.evening_detective_server.PlayGameRsp - 73, // 107: crabs.evening_detective_server.EveningDetectiveServer.FinishGame:output_type -> crabs.evening_detective_server.FinishGameRsp - 75, // 108: crabs.evening_detective_server.EveningDetectiveServer.ResetGame:output_type -> crabs.evening_detective_server.ResetGameRsp - 77, // 109: crabs.evening_detective_server.EveningDetectiveServer.DeleteGame:output_type -> crabs.evening_detective_server.DeleteGameRsp - 79, // 110: crabs.evening_detective_server.EveningDetectiveServer.AddTeam:output_type -> crabs.evening_detective_server.AddTeamRsp - 81, // 111: crabs.evening_detective_server.EveningDetectiveServer.UpdateTeam:output_type -> crabs.evening_detective_server.UpdateTeamRsp - 83, // 112: crabs.evening_detective_server.EveningDetectiveServer.DeleteTeam:output_type -> crabs.evening_detective_server.DeleteTeamRsp - 85, // 113: crabs.evening_detective_server.EveningDetectiveServer.GiveTeamApplications:output_type -> crabs.evening_detective_server.GiveTeamApplicationsRsp - 87, // 114: crabs.evening_detective_server.EveningDetectiveServer.GetTeamStory:output_type -> crabs.evening_detective_server.GetTeamStoryRsp - 89, // 115: crabs.evening_detective_server.EveningDetectiveServer.AddTeamAction:output_type -> crabs.evening_detective_server.AddTeamActionRsp - 91, // 116: crabs.evening_detective_server.EveningDetectiveServer.DeleteLastTeamAction:output_type -> crabs.evening_detective_server.DeleteLastTeamActionRsp - 74, // [74:117] is the sub-list for method output_type - 31, // [31:74] is the sub-list for method input_type - 31, // [31:31] is the sub-list for extension type_name - 31, // [31:31] is the sub-list for extension extendee - 0, // [0:31] is the sub-list for field type_name + 22, // 0: crabs.evening_detective_server.GetUsersRsp.users:type_name -> crabs.evening_detective_server.User + 100, // 1: crabs.evening_detective_server.User.created_at:type_name -> google.protobuf.Timestamp + 22, // 2: crabs.evening_detective_server.GetUserByIdRsp.user:type_name -> crabs.evening_detective_server.User + 22, // 3: crabs.evening_detective_server.GetMeRsp.user:type_name -> crabs.evening_detective_server.User + 44, // 4: crabs.evening_detective_server.GetMyScenariosRsp.scenarios:type_name -> crabs.evening_detective_server.Scenario + 44, // 5: crabs.evening_detective_server.GetScenariosCatalogRsp.scenarios:type_name -> crabs.evening_detective_server.Scenario + 44, // 6: crabs.evening_detective_server.GetScenarioRsp.scenario:type_name -> crabs.evening_detective_server.Scenario + 45, // 7: crabs.evening_detective_server.Scenario.story:type_name -> crabs.evening_detective_server.Story + 22, // 8: crabs.evening_detective_server.Scenario.author:type_name -> crabs.evening_detective_server.User + 100, // 9: crabs.evening_detective_server.Scenario.updated_at:type_name -> google.protobuf.Timestamp + 100, // 10: crabs.evening_detective_server.Scenario.created_at:type_name -> google.protobuf.Timestamp + 100, // 11: crabs.evening_detective_server.Scenario.published_at:type_name -> google.protobuf.Timestamp + 46, // 12: crabs.evening_detective_server.Story.places:type_name -> crabs.evening_detective_server.Place + 47, // 13: crabs.evening_detective_server.Place.applications:type_name -> crabs.evening_detective_server.Application + 48, // 14: crabs.evening_detective_server.Place.doors:type_name -> crabs.evening_detective_server.Door + 49, // 15: crabs.evening_detective_server.Place.keys:type_name -> crabs.evening_detective_server.Key + 49, // 16: crabs.evening_detective_server.Door.keys:type_name -> crabs.evening_detective_server.Key + 46, // 17: crabs.evening_detective_server.AddScenarioPlaceReq.place:type_name -> crabs.evening_detective_server.Place + 46, // 18: crabs.evening_detective_server.UpdateScenarioPlaceReq.place:type_name -> crabs.evening_detective_server.Place + 100, // 19: crabs.evening_detective_server.AddGameReq.start_at:type_name -> google.protobuf.Timestamp + 68, // 20: crabs.evening_detective_server.GetGamesRsp.games:type_name -> crabs.evening_detective_server.Game + 100, // 21: crabs.evening_detective_server.Game.start_at:type_name -> google.protobuf.Timestamp + 44, // 22: crabs.evening_detective_server.Game.scenario:type_name -> crabs.evening_detective_server.Scenario + 69, // 23: crabs.evening_detective_server.Game.teams:type_name -> crabs.evening_detective_server.Team + 100, // 24: crabs.evening_detective_server.Game.started_at:type_name -> google.protobuf.Timestamp + 100, // 25: crabs.evening_detective_server.Game.ended_at:type_name -> google.protobuf.Timestamp + 47, // 26: crabs.evening_detective_server.Team.applications:type_name -> crabs.evening_detective_server.Application + 68, // 27: crabs.evening_detective_server.GetGameRsp.game:type_name -> crabs.evening_detective_server.Game + 100, // 28: crabs.evening_detective_server.UpdateGameReq.start_at:type_name -> google.protobuf.Timestamp + 45, // 29: crabs.evening_detective_server.GetTeamStoryRsp.story:type_name -> crabs.evening_detective_server.Story + 68, // 30: crabs.evening_detective_server.GetTeamStoryRsp.game:type_name -> crabs.evening_detective_server.Game + 0, // 31: crabs.evening_detective_server.EveningDetectiveServer.Ping:input_type -> crabs.evening_detective_server.PingReq + 2, // 32: crabs.evening_detective_server.EveningDetectiveServer.Echo:input_type -> crabs.evening_detective_server.EchoReq + 4, // 33: crabs.evening_detective_server.EveningDetectiveServer.Signup:input_type -> crabs.evening_detective_server.SignupReq + 6, // 34: crabs.evening_detective_server.EveningDetectiveServer.RefreshPassword:input_type -> crabs.evening_detective_server.RefreshPasswordReq + 8, // 35: crabs.evening_detective_server.EveningDetectiveServer.Login:input_type -> crabs.evening_detective_server.LoginReq + 10, // 36: crabs.evening_detective_server.EveningDetectiveServer.Refresh:input_type -> crabs.evening_detective_server.RefreshReq + 12, // 37: crabs.evening_detective_server.EveningDetectiveServer.DeleteAccount:input_type -> crabs.evening_detective_server.DeleteAccountReq + 14, // 38: crabs.evening_detective_server.EveningDetectiveServer.GetTerms:input_type -> crabs.evening_detective_server.GetTermsReq + 16, // 39: crabs.evening_detective_server.EveningDetectiveServer.GetPrivacy:input_type -> crabs.evening_detective_server.GetPrivacyReq + 18, // 40: crabs.evening_detective_server.EveningDetectiveServer.GetConsent:input_type -> crabs.evening_detective_server.GetConsentReq + 20, // 41: crabs.evening_detective_server.EveningDetectiveServer.GetUsers:input_type -> crabs.evening_detective_server.GetUsersReq + 23, // 42: crabs.evening_detective_server.EveningDetectiveServer.GetUserById:input_type -> crabs.evening_detective_server.GetUserByIdReq + 25, // 43: crabs.evening_detective_server.EveningDetectiveServer.GetMe:input_type -> crabs.evening_detective_server.GetMeReq + 27, // 44: crabs.evening_detective_server.EveningDetectiveServer.AddUserRole:input_type -> crabs.evening_detective_server.AddUserRoleReq + 29, // 45: crabs.evening_detective_server.EveningDetectiveServer.DeleteUserRole:input_type -> crabs.evening_detective_server.DeleteUserRoleReq + 31, // 46: crabs.evening_detective_server.EveningDetectiveServer.GetPermissions:input_type -> crabs.evening_detective_server.GetPermissionsReq + 33, // 47: crabs.evening_detective_server.EveningDetectiveServer.UploadFile:input_type -> crabs.evening_detective_server.UploadFileReq + 35, // 48: crabs.evening_detective_server.EveningDetectiveServer.DownloadFile:input_type -> crabs.evening_detective_server.DownloadFileReq + 36, // 49: crabs.evening_detective_server.EveningDetectiveServer.AddScenario:input_type -> crabs.evening_detective_server.AddScenarioReq + 38, // 50: crabs.evening_detective_server.EveningDetectiveServer.GetMyScenarios:input_type -> crabs.evening_detective_server.GetMyScenariosReq + 40, // 51: crabs.evening_detective_server.EveningDetectiveServer.GetScenariosCatalog:input_type -> crabs.evening_detective_server.GetScenariosCatalogReq + 42, // 52: crabs.evening_detective_server.EveningDetectiveServer.GetFullScenario:input_type -> crabs.evening_detective_server.GetScenarioReq + 42, // 53: crabs.evening_detective_server.EveningDetectiveServer.GetScenario:input_type -> crabs.evening_detective_server.GetScenarioReq + 50, // 54: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenario:input_type -> crabs.evening_detective_server.UpdateScenarioReq + 52, // 55: crabs.evening_detective_server.EveningDetectiveServer.PublicScenario:input_type -> crabs.evening_detective_server.PublicScenarioReq + 54, // 56: crabs.evening_detective_server.EveningDetectiveServer.DraftScenario:input_type -> crabs.evening_detective_server.DraftScenarioReq + 56, // 57: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenario:input_type -> crabs.evening_detective_server.DeleteScenarioReq + 58, // 58: crabs.evening_detective_server.EveningDetectiveServer.AddScenarioPlace:input_type -> crabs.evening_detective_server.AddScenarioPlaceReq + 60, // 59: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioPlace:input_type -> crabs.evening_detective_server.UpdateScenarioPlaceReq + 62, // 60: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenarioPlace:input_type -> crabs.evening_detective_server.DeleteScenarioPlaceReq + 64, // 61: crabs.evening_detective_server.EveningDetectiveServer.AddGame:input_type -> crabs.evening_detective_server.AddGameReq + 66, // 62: crabs.evening_detective_server.EveningDetectiveServer.GetGames:input_type -> crabs.evening_detective_server.GetGamesReq + 70, // 63: crabs.evening_detective_server.EveningDetectiveServer.GetGame:input_type -> crabs.evening_detective_server.GetGameReq + 72, // 64: crabs.evening_detective_server.EveningDetectiveServer.UpdateGame:input_type -> crabs.evening_detective_server.UpdateGameReq + 74, // 65: crabs.evening_detective_server.EveningDetectiveServer.StartGame:input_type -> crabs.evening_detective_server.StartGameReq + 76, // 66: crabs.evening_detective_server.EveningDetectiveServer.PauseGame:input_type -> crabs.evening_detective_server.PauseGameReq + 78, // 67: crabs.evening_detective_server.EveningDetectiveServer.PlayGame:input_type -> crabs.evening_detective_server.PlayGameReq + 80, // 68: crabs.evening_detective_server.EveningDetectiveServer.FinishGame:input_type -> crabs.evening_detective_server.FinishGameReq + 82, // 69: crabs.evening_detective_server.EveningDetectiveServer.ResetGame:input_type -> crabs.evening_detective_server.ResetGameReq + 84, // 70: crabs.evening_detective_server.EveningDetectiveServer.DeleteGame:input_type -> crabs.evening_detective_server.DeleteGameReq + 86, // 71: crabs.evening_detective_server.EveningDetectiveServer.AddTeam:input_type -> crabs.evening_detective_server.AddTeamReq + 88, // 72: crabs.evening_detective_server.EveningDetectiveServer.UpdateTeam:input_type -> crabs.evening_detective_server.UpdateTeamReq + 90, // 73: crabs.evening_detective_server.EveningDetectiveServer.DeleteTeam:input_type -> crabs.evening_detective_server.DeleteTeamReq + 92, // 74: crabs.evening_detective_server.EveningDetectiveServer.GiveTeamApplications:input_type -> crabs.evening_detective_server.GiveTeamApplicationsReq + 94, // 75: crabs.evening_detective_server.EveningDetectiveServer.GetTeamStory:input_type -> crabs.evening_detective_server.GetTeamStoryReq + 96, // 76: crabs.evening_detective_server.EveningDetectiveServer.AddTeamAction:input_type -> crabs.evening_detective_server.AddTeamActionReq + 98, // 77: crabs.evening_detective_server.EveningDetectiveServer.DeleteLastTeamAction:input_type -> crabs.evening_detective_server.DeleteLastTeamActionReq + 1, // 78: crabs.evening_detective_server.EveningDetectiveServer.Ping:output_type -> crabs.evening_detective_server.PingRsp + 3, // 79: crabs.evening_detective_server.EveningDetectiveServer.Echo:output_type -> crabs.evening_detective_server.EchoRsp + 5, // 80: crabs.evening_detective_server.EveningDetectiveServer.Signup:output_type -> crabs.evening_detective_server.SignupRsp + 7, // 81: crabs.evening_detective_server.EveningDetectiveServer.RefreshPassword:output_type -> crabs.evening_detective_server.RefreshPasswordRsp + 9, // 82: crabs.evening_detective_server.EveningDetectiveServer.Login:output_type -> crabs.evening_detective_server.LoginRsp + 11, // 83: crabs.evening_detective_server.EveningDetectiveServer.Refresh:output_type -> crabs.evening_detective_server.RefreshRsp + 13, // 84: crabs.evening_detective_server.EveningDetectiveServer.DeleteAccount:output_type -> crabs.evening_detective_server.DeleteAccountRsp + 15, // 85: crabs.evening_detective_server.EveningDetectiveServer.GetTerms:output_type -> crabs.evening_detective_server.GetTermsRsp + 17, // 86: crabs.evening_detective_server.EveningDetectiveServer.GetPrivacy:output_type -> crabs.evening_detective_server.GetPrivacyRsp + 19, // 87: crabs.evening_detective_server.EveningDetectiveServer.GetConsent:output_type -> crabs.evening_detective_server.GetConsentRsp + 21, // 88: crabs.evening_detective_server.EveningDetectiveServer.GetUsers:output_type -> crabs.evening_detective_server.GetUsersRsp + 24, // 89: crabs.evening_detective_server.EveningDetectiveServer.GetUserById:output_type -> crabs.evening_detective_server.GetUserByIdRsp + 26, // 90: crabs.evening_detective_server.EveningDetectiveServer.GetMe:output_type -> crabs.evening_detective_server.GetMeRsp + 28, // 91: crabs.evening_detective_server.EveningDetectiveServer.AddUserRole:output_type -> crabs.evening_detective_server.AddUserRoleRsp + 30, // 92: crabs.evening_detective_server.EveningDetectiveServer.DeleteUserRole:output_type -> crabs.evening_detective_server.DeleteUserRoleRsp + 32, // 93: crabs.evening_detective_server.EveningDetectiveServer.GetPermissions:output_type -> crabs.evening_detective_server.GetPermissionsRsp + 34, // 94: crabs.evening_detective_server.EveningDetectiveServer.UploadFile:output_type -> crabs.evening_detective_server.UploadFileRsp + 101, // 95: crabs.evening_detective_server.EveningDetectiveServer.DownloadFile:output_type -> google.api.HttpBody + 37, // 96: crabs.evening_detective_server.EveningDetectiveServer.AddScenario:output_type -> crabs.evening_detective_server.AddScenarioRsp + 39, // 97: crabs.evening_detective_server.EveningDetectiveServer.GetMyScenarios:output_type -> crabs.evening_detective_server.GetMyScenariosRsp + 41, // 98: crabs.evening_detective_server.EveningDetectiveServer.GetScenariosCatalog:output_type -> crabs.evening_detective_server.GetScenariosCatalogRsp + 43, // 99: crabs.evening_detective_server.EveningDetectiveServer.GetFullScenario:output_type -> crabs.evening_detective_server.GetScenarioRsp + 43, // 100: crabs.evening_detective_server.EveningDetectiveServer.GetScenario:output_type -> crabs.evening_detective_server.GetScenarioRsp + 51, // 101: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenario:output_type -> crabs.evening_detective_server.UpdateScenarioRsp + 53, // 102: crabs.evening_detective_server.EveningDetectiveServer.PublicScenario:output_type -> crabs.evening_detective_server.PublicScenarioRsp + 55, // 103: crabs.evening_detective_server.EveningDetectiveServer.DraftScenario:output_type -> crabs.evening_detective_server.DraftScenarioRsp + 57, // 104: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenario:output_type -> crabs.evening_detective_server.DeleteScenarioRsp + 59, // 105: crabs.evening_detective_server.EveningDetectiveServer.AddScenarioPlace:output_type -> crabs.evening_detective_server.AddScenarioPlaceRsp + 61, // 106: crabs.evening_detective_server.EveningDetectiveServer.UpdateScenarioPlace:output_type -> crabs.evening_detective_server.UpdateScenarioPlaceRsp + 63, // 107: crabs.evening_detective_server.EveningDetectiveServer.DeleteScenarioPlace:output_type -> crabs.evening_detective_server.DeleteScenarioPlaceRsp + 65, // 108: crabs.evening_detective_server.EveningDetectiveServer.AddGame:output_type -> crabs.evening_detective_server.AddGameRsp + 67, // 109: crabs.evening_detective_server.EveningDetectiveServer.GetGames:output_type -> crabs.evening_detective_server.GetGamesRsp + 71, // 110: crabs.evening_detective_server.EveningDetectiveServer.GetGame:output_type -> crabs.evening_detective_server.GetGameRsp + 73, // 111: crabs.evening_detective_server.EveningDetectiveServer.UpdateGame:output_type -> crabs.evening_detective_server.UpdateGameRsp + 75, // 112: crabs.evening_detective_server.EveningDetectiveServer.StartGame:output_type -> crabs.evening_detective_server.StartGameRsp + 77, // 113: crabs.evening_detective_server.EveningDetectiveServer.PauseGame:output_type -> crabs.evening_detective_server.PauseGameRsp + 79, // 114: crabs.evening_detective_server.EveningDetectiveServer.PlayGame:output_type -> crabs.evening_detective_server.PlayGameRsp + 81, // 115: crabs.evening_detective_server.EveningDetectiveServer.FinishGame:output_type -> crabs.evening_detective_server.FinishGameRsp + 83, // 116: crabs.evening_detective_server.EveningDetectiveServer.ResetGame:output_type -> crabs.evening_detective_server.ResetGameRsp + 85, // 117: crabs.evening_detective_server.EveningDetectiveServer.DeleteGame:output_type -> crabs.evening_detective_server.DeleteGameRsp + 87, // 118: crabs.evening_detective_server.EveningDetectiveServer.AddTeam:output_type -> crabs.evening_detective_server.AddTeamRsp + 89, // 119: crabs.evening_detective_server.EveningDetectiveServer.UpdateTeam:output_type -> crabs.evening_detective_server.UpdateTeamRsp + 91, // 120: crabs.evening_detective_server.EveningDetectiveServer.DeleteTeam:output_type -> crabs.evening_detective_server.DeleteTeamRsp + 93, // 121: crabs.evening_detective_server.EveningDetectiveServer.GiveTeamApplications:output_type -> crabs.evening_detective_server.GiveTeamApplicationsRsp + 95, // 122: crabs.evening_detective_server.EveningDetectiveServer.GetTeamStory:output_type -> crabs.evening_detective_server.GetTeamStoryRsp + 97, // 123: crabs.evening_detective_server.EveningDetectiveServer.AddTeamAction:output_type -> crabs.evening_detective_server.AddTeamActionRsp + 99, // 124: crabs.evening_detective_server.EveningDetectiveServer.DeleteLastTeamAction:output_type -> crabs.evening_detective_server.DeleteLastTeamActionRsp + 78, // [78:125] is the sub-list for method output_type + 31, // [31:78] is the sub-list for method input_type + 31, // [31:31] is the sub-list for extension type_name + 31, // [31:31] is the sub-list for extension extendee + 0, // [0:31] is the sub-list for field type_name } func init() { file_main_proto_init() } @@ -5309,15 +5720,15 @@ func file_main_proto_init() { if File_main_proto != nil { return } - file_main_proto_msgTypes[36].OneofWrappers = []any{} - file_main_proto_msgTypes[60].OneofWrappers = []any{} + file_main_proto_msgTypes[44].OneofWrappers = []any{} + file_main_proto_msgTypes[68].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: 0, - NumMessages: 92, + NumMessages: 100, NumExtensions: 0, NumServices: 1, }, diff --git a/proto/main.pb.gw.go b/proto/main.pb.gw.go index 66dc781..bcc7eb7 100644 --- a/proto/main.pb.gw.go +++ b/proto/main.pb.gw.go @@ -199,6 +199,90 @@ func local_request_EveningDetectiveServer_Refresh_0(ctx context.Context, marshal return msg, metadata, err } +func request_EveningDetectiveServer_DeleteAccount_0(ctx context.Context, marshaler runtime.Marshaler, client EveningDetectiveServerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq DeleteAccountReq + metadata runtime.ServerMetadata + ) + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + msg, err := client.DeleteAccount(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_EveningDetectiveServer_DeleteAccount_0(ctx context.Context, marshaler runtime.Marshaler, server EveningDetectiveServerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq DeleteAccountReq + metadata runtime.ServerMetadata + ) + msg, err := server.DeleteAccount(ctx, &protoReq) + return msg, metadata, err +} + +func request_EveningDetectiveServer_GetTerms_0(ctx context.Context, marshaler runtime.Marshaler, client EveningDetectiveServerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetTermsReq + metadata runtime.ServerMetadata + ) + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + msg, err := client.GetTerms(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_EveningDetectiveServer_GetTerms_0(ctx context.Context, marshaler runtime.Marshaler, server EveningDetectiveServerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetTermsReq + metadata runtime.ServerMetadata + ) + msg, err := server.GetTerms(ctx, &protoReq) + return msg, metadata, err +} + +func request_EveningDetectiveServer_GetPrivacy_0(ctx context.Context, marshaler runtime.Marshaler, client EveningDetectiveServerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetPrivacyReq + metadata runtime.ServerMetadata + ) + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + msg, err := client.GetPrivacy(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_EveningDetectiveServer_GetPrivacy_0(ctx context.Context, marshaler runtime.Marshaler, server EveningDetectiveServerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetPrivacyReq + metadata runtime.ServerMetadata + ) + msg, err := server.GetPrivacy(ctx, &protoReq) + return msg, metadata, err +} + +func request_EveningDetectiveServer_GetConsent_0(ctx context.Context, marshaler runtime.Marshaler, client EveningDetectiveServerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetConsentReq + metadata runtime.ServerMetadata + ) + if req.Body != nil { + _, _ = io.Copy(io.Discard, req.Body) + } + msg, err := client.GetConsent(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_EveningDetectiveServer_GetConsent_0(ctx context.Context, marshaler runtime.Marshaler, server EveningDetectiveServerServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetConsentReq + metadata runtime.ServerMetadata + ) + msg, err := server.GetConsent(ctx, &protoReq) + return msg, metadata, err +} + func request_EveningDetectiveServer_GetUsers_0(ctx context.Context, marshaler runtime.Marshaler, client EveningDetectiveServerClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var ( protoReq GetUsersReq @@ -1754,6 +1838,86 @@ func RegisterEveningDetectiveServerHandlerServer(ctx context.Context, mux *runti } forward_EveningDetectiveServer_Refresh_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) + mux.Handle(http.MethodDelete, pattern_EveningDetectiveServer_DeleteAccount_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/DeleteAccount", runtime.WithHTTPPathPattern("/api/auth/delete-account")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_EveningDetectiveServer_DeleteAccount_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_DeleteAccount_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodGet, pattern_EveningDetectiveServer_GetTerms_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/GetTerms", runtime.WithHTTPPathPattern("/terms")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_EveningDetectiveServer_GetTerms_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_GetTerms_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodGet, pattern_EveningDetectiveServer_GetPrivacy_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/GetPrivacy", runtime.WithHTTPPathPattern("/privacy")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_EveningDetectiveServer_GetPrivacy_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_GetPrivacy_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodGet, pattern_EveningDetectiveServer_GetConsent_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/GetConsent", runtime.WithHTTPPathPattern("/consent")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_EveningDetectiveServer_GetConsent_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_GetConsent_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) mux.Handle(http.MethodGet, pattern_EveningDetectiveServer_GetUsers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -2636,6 +2800,74 @@ func RegisterEveningDetectiveServerHandlerClient(ctx context.Context, mux *runti } forward_EveningDetectiveServer_Refresh_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) + mux.Handle(http.MethodDelete, pattern_EveningDetectiveServer_DeleteAccount_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/DeleteAccount", runtime.WithHTTPPathPattern("/api/auth/delete-account")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_EveningDetectiveServer_DeleteAccount_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_DeleteAccount_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodGet, pattern_EveningDetectiveServer_GetTerms_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/GetTerms", runtime.WithHTTPPathPattern("/terms")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_EveningDetectiveServer_GetTerms_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_GetTerms_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodGet, pattern_EveningDetectiveServer_GetPrivacy_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/GetPrivacy", runtime.WithHTTPPathPattern("/privacy")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_EveningDetectiveServer_GetPrivacy_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_GetPrivacy_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle(http.MethodGet, pattern_EveningDetectiveServer_GetConsent_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/GetConsent", runtime.WithHTTPPathPattern("/consent")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_EveningDetectiveServer_GetConsent_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_GetConsent_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) mux.Handle(http.MethodGet, pattern_EveningDetectiveServer_GetUsers_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -3275,6 +3507,10 @@ var ( pattern_EveningDetectiveServer_RefreshPassword_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "auth", "refresh-password"}, "")) pattern_EveningDetectiveServer_Login_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "auth", "login"}, "")) pattern_EveningDetectiveServer_Refresh_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "auth", "refresh"}, "")) + pattern_EveningDetectiveServer_DeleteAccount_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "auth", "delete-account"}, "")) + pattern_EveningDetectiveServer_GetTerms_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"terms"}, "")) + pattern_EveningDetectiveServer_GetPrivacy_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"privacy"}, "")) + pattern_EveningDetectiveServer_GetConsent_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"consent"}, "")) pattern_EveningDetectiveServer_GetUsers_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"api", "users"}, "")) pattern_EveningDetectiveServer_GetUserById_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"api", "users", "id"}, "")) pattern_EveningDetectiveServer_GetMe_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "users", "me"}, "")) @@ -3321,6 +3557,10 @@ var ( forward_EveningDetectiveServer_RefreshPassword_0 = runtime.ForwardResponseMessage forward_EveningDetectiveServer_Login_0 = runtime.ForwardResponseMessage forward_EveningDetectiveServer_Refresh_0 = runtime.ForwardResponseMessage + forward_EveningDetectiveServer_DeleteAccount_0 = runtime.ForwardResponseMessage + forward_EveningDetectiveServer_GetTerms_0 = runtime.ForwardResponseMessage + forward_EveningDetectiveServer_GetPrivacy_0 = runtime.ForwardResponseMessage + forward_EveningDetectiveServer_GetConsent_0 = runtime.ForwardResponseMessage forward_EveningDetectiveServer_GetUsers_0 = runtime.ForwardResponseMessage forward_EveningDetectiveServer_GetUserById_0 = runtime.ForwardResponseMessage forward_EveningDetectiveServer_GetMe_0 = runtime.ForwardResponseMessage diff --git a/proto/main_grpc.pb.go b/proto/main_grpc.pb.go index 07699de..a4be14a 100644 --- a/proto/main_grpc.pb.go +++ b/proto/main_grpc.pb.go @@ -26,6 +26,10 @@ const ( EveningDetectiveServer_RefreshPassword_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/RefreshPassword" EveningDetectiveServer_Login_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/Login" EveningDetectiveServer_Refresh_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/Refresh" + EveningDetectiveServer_DeleteAccount_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/DeleteAccount" + EveningDetectiveServer_GetTerms_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/GetTerms" + EveningDetectiveServer_GetPrivacy_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/GetPrivacy" + EveningDetectiveServer_GetConsent_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/GetConsent" EveningDetectiveServer_GetUsers_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/GetUsers" EveningDetectiveServer_GetUserById_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/GetUserById" EveningDetectiveServer_GetMe_FullMethodName = "/crabs.evening_detective_server.EveningDetectiveServer/GetMe" @@ -75,6 +79,10 @@ type EveningDetectiveServerClient interface { RefreshPassword(ctx context.Context, in *RefreshPasswordReq, opts ...grpc.CallOption) (*RefreshPasswordRsp, error) Login(ctx context.Context, in *LoginReq, opts ...grpc.CallOption) (*LoginRsp, error) Refresh(ctx context.Context, in *RefreshReq, opts ...grpc.CallOption) (*RefreshRsp, error) + DeleteAccount(ctx context.Context, in *DeleteAccountReq, opts ...grpc.CallOption) (*DeleteAccountRsp, error) + GetTerms(ctx context.Context, in *GetTermsReq, opts ...grpc.CallOption) (*GetTermsRsp, error) + GetPrivacy(ctx context.Context, in *GetPrivacyReq, opts ...grpc.CallOption) (*GetPrivacyRsp, error) + GetConsent(ctx context.Context, in *GetConsentReq, opts ...grpc.CallOption) (*GetConsentRsp, error) GetUsers(ctx context.Context, in *GetUsersReq, opts ...grpc.CallOption) (*GetUsersRsp, error) GetUserById(ctx context.Context, in *GetUserByIdReq, opts ...grpc.CallOption) (*GetUserByIdRsp, error) GetMe(ctx context.Context, in *GetMeReq, opts ...grpc.CallOption) (*GetMeRsp, error) @@ -182,6 +190,46 @@ func (c *eveningDetectiveServerClient) Refresh(ctx context.Context, in *RefreshR return out, nil } +func (c *eveningDetectiveServerClient) DeleteAccount(ctx context.Context, in *DeleteAccountReq, opts ...grpc.CallOption) (*DeleteAccountRsp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(DeleteAccountRsp) + err := c.cc.Invoke(ctx, EveningDetectiveServer_DeleteAccount_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *eveningDetectiveServerClient) GetTerms(ctx context.Context, in *GetTermsReq, opts ...grpc.CallOption) (*GetTermsRsp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetTermsRsp) + err := c.cc.Invoke(ctx, EveningDetectiveServer_GetTerms_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *eveningDetectiveServerClient) GetPrivacy(ctx context.Context, in *GetPrivacyReq, opts ...grpc.CallOption) (*GetPrivacyRsp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetPrivacyRsp) + err := c.cc.Invoke(ctx, EveningDetectiveServer_GetPrivacy_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *eveningDetectiveServerClient) GetConsent(ctx context.Context, in *GetConsentReq, opts ...grpc.CallOption) (*GetConsentRsp, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetConsentRsp) + err := c.cc.Invoke(ctx, EveningDetectiveServer_GetConsent_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *eveningDetectiveServerClient) GetUsers(ctx context.Context, in *GetUsersReq, opts ...grpc.CallOption) (*GetUsersRsp, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GetUsersRsp) @@ -562,6 +610,10 @@ type EveningDetectiveServerServer interface { RefreshPassword(context.Context, *RefreshPasswordReq) (*RefreshPasswordRsp, error) Login(context.Context, *LoginReq) (*LoginRsp, error) Refresh(context.Context, *RefreshReq) (*RefreshRsp, error) + DeleteAccount(context.Context, *DeleteAccountReq) (*DeleteAccountRsp, error) + GetTerms(context.Context, *GetTermsReq) (*GetTermsRsp, error) + GetPrivacy(context.Context, *GetPrivacyReq) (*GetPrivacyRsp, error) + GetConsent(context.Context, *GetConsentReq) (*GetConsentRsp, error) GetUsers(context.Context, *GetUsersReq) (*GetUsersRsp, error) GetUserById(context.Context, *GetUserByIdReq) (*GetUserByIdRsp, error) GetMe(context.Context, *GetMeReq) (*GetMeRsp, error) @@ -627,6 +679,18 @@ func (UnimplementedEveningDetectiveServerServer) Login(context.Context, *LoginRe func (UnimplementedEveningDetectiveServerServer) Refresh(context.Context, *RefreshReq) (*RefreshRsp, error) { return nil, status.Error(codes.Unimplemented, "method Refresh not implemented") } +func (UnimplementedEveningDetectiveServerServer) DeleteAccount(context.Context, *DeleteAccountReq) (*DeleteAccountRsp, error) { + return nil, status.Error(codes.Unimplemented, "method DeleteAccount not implemented") +} +func (UnimplementedEveningDetectiveServerServer) GetTerms(context.Context, *GetTermsReq) (*GetTermsRsp, error) { + return nil, status.Error(codes.Unimplemented, "method GetTerms not implemented") +} +func (UnimplementedEveningDetectiveServerServer) GetPrivacy(context.Context, *GetPrivacyReq) (*GetPrivacyRsp, error) { + return nil, status.Error(codes.Unimplemented, "method GetPrivacy not implemented") +} +func (UnimplementedEveningDetectiveServerServer) GetConsent(context.Context, *GetConsentReq) (*GetConsentRsp, error) { + return nil, status.Error(codes.Unimplemented, "method GetConsent not implemented") +} func (UnimplementedEveningDetectiveServerServer) GetUsers(context.Context, *GetUsersReq) (*GetUsersRsp, error) { return nil, status.Error(codes.Unimplemented, "method GetUsers not implemented") } @@ -868,6 +932,78 @@ func _EveningDetectiveServer_Refresh_Handler(srv interface{}, ctx context.Contex return interceptor(ctx, in, info, handler) } +func _EveningDetectiveServer_DeleteAccount_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteAccountReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EveningDetectiveServerServer).DeleteAccount(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EveningDetectiveServer_DeleteAccount_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EveningDetectiveServerServer).DeleteAccount(ctx, req.(*DeleteAccountReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _EveningDetectiveServer_GetTerms_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetTermsReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EveningDetectiveServerServer).GetTerms(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EveningDetectiveServer_GetTerms_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EveningDetectiveServerServer).GetTerms(ctx, req.(*GetTermsReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _EveningDetectiveServer_GetPrivacy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetPrivacyReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EveningDetectiveServerServer).GetPrivacy(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EveningDetectiveServer_GetPrivacy_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EveningDetectiveServerServer).GetPrivacy(ctx, req.(*GetPrivacyReq)) + } + return interceptor(ctx, in, info, handler) +} + +func _EveningDetectiveServer_GetConsent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetConsentReq) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(EveningDetectiveServerServer).GetConsent(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: EveningDetectiveServer_GetConsent_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(EveningDetectiveServerServer).GetConsent(ctx, req.(*GetConsentReq)) + } + return interceptor(ctx, in, info, handler) +} + func _EveningDetectiveServer_GetUsers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetUsersReq) if err := dec(in); err != nil { @@ -1565,6 +1701,22 @@ var EveningDetectiveServer_ServiceDesc = grpc.ServiceDesc{ MethodName: "Refresh", Handler: _EveningDetectiveServer_Refresh_Handler, }, + { + MethodName: "DeleteAccount", + Handler: _EveningDetectiveServer_DeleteAccount_Handler, + }, + { + MethodName: "GetTerms", + Handler: _EveningDetectiveServer_GetTerms_Handler, + }, + { + MethodName: "GetPrivacy", + Handler: _EveningDetectiveServer_GetPrivacy_Handler, + }, + { + MethodName: "GetConsent", + Handler: _EveningDetectiveServer_GetConsent_Handler, + }, { MethodName: "GetUsers", Handler: _EveningDetectiveServer_GetUsers_Handler,