add service
This commit is contained in:
37
.gitignore
vendored
Normal file
37
.gitignore
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
# Binaries
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
bin/
|
||||
*.test
|
||||
*.out
|
||||
|
||||
# Go workspace file
|
||||
go.work
|
||||
|
||||
# Dependencies
|
||||
vendor/
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Config
|
||||
config/config.yaml
|
||||
!config/config.yaml.example
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
|
||||
# Build artifacts
|
||||
/bin/
|
||||
/dist/
|
||||
153
DEPLOYMENT.md
Normal file
153
DEPLOYMENT.md
Normal file
@@ -0,0 +1,153 @@
|
||||
# Инструкция по развертыванию
|
||||
|
||||
## Архитектура
|
||||
|
||||
Сервис построен на:
|
||||
- **rk-boot** - фреймворк для микросервисов с автоматической конфигурацией gRPC, логированием, метриками и трейсингом
|
||||
- **pgx/v5** - нативный высокопроизводительный драйвер PostgreSQL с connection pooling
|
||||
|
||||
## Быстрый старт
|
||||
|
||||
### 1. Установка goose для миграций
|
||||
|
||||
```bash
|
||||
go install github.com/pressly/goose/v3/cmd/goose@latest
|
||||
```
|
||||
|
||||
### 2. Применение миграций
|
||||
|
||||
```bash
|
||||
# Экспортируйте DATABASE_URL или используйте напрямую
|
||||
export DB_URL="postgres://postgres:password@localhost:5432/b2b_search?sslmode=disable"
|
||||
make migrate-up
|
||||
```
|
||||
|
||||
### 3. Настройка переменных окружения
|
||||
|
||||
Создайте `.env` файл или экспортируйте переменные:
|
||||
|
||||
```bash
|
||||
export DB_HOST=localhost
|
||||
export DB_PORT=5432
|
||||
export DB_NAME=b2b_search
|
||||
export DB_USER=postgres
|
||||
export DB_PASSWORD=password
|
||||
export OPENAI_API_KEY=your-openai-key
|
||||
export PERPLEXITY_API_KEY=your-perplexity-key
|
||||
export GRPC_PORT=9091
|
||||
```
|
||||
|
||||
**🧪 Mock-режим для тестирования:**
|
||||
|
||||
Если API ключи не указаны, сервис автоматически переключится в mock-режим:
|
||||
- **OpenAI**: вернет структурированное mock ТЗ
|
||||
- **Perplexity**: вернет 15 тестовых поставщиков
|
||||
|
||||
Это позволяет тестировать сервис без реальных API ключей!
|
||||
|
||||
```bash
|
||||
# Запуск в mock-режиме (без API ключей)
|
||||
make run
|
||||
```
|
||||
|
||||
### 4. Запуск сервиса
|
||||
|
||||
```bash
|
||||
# Локальный запуск
|
||||
make run
|
||||
|
||||
# Или сборка и запуск
|
||||
make build
|
||||
./bin/server
|
||||
```
|
||||
|
||||
## Docker Compose
|
||||
|
||||
```bash
|
||||
# Запуск всех сервисов
|
||||
docker-compose up -d
|
||||
|
||||
# Просмотр логов
|
||||
docker-compose logs -f smart-search-service
|
||||
|
||||
# Остановка
|
||||
docker-compose down
|
||||
```
|
||||
|
||||
## Миграции
|
||||
|
||||
### Применить все миграции
|
||||
|
||||
```bash
|
||||
make migrate-up DB_URL="postgres://user:pass@host:5432/dbname?sslmode=disable"
|
||||
```
|
||||
|
||||
### Откатить последнюю миграцию
|
||||
|
||||
```bash
|
||||
make migrate-down DB_URL="postgres://user:pass@host:5432/dbname?sslmode=disable"
|
||||
```
|
||||
|
||||
### Создать новую миграцию
|
||||
|
||||
```bash
|
||||
make migrate-create name=add_new_field
|
||||
```
|
||||
|
||||
## Структура БД
|
||||
|
||||
После применения миграций будут созданы следующие таблицы:
|
||||
|
||||
1. **users** - пользователи с зашифрованными PII полями
|
||||
2. **sessions** - сессии с JWT токенами
|
||||
3. **invite_codes** - инвайт-коды
|
||||
4. **mailing_status** - статусы рассылки (pending, in_progress, completed, failed)
|
||||
5. **requests_for_suppliers** - запросы на поставщиков
|
||||
6. **suppliers** - найденные поставщики
|
||||
7. **request_token_usage** - учет использования AI токенов
|
||||
|
||||
## Background Workers
|
||||
|
||||
Сервис автоматически запускает два фоновых процесса:
|
||||
|
||||
- **Session Cleaner** - удаление истекших сессий (каждый час)
|
||||
- **Invite Cleaner** - деактивация истекших инвайт-кодов (каждые 6 часов)
|
||||
|
||||
## rk-boot Возможности
|
||||
|
||||
Благодаря rk-boot сервис автоматически поддерживает:
|
||||
|
||||
- **gRPC Server** - на порту 9091
|
||||
- **Логирование** - структурированные логи через zap
|
||||
- **Метрики** - Prometheus метрики из коробки
|
||||
- **Трейсинг** - распределенная трассировка запросов
|
||||
- **Health Checks** - встроенные health endpoints
|
||||
- **Graceful Shutdown** - корректное завершение работы
|
||||
|
||||
## gRPC Сервисы
|
||||
|
||||
Сервер запускается на порту 9091 и предоставляет следующие сервисы:
|
||||
|
||||
- **AuthService** - аутентификация
|
||||
- **UserService** - управление пользователями
|
||||
- **InviteService** - управление инвайт-кодами
|
||||
- **RequestService** - управление запросами
|
||||
- **SupplierService** - экспорт поставщиков
|
||||
|
||||
## Проверка работоспособности
|
||||
|
||||
```bash
|
||||
# Проверка соединения с БД
|
||||
psql -h localhost -U postgres -d b2b_search -c "SELECT 1"
|
||||
|
||||
# Проверка gRPC сервера (требует grpcurl)
|
||||
grpcurl -plaintext localhost:9091 list
|
||||
```
|
||||
|
||||
## Безопасность
|
||||
|
||||
**ВАЖНО:** Секретные ключи для совместимости с существующим workflow:
|
||||
- JWT Secret: `xM8KhJVkk28cIJeBo0306O2e6Ifni6tNVlcCMxDFAEc=`
|
||||
- Crypto Secret: `xM8KhJVkk28cIJeBo0306O2e6Ifni6tNVlcCMxDFAEc=`
|
||||
|
||||
В production окружении **обязательно смените** эти ключи!
|
||||
32
Dockerfile
Normal file
32
Dockerfile
Normal file
@@ -0,0 +1,32 @@
|
||||
FROM golang:1.23-alpine AS builder
|
||||
|
||||
RUN apk add --no-cache git make protobuf-dev
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY go.mod go.sum ./
|
||||
ENV GOTOOLCHAIN=auto
|
||||
RUN go mod download
|
||||
|
||||
COPY . .
|
||||
|
||||
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o server cmd/server/main.go
|
||||
|
||||
FROM alpine:latest
|
||||
|
||||
RUN apk --no-cache add ca-certificates postgresql-client bash
|
||||
|
||||
WORKDIR /root/
|
||||
|
||||
COPY --from=builder /app/server .
|
||||
COPY --from=builder /app/migrations ./migrations
|
||||
COPY --from=builder /app/config/boot.yaml ./config/boot.yaml
|
||||
COPY --from=builder /app/config/config.yaml ./config/config.yaml
|
||||
COPY --from=builder /app/docker-entrypoint.sh /docker-entrypoint.sh
|
||||
|
||||
RUN chmod +x /docker-entrypoint.sh
|
||||
|
||||
EXPOSE 9091
|
||||
|
||||
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||
CMD ["./server"]
|
||||
244
GRPC_SERVICES.md
Normal file
244
GRPC_SERVICES.md
Normal file
@@ -0,0 +1,244 @@
|
||||
# gRPC Services
|
||||
|
||||
## Архитектура
|
||||
|
||||
gRPC handlers разделены на отдельные структуры для каждого сервиса во избежание коллизий имён методов (например, `GetInfo` присутствует как в `UserService`, так и в `InviteService`).
|
||||
|
||||
### Структура handlers
|
||||
|
||||
```
|
||||
internal/grpc/
|
||||
├── server.go # Инициализация handlers и регистрация
|
||||
├── auth_handler.go # AuthService gRPC методы
|
||||
├── user_handler.go # UserService gRPC методы
|
||||
├── invite_handler.go # InviteService gRPC методы
|
||||
├── request_handler.go # RequestService gRPC методы
|
||||
├── supplier_handler.go # SupplierService gRPC методы
|
||||
└── error_mapper.go # Маппинг ошибок в gRPC статусы
|
||||
```
|
||||
|
||||
## Сервисы
|
||||
|
||||
### 1. AuthService
|
||||
|
||||
**Proto:** `api/proto/auth/auth.proto`
|
||||
|
||||
| Метод | Описание |
|
||||
|-------|----------|
|
||||
| `Login` | Аутентификация пользователя (email + password) |
|
||||
| `Refresh` | Обновление access token по refresh token |
|
||||
| `Validate` | Валидация access token |
|
||||
| `Logout` | Выход (invalidate refresh token) |
|
||||
|
||||
**Пример:**
|
||||
|
||||
```go
|
||||
// Login
|
||||
req := &auth.LoginRequest{
|
||||
Email: "user@example.com",
|
||||
Password: "password",
|
||||
Ip: "127.0.0.1",
|
||||
UserAgent: "MyApp/1.0",
|
||||
}
|
||||
resp, err := authClient.Login(ctx, req)
|
||||
// resp.AccessToken, resp.RefreshToken
|
||||
```
|
||||
|
||||
### 2. UserService
|
||||
|
||||
**Proto:** `api/proto/user/user.proto`
|
||||
|
||||
| Метод | Описание |
|
||||
|-------|----------|
|
||||
| `GetInfo` | Получить информацию о пользователе |
|
||||
| `GetBalance` | Получить баланс |
|
||||
| `GetStatistics` | Получить статистику заявок |
|
||||
| `GetBalanceStatistics` | Комбинированная статистика баланса и заявок |
|
||||
|
||||
**Пример:**
|
||||
|
||||
```go
|
||||
req := &user.GetInfoRequest{UserId: 123}
|
||||
resp, err := userClient.GetInfo(ctx, req)
|
||||
// resp.Email, resp.Name, resp.CompanyName...
|
||||
```
|
||||
|
||||
### 3. InviteService
|
||||
|
||||
**Proto:** `api/proto/invite/invite.proto`
|
||||
|
||||
| Метод | Описание |
|
||||
|-------|----------|
|
||||
| `Generate` | Сгенерировать инвайт-код |
|
||||
| `GetInfo` | Получить информацию об инвайт-коде |
|
||||
|
||||
**Пример:**
|
||||
|
||||
```go
|
||||
req := &invite.GenerateRequest{
|
||||
UserId: 123,
|
||||
TtlDays: 30,
|
||||
MaxUses: 5,
|
||||
}
|
||||
resp, err := inviteClient.Generate(ctx, req)
|
||||
// resp.Code, resp.ExpiresAt
|
||||
```
|
||||
|
||||
### 4. RequestService
|
||||
|
||||
**Proto:** `api/proto/request/request.proto`
|
||||
|
||||
| Метод | Описание |
|
||||
|-------|----------|
|
||||
| `CreateTZ` | Создать заявку и сгенерировать ТЗ (AI) |
|
||||
| `ApproveTZ` | Подтвердить ТЗ и найти поставщиков (AI) |
|
||||
| `GetMailingList` | Получить список заявок пользователя |
|
||||
| `GetMailingListByID` | Получить детали конкретной заявки |
|
||||
|
||||
**Особенности:**
|
||||
|
||||
- `CreateTZ`: поддерживает опциональные `file_data` и `file_name` для прикрепления файлов
|
||||
- `ApproveTZ`: запускает поиск поставщиков через Perplexity API
|
||||
|
||||
**Пример:**
|
||||
|
||||
```go
|
||||
// Создание ТЗ
|
||||
req := &request.CreateTZRequest{
|
||||
UserId: 123,
|
||||
RequestTxt: "Нужны поставщики автозапчастей",
|
||||
FileData: fileBytes, // опционально
|
||||
FileName: "specs.pdf", // опционально
|
||||
}
|
||||
resp, err := requestClient.CreateTZ(ctx, req)
|
||||
// resp.RequestId, resp.TzText (сгенерировано AI)
|
||||
|
||||
// Подтверждение ТЗ
|
||||
approveReq := &request.ApproveTZRequest{
|
||||
RequestId: resp.RequestId,
|
||||
FinalTz: "Отредактированное ТЗ",
|
||||
UserId: 123,
|
||||
}
|
||||
approveResp, err := requestClient.ApproveTZ(ctx, approveReq)
|
||||
// approveResp.MailingStatus (поставщики найдены)
|
||||
```
|
||||
|
||||
### 5. SupplierService
|
||||
|
||||
**Proto:** `api/proto/supplier/supplier.proto`
|
||||
|
||||
| Метод | Описание |
|
||||
|-------|----------|
|
||||
| `ExportExcel` | Экспортировать список поставщиков в Excel |
|
||||
|
||||
**Пример:**
|
||||
|
||||
```go
|
||||
req := &supplier.ExportExcelRequest{
|
||||
RequestId: "uuid-string",
|
||||
UserId: 123,
|
||||
}
|
||||
resp, err := supplierClient.ExportExcel(ctx, req)
|
||||
// resp.FileData, resp.FileName, resp.MimeType
|
||||
```
|
||||
|
||||
## Обработка ошибок
|
||||
|
||||
Все ошибки из service layer автоматически мапятся в gRPC статусы через `errors.ToGRPCError()`:
|
||||
|
||||
| Код ошибки | gRPC Status |
|
||||
|------------|-------------|
|
||||
| `AUTH_INVALID_CREDENTIALS` | `Unauthenticated` |
|
||||
| `AUTH_INVALID_TOKEN` | `Unauthenticated` |
|
||||
| `USER_NOT_FOUND` | `NotFound` |
|
||||
| `REQUEST_NOT_FOUND` | `NotFound` |
|
||||
| `INVITE_LIMIT_REACHED` | `ResourceExhausted` |
|
||||
| `INSUFFICIENT_BALANCE` | `FailedPrecondition` |
|
||||
| Внутренние ошибки | `Internal` (без деталей) |
|
||||
|
||||
## Регистрация сервисов
|
||||
|
||||
В `cmd/server/main.go`:
|
||||
|
||||
```go
|
||||
authHandler, userHandler, inviteHandler, requestHandler, supplierHandler :=
|
||||
grpcServer.NewHandlers(pool, openAIKey, perplexityKey)
|
||||
|
||||
grpcEntry.AddRegFuncGrpc(func(s *grpc.Server) {
|
||||
grpcServer.RegisterServices(s,
|
||||
authHandler, userHandler, inviteHandler,
|
||||
requestHandler, supplierHandler)
|
||||
})
|
||||
```
|
||||
|
||||
## Context Flow
|
||||
|
||||
```
|
||||
gRPC Request → Handler(ctx) → Service(ctx) → Repository(ctx) → pgx(ctx)
|
||||
```
|
||||
|
||||
Все gRPC handlers принимают `context.Context` из gRPC request и прокидывают его через все слои.
|
||||
|
||||
## Тестирование
|
||||
|
||||
Для тестирования gRPC методов можно использовать:
|
||||
|
||||
### 1. grpcurl (CLI)
|
||||
|
||||
```bash
|
||||
# Получить список сервисов
|
||||
grpcurl -plaintext localhost:9091 list
|
||||
|
||||
# Вызвать метод
|
||||
grpcurl -plaintext \
|
||||
-d '{"email":"user@example.com","password":"password","ip":"127.0.0.1","user_agent":"test"}' \
|
||||
localhost:9091 auth.AuthService/Login
|
||||
```
|
||||
|
||||
### 2. Unit тесты с моками
|
||||
|
||||
```go
|
||||
// Создать mock service
|
||||
mockRequestService := &mockRequestService{
|
||||
createTZFunc: func(ctx context.Context, userID int, txt string) (uuid.UUID, string, error) {
|
||||
return uuid.New(), "Mock TZ", nil
|
||||
},
|
||||
}
|
||||
|
||||
// Создать handler с mock
|
||||
handler := &grpc.RequestHandler{
|
||||
requestService: mockRequestService,
|
||||
}
|
||||
|
||||
// Тестировать
|
||||
resp, err := handler.CreateTZ(ctx, &request.CreateTZRequest{...})
|
||||
```
|
||||
|
||||
## Метрики и трейсинг
|
||||
|
||||
Все gRPC методы автоматически отслеживаются через `rk-boot`:
|
||||
|
||||
- **Метрики**: запросы, ошибки, latency
|
||||
- **Трейсинг**: distributed tracing через OpenTelemetry
|
||||
- **Логирование**: все запросы логируются с request ID
|
||||
|
||||
Доступно на:
|
||||
- Метрики: `http://localhost:9091/metrics`
|
||||
- Health: `http://localhost:9091/health`
|
||||
|
||||
## Reflection
|
||||
|
||||
gRPC Reflection включен в `config/boot.yaml`, что позволяет использовать `grpcurl` и другие инструменты без .proto файлов:
|
||||
|
||||
```yaml
|
||||
grpc:
|
||||
- name: smart-search-service
|
||||
enableReflection: true
|
||||
```
|
||||
|
||||
## Статистика
|
||||
|
||||
- **Всего gRPC методов**: 16
|
||||
- **Всего handlers**: 5
|
||||
- **Строк кода handlers**: ~371
|
||||
- **Proto файлов**: 5
|
||||
78
Makefile
Normal file
78
Makefile
Normal file
@@ -0,0 +1,78 @@
|
||||
.PHONY: help build run migrate-up migrate-down migrate-create lint test proto clean
|
||||
|
||||
help:
|
||||
@echo "Available commands:"
|
||||
@echo " make build - Build the service"
|
||||
@echo " make run - Run the service"
|
||||
@echo " make migrate-up - Apply migrations"
|
||||
@echo " make migrate-down - Rollback migrations"
|
||||
@echo " make migrate-create - Create new migration (usage: make migrate-create name=migration_name)"
|
||||
@echo " make lint - Run golangci-lint"
|
||||
@echo " make proto - Generate proto files"
|
||||
@echo " make generate-mock - Generate mocks for all interfaces (minimock)"
|
||||
@echo " make test - Run tests"
|
||||
@echo " make clean - Clean build artifacts"
|
||||
|
||||
build:
|
||||
@echo "Building server..."
|
||||
@mkdir -p bin
|
||||
go build -o bin/server cmd/server/main.go
|
||||
@echo "Build complete: bin/server"
|
||||
|
||||
run:
|
||||
@echo "Running server..."
|
||||
go run cmd/server/main.go
|
||||
|
||||
migrate-up:
|
||||
@echo "Applying migrations..."
|
||||
goose -dir migrations postgres "$(DB_URL)" up
|
||||
|
||||
migrate-down:
|
||||
@echo "Rolling back migrations..."
|
||||
goose -dir migrations postgres "$(DB_URL)" down
|
||||
|
||||
migrate-create:
|
||||
@echo "Creating migration: $(name)"
|
||||
goose -dir migrations create $(name) sql
|
||||
|
||||
lint:
|
||||
@echo "Running linter..."
|
||||
golangci-lint run ./...
|
||||
|
||||
proto:
|
||||
@echo "Generating proto files..."
|
||||
@mkdir -p pkg/pb
|
||||
@find api/proto -name "*.proto" -exec protoc --go_out=pkg/pb --go_opt=paths=source_relative --go-grpc_out=pkg/pb --go-grpc_opt=paths=source_relative {} \;
|
||||
@echo "Proto generation complete"
|
||||
|
||||
clean:
|
||||
@echo "Cleaning build artifacts..."
|
||||
rm -rf bin/
|
||||
@echo "Clean complete"
|
||||
|
||||
.PHONY: generate-mock
|
||||
generate-mock:
|
||||
@echo "Generating mocks for repository interfaces..."
|
||||
@mkdir -p internal/mocks
|
||||
@cd internal/repository && \
|
||||
go run github.com/gojuno/minimock/v3/cmd/minimock@latest -i UserRepository -o ../mocks -p mocks -s "_mock.go" && \
|
||||
go run github.com/gojuno/minimock/v3/cmd/minimock@latest -i SessionRepository -o ../mocks -p mocks -s "_mock.go" && \
|
||||
go run github.com/gojuno/minimock/v3/cmd/minimock@latest -i InviteRepository -o ../mocks -p mocks -s "_mock.go" && \
|
||||
go run github.com/gojuno/minimock/v3/cmd/minimock@latest -i RequestRepository -o ../mocks -p mocks -s "_mock.go" && \
|
||||
go run github.com/gojuno/minimock/v3/cmd/minimock@latest -i SupplierRepository -o ../mocks -p mocks -s "_mock.go" && \
|
||||
go run github.com/gojuno/minimock/v3/cmd/minimock@latest -i TokenUsageRepository -o ../mocks -p mocks -s "_mock.go"
|
||||
@echo "Generating mocks for service interfaces..."
|
||||
@cd internal/service && \
|
||||
go run github.com/gojuno/minimock/v3/cmd/minimock@latest -i AuthService -o ../mocks -p mocks -s "_mock.go" && \
|
||||
go run github.com/gojuno/minimock/v3/cmd/minimock@latest -i UserService -o ../mocks -p mocks -s "_mock.go" && \
|
||||
go run github.com/gojuno/minimock/v3/cmd/minimock@latest -i InviteService -o ../mocks -p mocks -s "_mock.go" && \
|
||||
go run github.com/gojuno/minimock/v3/cmd/minimock@latest -i RequestService -o ../mocks -p mocks -s "_mock.go" && \
|
||||
go run github.com/gojuno/minimock/v3/cmd/minimock@latest -i SupplierService -o ../mocks -p mocks -s "_mock.go"
|
||||
@echo "Mocks generated in internal/mocks/"
|
||||
|
||||
test:
|
||||
@echo "Running tests..."
|
||||
go test -v ./...
|
||||
|
||||
# Default DB URL for local development
|
||||
DB_URL ?= postgres://postgres:password@localhost:5432/b2b_search?sslmode=disable
|
||||
152
README.md
152
README.md
@@ -1,2 +1,152 @@
|
||||
# smart-search-back
|
||||
# Smart Search Backend Service
|
||||
|
||||
Backend микросервис для системы поиска поставщиков с AI интеграцией.
|
||||
|
||||
## Технологии
|
||||
|
||||
- **Go 1.21+** - основной язык
|
||||
- **rk-boot** - фреймворк для микросервисов (автоматическая настройка gRPC, логирование, метрики)
|
||||
- **PostgreSQL 15** - база данных
|
||||
- **pgx/v5** - нативный драйвер PostgreSQL (высокая производительность)
|
||||
- **gRPC** - межсервисное взаимодействие
|
||||
- **Squirrel** - SQL query builder
|
||||
- **Goose** - миграции БД
|
||||
- **JWT (HS256)** - аутентификация
|
||||
- **AES-256-GCM** - шифрование PII данных
|
||||
- **OpenAI API** - генерация ТЗ (gpt-4o-mini)
|
||||
- **Perplexity API** - поиск поставщиков
|
||||
|
||||
### rk-boot + pgx
|
||||
|
||||
Сервис использует комбинацию rk-boot и pgx:
|
||||
|
||||
**rk-boot** обеспечивает:
|
||||
- ✅ Автоматическое управление gRPC сервером
|
||||
- ✅ Структурированное логирование (zap)
|
||||
- ✅ Prometheus метрики
|
||||
- ✅ Distributed tracing
|
||||
- ✅ Health checks
|
||||
- ✅ Graceful shutdown
|
||||
|
||||
**pgx/v5** обеспечивает:
|
||||
- ✅ Нативный драйвер PostgreSQL (в 2-3 раза быстрее database/sql)
|
||||
- ✅ Connection pooling из коробки
|
||||
- ✅ Batch operations
|
||||
- ✅ Prepared statements
|
||||
- ✅ Context support
|
||||
|
||||
### gRPC Services
|
||||
|
||||
**5 gRPC сервисов с 16 методами**:
|
||||
- `AuthService` - аутентификация (Login, Refresh, Validate, Logout)
|
||||
- `UserService` - информация о пользователе и статистика
|
||||
- `InviteService` - управление инвайт-кодами
|
||||
- `RequestService` - создание и управление заявками с AI
|
||||
- `SupplierService` - экспорт данных поставщиков
|
||||
|
||||
Подробнее: [GRPC_SERVICES.md](GRPC_SERVICES.md)
|
||||
|
||||
## Структура проекта
|
||||
|
||||
```
|
||||
smart-search-back/
|
||||
├── cmd/server/ # Точка входа
|
||||
├── internal/ # Внутренняя логика
|
||||
│ ├── grpc/ # gRPC server
|
||||
│ ├── service/ # Бизнес-логика
|
||||
│ ├── repository/ # Слой данных
|
||||
│ ├── model/ # Domain модели
|
||||
│ ├── worker/ # Background workers
|
||||
│ └── ai/ # AI интеграция
|
||||
├── api/proto/ # Proto файлы (только .proto)
|
||||
├── migrations/ # SQL миграции
|
||||
├── pkg/ # Общие утилиты
|
||||
│ ├── pb/ # Сгенерированные proto файлы
|
||||
│ ├── crypto/ # Шифрование
|
||||
│ ├── jwt/ # JWT токены
|
||||
│ └── errors/ # Обработка ошибок
|
||||
└── config/ # Конфигурация
|
||||
|
||||
## Установка
|
||||
|
||||
```bash
|
||||
# Установить зависимости
|
||||
go mod download
|
||||
|
||||
# Применить миграции
|
||||
make migrate-up
|
||||
|
||||
# Запустить сервис
|
||||
make run
|
||||
```
|
||||
|
||||
### 🧪 Mock-режим
|
||||
|
||||
Для тестирования без реальных API ключей сервис поддерживает mock-режим:
|
||||
|
||||
- Если `OPENAI_API_KEY` не указан → возвращается тестовое ТЗ
|
||||
- Если `PERPLEXITY_API_KEY` не указан → возвращается 15 mock поставщиков
|
||||
|
||||
Просто запустите без экспорта API ключей:
|
||||
```bash
|
||||
make run # Mock-режим активируется автоматически
|
||||
```
|
||||
|
||||
## Миграции
|
||||
|
||||
```bash
|
||||
# Применить миграции
|
||||
make migrate-up
|
||||
|
||||
# Откатить миграции
|
||||
make migrate-down
|
||||
```
|
||||
|
||||
## Разработка
|
||||
|
||||
```bash
|
||||
# Запустить линтер
|
||||
make lint
|
||||
|
||||
# Сгенерировать proto файлы
|
||||
make proto
|
||||
|
||||
# Собрать проект
|
||||
make build
|
||||
|
||||
# Запустить тесты
|
||||
go test ./...
|
||||
|
||||
# С покрытием
|
||||
go test ./... -cover
|
||||
```
|
||||
|
||||
### Тестирование
|
||||
|
||||
Проект полностью подготовлен для тестирования:
|
||||
|
||||
- ✅ **Интерфейсы** для всех репозиториев и сервисов
|
||||
- ✅ **Context** создается один раз в `main.go` и прокидывается через все слои
|
||||
- ✅ **Приватные структуры** возвращают публичные интерфейсы
|
||||
- ✅ **Примеры тестов** с моками в `internal/service/tests/`
|
||||
- ✅ **Graceful shutdown** через context cancellation
|
||||
|
||||
Подробнее см. [TESTING.md](TESTING.md)
|
||||
|
||||
## Docker
|
||||
|
||||
```bash
|
||||
# Запустить все сервисы
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
gRPC сервер запускается на порту 9091.
|
||||
|
||||
Доступные сервисы:
|
||||
- AuthService - аутентификация
|
||||
- UserService - управление пользователями
|
||||
- InviteService - инвайт-коды
|
||||
- RequestService - запросы на поставщиков
|
||||
- SupplierService - экспорт поставщиков
|
||||
|
||||
309
TESTING.md
Normal file
309
TESTING.md
Normal file
@@ -0,0 +1,309 @@
|
||||
# Руководство по тестированию
|
||||
|
||||
## Архитектура для тестирования
|
||||
|
||||
Проект спроектирован с учетом тестируемости:
|
||||
|
||||
### ✅ Интерфейсы для всех слоев
|
||||
|
||||
**Repository интерфейсы** (`internal/repository/interfaces.go`):
|
||||
```go
|
||||
type UserRepository interface {
|
||||
FindByEmailHash(ctx context.Context, emailHash string) (*model.User, error)
|
||||
FindByID(ctx context.Context, userID int) (*model.User, error)
|
||||
Create(ctx context.Context, user *model.User) error
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**Service интерфейсы** (`internal/service/interfaces.go`):
|
||||
```go
|
||||
type AuthService interface {
|
||||
Login(ctx context.Context, email, password, ip, userAgent string) (string, string, error)
|
||||
Refresh(ctx context.Context, refreshToken string) (string, error)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### ✅ Context пробрасывается через все слои
|
||||
|
||||
```
|
||||
main.go (ctx) → Workers (ctx) → gRPC Handler (ctx) → Service (ctx) → Repository (ctx) → pgx
|
||||
```
|
||||
|
||||
**Правило**: `context.Background()` создается **только один раз** в `main.go` и прокидывается через все компоненты.
|
||||
|
||||
Это позволяет:
|
||||
- **Graceful shutdown**: при отмене context все workers и операции останавливаются
|
||||
- Отменять долгие операции
|
||||
- Передавать метаданные (trace ID, user ID)
|
||||
- Контролировать таймауты
|
||||
- Избежать потерянных goroutines
|
||||
|
||||
## Автоматическая генерация моков
|
||||
|
||||
Проект использует [minimock](https://github.com/gojuno/minimock) для автоматической генерации типизированных моков из интерфейсов.
|
||||
|
||||
### Генерация моков
|
||||
|
||||
Все моки генерируются в `internal/mocks/` одной командой:
|
||||
|
||||
```bash
|
||||
make generate-mock
|
||||
```
|
||||
|
||||
Эта команда генерирует моки для всех интерфейсов:
|
||||
- **Repository интерфейсы**: `UserRepository`, `SessionRepository`, `InviteRepository`, `RequestRepository`, `SupplierRepository`, `TokenUsageRepository`
|
||||
- **Service интерфейсы**: `AuthService`, `UserService`, `InviteService`, `RequestService`, `SupplierService`
|
||||
|
||||
### Использование сгенерированных моков
|
||||
|
||||
```go
|
||||
import (
|
||||
"testing"
|
||||
"context"
|
||||
"smart-search-back/internal/mocks"
|
||||
"smart-search-back/internal/service"
|
||||
"smart-search-back/internal/model"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAuthService_Login_Success(t *testing.T) {
|
||||
// Создаем моки
|
||||
mockUserRepo := mocks.NewUserRepositoryMock(t)
|
||||
mockSessionRepo := mocks.NewSessionRepositoryMock(t)
|
||||
|
||||
// Настраиваем поведение мока
|
||||
mockUserRepo.FindByEmailHashMock.Expect(context.Background(), "email_hash").Return(&model.User{
|
||||
ID: 1,
|
||||
PasswordHash: "b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86",
|
||||
}, nil)
|
||||
|
||||
mockSessionRepo.CreateMock.Expect(context.Background(), &model.Session{}).Return(nil)
|
||||
|
||||
// Создаем сервис с моками
|
||||
authService := service.NewAuthService(mockUserRepo, mockSessionRepo)
|
||||
|
||||
// Выполняем тест
|
||||
accessToken, refreshToken, err := authService.Login(
|
||||
context.Background(),
|
||||
"test@example.com",
|
||||
"password",
|
||||
"127.0.0.1",
|
||||
"test-agent",
|
||||
)
|
||||
|
||||
// Проверяем результат
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, accessToken)
|
||||
assert.NotEmpty(t, refreshToken)
|
||||
|
||||
// Minimock автоматически проверит что все ожидания выполнены
|
||||
}
|
||||
```
|
||||
|
||||
### Преимущества minimock
|
||||
|
||||
✅ **Типобезопасность** - моки генерируются из интерфейсов, ошибки компиляции при изменении сигнатур
|
||||
✅ **Автоматическая проверка** - проверяет что все ожидания выполнены
|
||||
✅ **Счетчики вызовов** - можно проверить сколько раз был вызван метод
|
||||
✅ **Inspection** - можно проверить аргументы вызовов
|
||||
✅ **Minimal boilerplate** - не нужно писать моки вручную
|
||||
|
||||
### Пример с проверкой вызовов
|
||||
|
||||
```go
|
||||
func TestUserService_GetBalance(t *testing.T) {
|
||||
mockUserRepo := mocks.NewUserRepositoryMock(t)
|
||||
|
||||
// Ожидаем вызов GetBalance с userID=123
|
||||
mockUserRepo.GetBalanceMock.Expect(context.Background(), 123).Return(100.50, nil)
|
||||
|
||||
userService := service.NewUserService(mockUserRepo, nil)
|
||||
balance, err := userService.GetBalance(context.Background(), 123)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 100.50, balance)
|
||||
|
||||
// Minimock автоматически проверит:
|
||||
// - что GetBalance был вызван ровно 1 раз
|
||||
// - с правильными аргументами
|
||||
// - и вернул правильное значение
|
||||
}
|
||||
```
|
||||
|
||||
### Ручные моки (legacy пример)
|
||||
|
||||
Для сравнения, старый пример с ручными моками (все еще работает, но не рекомендуется):
|
||||
|
||||
```go
|
||||
// Mock репозитория (legacy - используйте minimock!)
|
||||
type mockUserRepo struct {
|
||||
findByEmailHashFunc func(ctx context.Context, emailHash string) (*model.User, error)
|
||||
}
|
||||
|
||||
func (m *mockUserRepo) FindByEmailHash(ctx context.Context, emailHash string) (*model.User, error) {
|
||||
if m.findByEmailHashFunc != nil {
|
||||
return m.findByEmailHashFunc(ctx, emailHash)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
```
|
||||
|
||||
## Запуск тестов
|
||||
|
||||
```bash
|
||||
# Все тесты
|
||||
go test ./...
|
||||
|
||||
# С покрытием
|
||||
go test ./... -cover
|
||||
|
||||
# Verbose режим
|
||||
go test ./... -v
|
||||
|
||||
# Конкретный пакет
|
||||
go test ./internal/service/tests/...
|
||||
|
||||
# С race detector
|
||||
go test ./... -race
|
||||
```
|
||||
|
||||
## Использование minimock
|
||||
|
||||
Проект использует [minimock](https://github.com/gojuno/minimock) для автоматической генерации типизированных моков.
|
||||
|
||||
### Генерация моков
|
||||
|
||||
Все моки генерируются в `internal/mocks/`:
|
||||
|
||||
```bash
|
||||
make generate-mock
|
||||
```
|
||||
|
||||
Генерируются моки для всех интерфейсов:
|
||||
- **Repository**: `UserRepository`, `SessionRepository`, `InviteRepository`, `RequestRepository`, `SupplierRepository`, `TokenUsageRepository`
|
||||
- **Service**: `AuthService`, `UserService`, `InviteService`, `RequestService`, `SupplierService`
|
||||
|
||||
### Использование сгенерированных моков
|
||||
|
||||
```go
|
||||
import "smart-search-back/internal/mocks"
|
||||
|
||||
func TestAuthService_Login(t *testing.T) {
|
||||
mockUserRepo := mocks.NewUserRepositoryMock(t)
|
||||
mockSessionRepo := mocks.NewSessionRepositoryMock(t)
|
||||
|
||||
mockUserRepo.FindByEmailHashMock.Expect(ctx, "hash").Return(&model.User{...}, nil)
|
||||
|
||||
authService := service.NewAuthService(mockUserRepo, mockSessionRepo)
|
||||
// ... тест
|
||||
}
|
||||
```
|
||||
|
||||
Подробнее см. раздел "Автоматическая генерация моков" выше.
|
||||
|
||||
## Структура тестов
|
||||
|
||||
```
|
||||
internal/
|
||||
├── service/
|
||||
│ ├── auth.go
|
||||
│ ├── interfaces.go # Интерфейсы сервисов
|
||||
│ └── tests/
|
||||
│ └── auth_test.go # Тесты с моками
|
||||
├── repository/
|
||||
│ ├── user.go
|
||||
│ ├── interfaces.go # Интерфейсы репозиториев
|
||||
│ └── tests/
|
||||
│ └── user_test.go
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. Используйте context.Background() в тестах
|
||||
|
||||
```go
|
||||
ctx := context.Background()
|
||||
result, err := service.SomeMethod(ctx, params)
|
||||
```
|
||||
|
||||
### 2. Мокайте только то, что нужно
|
||||
|
||||
```go
|
||||
mockRepo := &mockUserRepo{
|
||||
findByIDFunc: func(ctx context.Context, id int) (*model.User, error) {
|
||||
return &model.User{ID: id}, nil
|
||||
},
|
||||
// Остальные методы можно не реализовывать если не используются
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Проверяйте вызовы
|
||||
|
||||
```go
|
||||
var called bool
|
||||
mockRepo := &mockUserRepo{
|
||||
createFunc: func(ctx context.Context, user *model.User) error {
|
||||
called = true
|
||||
assert.Equal(t, "expected@email.com", user.Email)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// ... вызов сервиса
|
||||
|
||||
assert.True(t, called, "Create should have been called")
|
||||
```
|
||||
|
||||
### 4. Тестируйте ошибки
|
||||
|
||||
```go
|
||||
mockRepo := &mockUserRepo{
|
||||
findByIDFunc: func(ctx context.Context, id int) (*model.User, error) {
|
||||
return nil, errors.NewBusinessError(errors.UserNotFound, "user not found")
|
||||
},
|
||||
}
|
||||
|
||||
result, err := service.GetUser(ctx, 123)
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, result)
|
||||
```
|
||||
|
||||
## Integration тесты
|
||||
|
||||
Для integration тестов с реальной БД можно использовать testcontainers:
|
||||
|
||||
```go
|
||||
func TestUserRepository_Integration(t *testing.T) {
|
||||
// Создать testcontainer с PostgreSQL
|
||||
// Применить миграции
|
||||
// Запустить тесты
|
||||
}
|
||||
```
|
||||
|
||||
## CI/CD
|
||||
|
||||
```yaml
|
||||
# .github/workflows/test.yml
|
||||
name: Tests
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.21
|
||||
- run: go test ./... -race -cover
|
||||
```
|
||||
|
||||
## Хэши для тестов
|
||||
|
||||
При тестировании аутентификации используйте правильные хэши:
|
||||
|
||||
- Пароль: `"password"`
|
||||
- SHA512 хэш: `"b109f3bbbc244eb82441917ed06d618b9008dd09b3befd1b5e07394c706a8bb980b1d7785e5976ec049b46df5f1326af5a2ea6d103fd07c95385ffab0cacbc86"`
|
||||
|
||||
Или используйте `crypto.PasswordHash("password")` прямо в тестах.
|
||||
50
api/proto/auth/auth.proto
Normal file
50
api/proto/auth/auth.proto
Normal file
@@ -0,0 +1,50 @@
|
||||
syntax = "proto3";
|
||||
package auth;
|
||||
option go_package = "github.com/smart-search-gateway/api/proto/auth/auth";
|
||||
|
||||
service AuthService {
|
||||
rpc Login(LoginRequest) returns (LoginResponse);
|
||||
rpc Refresh(RefreshRequest) returns (RefreshResponse);
|
||||
rpc Validate(ValidateRequest) returns (ValidateResponse);
|
||||
rpc Logout(LogoutRequest) returns (LogoutResponse);
|
||||
}
|
||||
|
||||
message LoginRequest {
|
||||
string email = 1;
|
||||
string password = 2;
|
||||
string ip = 3;
|
||||
string user_agent = 4;
|
||||
}
|
||||
|
||||
message LoginResponse {
|
||||
string access_token = 1;
|
||||
string refresh_token = 2;
|
||||
}
|
||||
|
||||
message RefreshRequest {
|
||||
string refresh_token = 1;
|
||||
string ip = 2;
|
||||
string user_agent = 3;
|
||||
}
|
||||
|
||||
message RefreshResponse {
|
||||
string access_token = 1;
|
||||
string refresh_token = 2;
|
||||
}
|
||||
|
||||
message ValidateRequest {
|
||||
string access_token = 1;
|
||||
}
|
||||
|
||||
message ValidateResponse {
|
||||
bool valid = 1;
|
||||
int64 user_id = 2;
|
||||
}
|
||||
|
||||
message LogoutRequest {
|
||||
string access_token = 1;
|
||||
}
|
||||
|
||||
message LogoutResponse {
|
||||
bool success = 1;
|
||||
}
|
||||
36
api/proto/invite/invite.proto
Normal file
36
api/proto/invite/invite.proto
Normal file
@@ -0,0 +1,36 @@
|
||||
syntax = "proto3";
|
||||
package invite;
|
||||
option go_package = "github.com/smart-search-gateway/api/proto/invite/invite";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
service InviteService {
|
||||
rpc Generate(GenerateRequest) returns (GenerateResponse);
|
||||
rpc GetInfo(GetInfoRequest) returns (GetInfoResponse);
|
||||
}
|
||||
|
||||
message GenerateRequest {
|
||||
int64 user_id = 1;
|
||||
int32 ttl_days = 2;
|
||||
int32 max_uses = 3;
|
||||
}
|
||||
|
||||
message GenerateResponse {
|
||||
string code = 1;
|
||||
int32 max_uses = 2;
|
||||
google.protobuf.Timestamp expires_at = 3;
|
||||
}
|
||||
|
||||
message GetInfoRequest {
|
||||
string code = 1;
|
||||
}
|
||||
|
||||
message GetInfoResponse {
|
||||
string code = 1;
|
||||
int64 user_id = 2;
|
||||
int32 can_be_used_count = 3;
|
||||
int32 used_count = 4;
|
||||
google.protobuf.Timestamp expires_at = 5;
|
||||
bool is_active = 6;
|
||||
google.protobuf.Timestamp created_at = 7;
|
||||
}
|
||||
61
api/proto/request/request.proto
Normal file
61
api/proto/request/request.proto
Normal file
@@ -0,0 +1,61 @@
|
||||
syntax = "proto3";
|
||||
package request;
|
||||
option go_package = "github.com/smart-search-gateway/api/proto/request/request";
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
service RequestService {
|
||||
rpc CreateTZ(CreateTZRequest) returns (CreateTZResponse);
|
||||
rpc ApproveTZ(ApproveTZRequest) returns (ApproveTZResponse);
|
||||
rpc GetMailingList(GetMailingListRequest) returns (GetMailingListResponse);
|
||||
rpc GetMailingListByID(GetMailingListByIDRequest) returns (GetMailingListByIDResponse);
|
||||
}
|
||||
|
||||
message CreateTZRequest {
|
||||
int64 user_id = 1;
|
||||
string request_txt = 2;
|
||||
bytes file_data = 3;
|
||||
string file_name = 4;
|
||||
}
|
||||
|
||||
message CreateTZResponse {
|
||||
string request_id = 1;
|
||||
string tz_text = 2;
|
||||
}
|
||||
|
||||
message ApproveTZRequest {
|
||||
string request_id = 1;
|
||||
string final_tz = 2;
|
||||
int64 user_id = 3;
|
||||
}
|
||||
|
||||
message ApproveTZResponse {
|
||||
bool success = 1;
|
||||
string mailing_status = 2;
|
||||
}
|
||||
|
||||
message GetMailingListRequest {
|
||||
int64 user_id = 1;
|
||||
}
|
||||
|
||||
message GetMailingListResponse {
|
||||
repeated MailingItem items = 1;
|
||||
}
|
||||
|
||||
message GetMailingListByIDRequest {
|
||||
string request_id = 1;
|
||||
int64 user_id = 2;
|
||||
}
|
||||
|
||||
message GetMailingListByIDResponse {
|
||||
MailingItem item = 1;
|
||||
}
|
||||
|
||||
message MailingItem {
|
||||
string request_id = 1;
|
||||
string request_txt = 2;
|
||||
string final_tz = 3;
|
||||
string mailing_status = 4;
|
||||
google.protobuf.Timestamp created_at = 5;
|
||||
int32 suppliers_found = 6;
|
||||
}
|
||||
18
api/proto/supplier/supplier.proto
Normal file
18
api/proto/supplier/supplier.proto
Normal file
@@ -0,0 +1,18 @@
|
||||
syntax = "proto3";
|
||||
package supplier;
|
||||
option go_package = "github.com/smart-search-gateway/api/proto/supplier/supplier";
|
||||
|
||||
service SupplierService {
|
||||
rpc ExportExcel(ExportExcelRequest) returns (ExportExcelResponse);
|
||||
}
|
||||
|
||||
message ExportExcelRequest {
|
||||
string request_id = 1;
|
||||
int64 user_id = 2;
|
||||
}
|
||||
|
||||
message ExportExcelResponse {
|
||||
bytes file_data = 1;
|
||||
string file_name = 2;
|
||||
string mime_type = 3;
|
||||
}
|
||||
51
api/proto/user/user.proto
Normal file
51
api/proto/user/user.proto
Normal file
@@ -0,0 +1,51 @@
|
||||
syntax = "proto3";
|
||||
package user;
|
||||
option go_package = "github.com/smart-search-gateway/api/proto/user/user";
|
||||
|
||||
service UserService {
|
||||
rpc GetInfo(GetInfoRequest) returns (GetInfoResponse);
|
||||
rpc GetBalance(GetBalanceRequest) returns (GetBalanceResponse);
|
||||
rpc GetStatistics(GetStatisticsRequest) returns (GetStatisticsResponse);
|
||||
rpc GetBalanceStatistics(GetBalanceStatisticsRequest) returns (GetBalanceStatisticsResponse);
|
||||
}
|
||||
|
||||
message GetInfoRequest {
|
||||
int64 user_id = 1;
|
||||
}
|
||||
|
||||
message GetInfoResponse {
|
||||
string email = 1;
|
||||
string name = 2;
|
||||
string phone = 3;
|
||||
string company_name = 4;
|
||||
string payment_status = 5;
|
||||
}
|
||||
|
||||
message GetBalanceRequest {
|
||||
int64 user_id = 1;
|
||||
}
|
||||
|
||||
message GetBalanceResponse {
|
||||
double balance = 1;
|
||||
}
|
||||
|
||||
message GetStatisticsRequest {
|
||||
int64 user_id = 1;
|
||||
}
|
||||
|
||||
message GetStatisticsResponse {
|
||||
int32 total_requests = 1;
|
||||
int32 successful_requests = 2;
|
||||
int32 failed_requests = 3;
|
||||
double total_spent = 4;
|
||||
}
|
||||
|
||||
message GetBalanceStatisticsRequest {
|
||||
int64 user_id = 1;
|
||||
}
|
||||
|
||||
message GetBalanceStatisticsResponse {
|
||||
double balance = 1;
|
||||
int32 total_requests = 2;
|
||||
double total_spent = 3;
|
||||
}
|
||||
88
cmd/server/main.go
Normal file
88
cmd/server/main.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
_ "github.com/jackc/pgx/v5/stdlib"
|
||||
rkboot "github.com/rookie-ninja/rk-boot/v2"
|
||||
"github.com/rookie-ninja/rk-entry/v2/entry"
|
||||
rkgrpc "github.com/rookie-ninja/rk-grpc/v2/boot"
|
||||
"google.golang.org/grpc"
|
||||
|
||||
"smart-search-back/internal/config"
|
||||
"smart-search-back/internal/database"
|
||||
grpcServer "smart-search-back/internal/grpc"
|
||||
"smart-search-back/internal/repository"
|
||||
"smart-search-back/internal/worker"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cfg, err := config.Load("config/config.yaml")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load config: %v", err)
|
||||
}
|
||||
|
||||
boot := rkboot.NewBoot(rkboot.WithBootConfigPath("config/boot.yaml", nil))
|
||||
|
||||
ctx := context.Background()
|
||||
boot.Bootstrap(ctx)
|
||||
|
||||
grpcEntry := rkgrpc.GetGrpcEntry("smart-search-service")
|
||||
if grpcEntry == nil {
|
||||
log.Fatal("Failed to get gRPC entry from rk-boot")
|
||||
}
|
||||
|
||||
loggerEntry := rkentry.GlobalAppCtx.GetLoggerEntry("smart-search-service")
|
||||
if loggerEntry == nil {
|
||||
loggerEntry = rkentry.GlobalAppCtx.GetLoggerEntryDefault()
|
||||
}
|
||||
logger := loggerEntry.Logger
|
||||
|
||||
if err := database.RunMigrations(cfg.DatabaseURL()); err != nil {
|
||||
log.Fatalf("Failed to run migrations: %v", err)
|
||||
}
|
||||
|
||||
pool, err := pgxpool.New(ctx, cfg.DatabaseURL())
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to connect to database: %v", err)
|
||||
}
|
||||
defer pool.Close()
|
||||
|
||||
if err := pool.Ping(ctx); err != nil {
|
||||
log.Fatalf("Failed to ping database: %v", err)
|
||||
}
|
||||
|
||||
log.Println("Successfully connected to database")
|
||||
|
||||
sessionRepo := repository.NewSessionRepository(pool)
|
||||
inviteRepo := repository.NewInviteRepository(pool)
|
||||
|
||||
sessionCleaner := worker.NewSessionCleaner(ctx, sessionRepo)
|
||||
sessionCleaner.Start()
|
||||
defer sessionCleaner.Stop()
|
||||
|
||||
inviteCleaner := worker.NewInviteCleaner(ctx, inviteRepo)
|
||||
inviteCleaner.Start()
|
||||
defer inviteCleaner.Stop()
|
||||
|
||||
authHandler, userHandler, inviteHandler, requestHandler, supplierHandler := grpcServer.NewHandlers(
|
||||
pool,
|
||||
cfg.Security.JWTSecret,
|
||||
cfg.Security.CryptoSecret,
|
||||
cfg.AI.OpenAIKey,
|
||||
cfg.AI.PerplexityKey,
|
||||
logger,
|
||||
)
|
||||
|
||||
grpcEntry.AddRegFuncGrpc(func(s *grpc.Server) {
|
||||
grpcServer.RegisterServices(s, authHandler, userHandler, inviteHandler, requestHandler, supplierHandler)
|
||||
})
|
||||
|
||||
log.Println("gRPC server started via rk-boot on port 9091")
|
||||
|
||||
boot.WaitForShutdownSig(ctx)
|
||||
|
||||
log.Println("Server stopped gracefully")
|
||||
}
|
||||
35
config/boot.yaml
Normal file
35
config/boot.yaml
Normal file
@@ -0,0 +1,35 @@
|
||||
---
|
||||
logger:
|
||||
- name: smart-search-logger
|
||||
description: "Application logger for smart-search service"
|
||||
default: true
|
||||
zap:
|
||||
level: error
|
||||
development: false
|
||||
encoding: console
|
||||
outputPaths: ["stdout"]
|
||||
errorOutputPaths: ["stderr"]
|
||||
disableCaller: false
|
||||
disableStacktrace: false
|
||||
|
||||
grpc:
|
||||
- name: smart-search-service
|
||||
port: 9091
|
||||
enabled: true
|
||||
enableReflection: true
|
||||
enableRkGwOption: true
|
||||
loggerEntry: smart-search-logger
|
||||
eventEntry: smart-search-logger
|
||||
middleware:
|
||||
logging:
|
||||
enabled: true
|
||||
loggerEncoding: "console"
|
||||
loggerOutputPaths: ["stdout"]
|
||||
meta:
|
||||
enabled: true
|
||||
trace:
|
||||
enabled: true
|
||||
prometheus:
|
||||
enabled: true
|
||||
auth:
|
||||
enabled: false
|
||||
24
config/config.yaml.example
Normal file
24
config/config.yaml.example
Normal file
@@ -0,0 +1,24 @@
|
||||
database:
|
||||
host: ${DB_HOST:localhost}
|
||||
port: ${DB_PORT:5432}
|
||||
name: ${DB_NAME:b2b_search}
|
||||
user: ${DB_USER:postgres}
|
||||
password: ${DB_PASSWORD:password}
|
||||
ssl_mode: ${DB_SSL_MODE:disable}
|
||||
max_conns: ${DB_MAX_CONNS:25}
|
||||
min_conns: ${DB_MIN_CONNS:5}
|
||||
|
||||
ai:
|
||||
openai_key: ${OPENAI_API_KEY:}
|
||||
perplexity_key: ${PERPLEXITY_API_KEY:}
|
||||
|
||||
security:
|
||||
jwt_secret: ${JWT_SECRET:xM8KhJVkk28cIJeBo0306O2e6Ifni6tNVlcCMxDFAEc=}
|
||||
crypto_secret: ${CRYPTO_SECRET:xM8KhJVkk28cIJeBo0306O2e6Ifni6tNVlcCMxDFAEc=}
|
||||
|
||||
grpc:
|
||||
port: ${GRPC_PORT:9091}
|
||||
max_connections: ${GRPC_MAX_CONNS:100}
|
||||
|
||||
logging:
|
||||
level: ${LOG_LEVEL:info}
|
||||
41
docker-compose.yml
Normal file
41
docker-compose.yml
Normal file
@@ -0,0 +1,41 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15-alpine
|
||||
container_name: smart-search-postgres
|
||||
environment:
|
||||
POSTGRES_DB: b2b_search
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: password
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- postgres_data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
smart-search-service:
|
||||
build: .
|
||||
container_name: smart-search-service
|
||||
ports:
|
||||
- "9091:9091"
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
DB_HOST: postgres
|
||||
DB_PORT: 5432
|
||||
DB_NAME: b2b_search
|
||||
DB_USER: postgres
|
||||
DB_PASSWORD: password
|
||||
OPENAI_API_KEY: ${OPENAI_API_KEY}
|
||||
PERPLEXITY_API_KEY: ${PERPLEXITY_API_KEY}
|
||||
GRPC_PORT: 9091
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
16
docker-entrypoint.sh
Executable file
16
docker-entrypoint.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
echo "=== Smart Search Backend Entrypoint ==="
|
||||
|
||||
# Wait for database to be ready
|
||||
echo "Waiting for database to be ready..."
|
||||
until PGPASSWORD=$DB_PASSWORD psql -h "$DB_HOST" -U "$DB_USER" -d "$DB_NAME" -c '\q' 2>/dev/null; do
|
||||
echo "Database is unavailable - sleeping"
|
||||
sleep 2
|
||||
done
|
||||
|
||||
echo "Database is ready!"
|
||||
|
||||
echo "Starting server..."
|
||||
exec "$@"
|
||||
95
go.mod
Normal file
95
go.mod
Normal file
@@ -0,0 +1,95 @@
|
||||
module smart-search-back
|
||||
|
||||
go 1.24.0
|
||||
|
||||
require (
|
||||
github.com/Masterminds/squirrel v1.5.4
|
||||
github.com/gojuno/minimock/v3 v3.4.7
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/jackc/pgx/v5 v5.8.0
|
||||
github.com/rookie-ninja/rk-boot/v2 v2.2.22
|
||||
github.com/rookie-ninja/rk-entry/v2 v2.2.22
|
||||
github.com/rookie-ninja/rk-grpc/v2 v2.2.22
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/xuri/excelize/v2 v2.10.0
|
||||
go.uber.org/zap v1.27.1
|
||||
google.golang.org/grpc v1.78.0
|
||||
google.golang.org/protobuf v1.36.11
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/benbjohnson/clock v1.3.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect
|
||||
github.com/improbable-eng/grpc-web v0.15.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
|
||||
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
|
||||
github.com/mfridman/interpolate v0.0.2 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/openzipkin/zipkin-go v0.4.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/pressly/goose/v3 v3.26.0 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.5 // indirect
|
||||
github.com/prometheus/procfs v0.19.2 // indirect
|
||||
github.com/richardlehane/mscfb v1.0.4 // indirect
|
||||
github.com/richardlehane/msoleps v1.0.4 // indirect
|
||||
github.com/rookie-ninja/rk-logger v1.2.13 // indirect
|
||||
github.com/rookie-ninja/rk-query v1.2.14 // indirect
|
||||
github.com/rs/cors v1.7.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.12.0 // indirect
|
||||
github.com/sethvargo/go-retry v0.3.0 // indirect
|
||||
github.com/soheilhy/cmux v0.1.5 // indirect
|
||||
github.com/spf13/afero v1.15.0 // indirect
|
||||
github.com/spf13/cast v1.10.0 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/spf13/viper v1.21.0 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/tiendc/go-deepcopy v1.7.1 // indirect
|
||||
github.com/xuri/efp v0.0.1 // indirect
|
||||
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib v1.19.0 // indirect
|
||||
go.opentelemetry.io/otel v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/zipkin v1.18.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/ratelimit v0.3.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.47.0 // indirect
|
||||
golang.org/x/net v0.49.0 // indirect
|
||||
golang.org/x/sync v0.19.0 // indirect
|
||||
golang.org/x/sys v0.40.0 // indirect
|
||||
golang.org/x/text v0.33.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20251029180050-ab9386a59fda // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260114163908-3f89685c29c3 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
nhooyr.io/websocket v1.8.6 // indirect
|
||||
)
|
||||
677
go.sum
Normal file
677
go.sum
Normal file
@@ -0,0 +1,677 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM=
|
||||
github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
|
||||
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
|
||||
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
|
||||
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
|
||||
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I=
|
||||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
|
||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
|
||||
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
|
||||
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
|
||||
github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
|
||||
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
|
||||
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
|
||||
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gojuno/minimock/v3 v3.4.7 h1:vhE5zpniyPDRT0DXd5s3DbtZJVlcbmC5k80izYtj9lY=
|
||||
github.com/gojuno/minimock/v3 v3.4.7/go.mod h1:QxJk4mdPrVyYUmEZGc2yD2NONpqM/j4dWhsy9twjFHg=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/glog v1.2.5 h1:DrW6hGnjIhtvhOIiAKT6Psh/Kd/ldepEa81DKeiRJ5I=
|
||||
github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk=
|
||||
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
|
||||
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
|
||||
github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ=
|
||||
github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.8.0 h1:TYPDoleBBme0xGSAX3/+NujXXtpZn9HBONkQC7IEZSo=
|
||||
github.com/jackc/pgx/v5 v5.8.0/go.mod h1:QVeDInX2m9VyzvNeiCJVjCkNFqzsNb43204HshNSZKw=
|
||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw=
|
||||
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o=
|
||||
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk=
|
||||
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw=
|
||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
|
||||
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY=
|
||||
github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76/go.mod h1:x5OoJHDHqxHS801UIuhqGl6QdSAEJvtausosHSdazIo=
|
||||
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
|
||||
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
|
||||
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
|
||||
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
|
||||
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
|
||||
github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
|
||||
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
|
||||
github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
|
||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/openzipkin/zipkin-go v0.4.2 h1:zjqfqHjUpPmB3c1GlCvvgsM1G4LkvqQbBDueDOCg/jA=
|
||||
github.com/openzipkin/zipkin-go v0.4.2/go.mod h1:ZeVkFjuuBiSy13y8vpSDCjMi9GoI3hPpCJSBx/EYFhY=
|
||||
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
||||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/pressly/goose/v3 v3.26.0 h1:KJakav68jdH0WDvoAcj8+n61WqOIaPGgH0bJWS6jpmM=
|
||||
github.com/pressly/goose/v3 v3.26.0/go.mod h1:4hC1KrritdCxtuFsqgs1R4AU5bWtTAf+cnWvfhf2DNY=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
|
||||
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
|
||||
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
|
||||
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
|
||||
github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
|
||||
github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4=
|
||||
github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws=
|
||||
github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
|
||||
github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
|
||||
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||
github.com/richardlehane/msoleps v1.0.4 h1:WuESlvhX3gH2IHcd8UqyCuFY5yiq/GR/yqaSM/9/g00=
|
||||
github.com/richardlehane/msoleps v1.0.4/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/rookie-ninja/rk-boot/v2 v2.2.22 h1:JeDO1iibJGYNEi19czLq4xTVJW2eAsIwi0n8B3r+TEQ=
|
||||
github.com/rookie-ninja/rk-boot/v2 v2.2.22/go.mod h1:vSWXUxJT7xVNZzrhy/r/wsQ+fjKLWQw6BaZJIHbQXNE=
|
||||
github.com/rookie-ninja/rk-entry/v2 v2.2.22 h1:kYXhLV22APPxd9h6kLtA5Vf/tswPOw2Rth2X3NlUi7E=
|
||||
github.com/rookie-ninja/rk-entry/v2 v2.2.22/go.mod h1:ZvSdFFG2HuJDmDuZP2ljh/0RiuMt/hjUs5p+n54W56Q=
|
||||
github.com/rookie-ninja/rk-grpc/v2 v2.2.22 h1:prPnZ6GDFejWgAP63CAEEyk6GFSyJsGF9T6fK1+x1hs=
|
||||
github.com/rookie-ninja/rk-grpc/v2 v2.2.22/go.mod h1:zNEHf1NTb16OoA7gkTisINqOxfNwqmlH6IUR3cpJg0k=
|
||||
github.com/rookie-ninja/rk-logger v1.2.13 h1:ERxeNZUmszlY4xehHcJRXECPtbjYIXzN8yRIyYyLGsg=
|
||||
github.com/rookie-ninja/rk-logger v1.2.13/go.mod h1:0ZiGn1KsHKOmCv+FHMH7k40DWYSJcj5yIR3EYcjlnLs=
|
||||
github.com/rookie-ninja/rk-query v1.2.14 h1:aYNyMXixpsEYRfEOz9Npt5QG3A6BQlo9vKjYc78x7bc=
|
||||
github.com/rookie-ninja/rk-query v1.2.14/go.mod h1:OG4rBizXsBjGp+gbyWNTeQogJLzZGUZWkV9QeHEj1ZU=
|
||||
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
|
||||
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4=
|
||||
github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE=
|
||||
github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
|
||||
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
|
||||
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
|
||||
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
|
||||
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
|
||||
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
|
||||
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
|
||||
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
|
||||
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/tiendc/go-deepcopy v1.7.1 h1:LnubftI6nYaaMOcaz0LphzwraqN8jiWTwm416sitff4=
|
||||
github.com/tiendc/go-deepcopy v1.7.1/go.mod h1:4bKjNC2r7boYOkD2IOuZpYjmlDdzjbpTRyCx+goBCJQ=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xuri/efp v0.0.1 h1:fws5Rv3myXyYni8uwj2qKjVaRP30PdjeYe2Y6FDsCL8=
|
||||
github.com/xuri/efp v0.0.1/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
|
||||
github.com/xuri/excelize/v2 v2.10.0 h1:8aKsP7JD39iKLc6dH5Tw3dgV3sPRh8uRVXu/fMstfW4=
|
||||
github.com/xuri/excelize/v2 v2.10.0/go.mod h1:SC5TzhQkaOsTWpANfm+7bJCldzcnU/jrhqkTi/iBHBU=
|
||||
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9 h1:+C0TIdyyYmzadGaL/HBLbf3WdLgC29pgyhTjAT/0nuE=
|
||||
github.com/xuri/nfp v0.0.2-0.20250530014748-2ddeb826f9a9/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib v1.19.0 h1:rnYI7OEPMWFeM4QCqWQ3InMJ0arWMR1i0Cx9A5hcjYM=
|
||||
go.opentelemetry.io/contrib v1.19.0/go.mod h1:gIzjwWFoGazJmtCaDgViqOSJPde2mCWzv60o0bWPcZs=
|
||||
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
|
||||
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 h1:IAtl+7gua134xcV3NieDhJHjjOVeJhXAnYf/0hswjUY=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0/go.mod h1:w+pXobnBzh95MNIkeIuAKcHe/Uu/CX2PKIvBP6ipKRA=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 h1:yE32ay7mJG2leczfREEhoW3VfSZIvHaB+gvVo1o8DQ8=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0/go.mod h1:G17FHPDLt74bCI7tJ4CMitEk4BXTYG4FW6XUpkPBXa4=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 h1:hSWWvDjXHVLq9DkmB+77fl8v7+t+yYiS+eNkiplDK54=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0/go.mod h1:zG7KQql1WjZCaUJd+L/ReSYx4bjbYJxg5ws9ws+mYes=
|
||||
go.opentelemetry.io/otel/exporters/zipkin v1.18.0 h1:ZqrHgvega5NIiScTiVrtpZSpEmjUdwzkhuuCEIMAp+s=
|
||||
go.opentelemetry.io/otel/exporters/zipkin v1.18.0/go.mod h1:C80yIYcSceQipAZb4Ah11EE/yERlyc1MtqJG2xP7p+s=
|
||||
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
|
||||
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
|
||||
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
|
||||
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
|
||||
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
||||
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
|
||||
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
|
||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/ratelimit v0.3.0 h1:IdZd9wqvFXnvLvSEBo0KPcGfkoBGNkpTHlrE3Rcjkjw=
|
||||
go.uber.org/ratelimit v0.3.0/go.mod h1:So5LG7CV1zWpY1sHe+DXTJqQvOx+FFPFaAs2SnoyBaI=
|
||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||
go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
|
||||
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
||||
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.25.0 h1:Y6uW6rH1y5y/LK1J8BPWZtr6yZ7hrsy6hFrXjgsc2fQ=
|
||||
golang.org/x/image v0.25.0/go.mod h1:tCAmOEGthTtkalusGp1g3xa2gke8J6c2N565dTyl9Rs=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20251029180050-ab9386a59fda h1:+2XxjfsAu6vqFxwGBRcHiMaDCuZiqXGDUDVWVtrFAnE=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20251029180050-ab9386a59fda/go.mod h1:fDMmzKV90WSg1NbozdqrE64fkuTv6mlq2zxo9ad+3yo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260114163908-3f89685c29c3 h1:C4WAdL+FbjnGlpp2S+HMVhBeCq2Lcib4xZqfPNF6OoQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260114163908-3f89685c29c3/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
||||
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k=
|
||||
nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||
193
internal/ai/openai.go
Normal file
193
internal/ai/openai.go
Normal file
@@ -0,0 +1,193 @@
|
||||
package ai
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"smart-search-back/pkg/errors"
|
||||
)
|
||||
|
||||
type OpenAIClient struct {
|
||||
apiKey string
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
type openAIRequest struct {
|
||||
Model string `json:"model"`
|
||||
Messages []openAIMessage `json:"messages"`
|
||||
}
|
||||
|
||||
type openAIMessage struct {
|
||||
Role string `json:"role"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
type openAIResponse struct {
|
||||
Choices []struct {
|
||||
Message openAIMessage `json:"message"`
|
||||
} `json:"choices"`
|
||||
Error *struct {
|
||||
Message string `json:"message"`
|
||||
} `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
type tzResponse struct {
|
||||
TZResponse string `json:"tz_response"`
|
||||
}
|
||||
|
||||
func NewOpenAIClient(apiKey string) *OpenAIClient {
|
||||
return &OpenAIClient{
|
||||
apiKey: apiKey,
|
||||
client: &http.Client{},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *OpenAIClient) isMockMode() bool {
|
||||
return c.apiKey == ""
|
||||
}
|
||||
|
||||
func (c *OpenAIClient) GenerateTZ(requestTxt string) (string, error) {
|
||||
if c.isMockMode() {
|
||||
return c.generateMockTZ(requestTxt), nil
|
||||
}
|
||||
|
||||
prompt := fmt.Sprintf(`Ты — эксперт по разработке технических заданий.
|
||||
|
||||
ЗАДАЧА:
|
||||
Преобразовать описание заказа в структурированное техническое задание.
|
||||
|
||||
ВХОДНЫЕ ДАННЫЕ:
|
||||
Описание: %s
|
||||
|
||||
СТРУКТУРА ТЗ:
|
||||
1. Наименование и описание
|
||||
2. Количество и единицы измерения
|
||||
3. Технические требования
|
||||
4. Сроки выполнения/поставки
|
||||
6. Требования к качеству (если есть)
|
||||
7. Стоимость/бюджет (если указан)
|
||||
8. Особые условия
|
||||
|
||||
ПРИМЕР:
|
||||
|
||||
Входные данные: "Нужны офисные столы деревянные, 10 шт, белого цвета, на колесиках, 50 тысяч, на ул. Пушкина"
|
||||
|
||||
Ответ:
|
||||
{
|
||||
"tz_response": "ТЕХНИЧЕСКОЕ ЗАДАНИЕ\n\n1. ПРЕДМЕТ\nПоставка офисных столов\n\n2. КОЛИЧЕСТВО\n10 шт.\n\n3. ТРЕБОВАНИЯ\n- Материал: дерево\n- Цвет: белый\n- На колесиках\n\n4. МЕСТО ДОСТАВКИ\nг. Москва, ул. Пушкина\n\n5. БЮДЖЕТ\n50 000 руб.\n\n6. СРОКИ\nОт согласования"
|
||||
}
|
||||
|
||||
ФОРМАТ ОТВЕТА:
|
||||
{
|
||||
"tz_response": "ТЕХНИЧЕСКОЕ ЗАДАНИЕ\n\n1. РАЗДЕЛ\nДетали...\n\n2. РАЗДЕЛ\nДетали..."
|
||||
}
|
||||
|
||||
ПРАВИЛА:
|
||||
- Ответ ТОЛЬКО в формате JSON
|
||||
- Используй \n для переносов строк
|
||||
- Без текста до или после JSON
|
||||
- Ясная нумерация разделов
|
||||
- Все параметры из описания должны быть в ТЗ
|
||||
- Если параметр не указан → укажи "Не указано"`, requestTxt)
|
||||
|
||||
reqBody := openAIRequest{
|
||||
Model: "gpt-4o-mini",
|
||||
Messages: []openAIMessage{
|
||||
{
|
||||
Role: "user",
|
||||
Content: prompt,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
jsonData, err := json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
return "", errors.NewInternalError(errors.AIAPIError, "failed to marshal request", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", "https://api.openai.com/v1/chat/completions", bytes.NewBuffer(jsonData))
|
||||
if err != nil {
|
||||
return "", errors.NewInternalError(errors.AIAPIError, "failed to create request", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+c.apiKey)
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return "", errors.NewInternalError(errors.AIAPIError, "failed to send request", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", errors.NewInternalError(errors.AIAPIError, "failed to read response", err)
|
||||
}
|
||||
|
||||
var aiResp openAIResponse
|
||||
if err := json.Unmarshal(body, &aiResp); err != nil {
|
||||
return "", errors.NewInternalError(errors.AIAPIError, "failed to unmarshal response", err)
|
||||
}
|
||||
|
||||
if aiResp.Error != nil {
|
||||
return "", errors.NewInternalError(errors.AIAPIError, aiResp.Error.Message, nil)
|
||||
}
|
||||
|
||||
if len(aiResp.Choices) == 0 {
|
||||
return "", errors.NewInternalError(errors.AIAPIError, "no choices in response", nil)
|
||||
}
|
||||
|
||||
content := aiResp.Choices[0].Message.Content
|
||||
|
||||
content = strings.TrimPrefix(content, "```json")
|
||||
content = strings.TrimPrefix(content, "```")
|
||||
content = strings.TrimSuffix(content, "```")
|
||||
content = strings.TrimSpace(content)
|
||||
|
||||
var tzResp tzResponse
|
||||
if err := json.Unmarshal([]byte(content), &tzResp); err != nil {
|
||||
re := regexp.MustCompile(`\{[\s\S]*\}`)
|
||||
match := re.FindString(content)
|
||||
if match != "" {
|
||||
if err := json.Unmarshal([]byte(match), &tzResp); err != nil {
|
||||
return "", errors.NewInternalError(errors.AIAPIError, "failed to parse TZ response", err)
|
||||
}
|
||||
} else {
|
||||
return "", errors.NewInternalError(errors.AIAPIError, "failed to parse TZ response", err)
|
||||
}
|
||||
}
|
||||
|
||||
return tzResp.TZResponse, nil
|
||||
}
|
||||
|
||||
func (c *OpenAIClient) generateMockTZ(requestTxt string) string {
|
||||
return fmt.Sprintf(`ТЕХНИЧЕСКОЕ ЗАДАНИЕ (MOCK)
|
||||
|
||||
1. ПРЕДМЕТ
|
||||
%s
|
||||
|
||||
2. КОЛИЧЕСТВО
|
||||
По запросу
|
||||
|
||||
3. ТРЕБОВАНИЯ
|
||||
- Качественное исполнение
|
||||
- Соответствие стандартам
|
||||
- Своевременная поставка
|
||||
|
||||
4. МЕСТО ДОСТАВКИ
|
||||
г. Москва
|
||||
|
||||
5. БЮДЖЕТ
|
||||
Уточняется
|
||||
|
||||
6. СРОКИ
|
||||
От согласования
|
||||
|
||||
7. ОСОБЫЕ УСЛОВИЯ
|
||||
Mock-данные для тестирования. API ключ OpenAI не настроен.`, requestTxt)
|
||||
}
|
||||
321
internal/ai/perplexity.go
Normal file
321
internal/ai/perplexity.go
Normal file
@@ -0,0 +1,321 @@
|
||||
package ai
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"smart-search-back/internal/model"
|
||||
"smart-search-back/pkg/errors"
|
||||
)
|
||||
|
||||
type PerplexityClient struct {
|
||||
apiKey string
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
type perplexityRequest struct {
|
||||
Model string `json:"model"`
|
||||
Messages []perplexityMessage `json:"messages"`
|
||||
}
|
||||
|
||||
type perplexityMessage struct {
|
||||
Role string `json:"role"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
type perplexityResponse struct {
|
||||
Choices []struct {
|
||||
Message perplexityMessage `json:"message"`
|
||||
} `json:"choices"`
|
||||
Usage *struct {
|
||||
PromptTokens int `json:"prompt_tokens"`
|
||||
CompletionTokens int `json:"completion_tokens"`
|
||||
} `json:"usage,omitempty"`
|
||||
Error *struct {
|
||||
Message string `json:"message"`
|
||||
} `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
type supplierData struct {
|
||||
CompanyName string `json:"company_name"`
|
||||
Email string `json:"email"`
|
||||
Phone string `json:"phone"`
|
||||
Address string `json:"adress"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
func NewPerplexityClient(apiKey string) *PerplexityClient {
|
||||
return &PerplexityClient{
|
||||
apiKey: apiKey,
|
||||
client: &http.Client{},
|
||||
}
|
||||
}
|
||||
|
||||
func (c *PerplexityClient) isMockMode() bool {
|
||||
return c.apiKey == ""
|
||||
}
|
||||
|
||||
func (c *PerplexityClient) FindSuppliers(tzText string) ([]*model.Supplier, int, int, error) {
|
||||
if c.isMockMode() {
|
||||
return c.generateMockSuppliers(), 1000, 500, nil
|
||||
}
|
||||
|
||||
prompt := fmt.Sprintf(`Ты — эксперт по поиску поставщиков на российском рынке.
|
||||
|
||||
ЗАДАЧА:
|
||||
Найти компании-поставщики/производители для технического задания:
|
||||
%s
|
||||
|
||||
ОПРЕДЕЛЕНИЕ ТИПА ПОИСКА:
|
||||
- Если ТЗ требует производства/изготовления → ищи производителей
|
||||
- Если ТЗ требует готовый товар/услугу → ищи компании, которые это продают
|
||||
|
||||
КРИТЕРИИ:
|
||||
1. Максимальная релевантность
|
||||
2. Действующие компании с полными контактами
|
||||
3. Приоритет: производители > дистрибьюторы
|
||||
|
||||
ПРИМЕРЫ ОТВЕТОВ:
|
||||
|
||||
Пример 1 - ТЗ: "Поставка офисной мебели: столы 20 шт, стулья 50 шт"
|
||||
[
|
||||
{
|
||||
"company_name": "ООО Мебельная фабрика Союз",
|
||||
"email": "zakaz@mebelsoyuz.ru",
|
||||
"phone": "+7 495 123-45-67",
|
||||
"adress": "г. Москва, ул. Промышленная, д. 15",
|
||||
"url": ""
|
||||
}
|
||||
]
|
||||
|
||||
Пример 2 - ТЗ: "Производство кованых изделий: ворота, решётки, перила"
|
||||
[
|
||||
{
|
||||
"company_name": "ООО Кузня Премиум",
|
||||
"email": "info@kuzniya.ru",
|
||||
"phone": "",
|
||||
"adress": "г. Москва, ул. Заводская, д. 42",
|
||||
"url": "www.mebelsoyuz.ru"
|
||||
}
|
||||
]
|
||||
|
||||
ФОРМАТ ОТВЕТА - ТОЛЬКО JSON:
|
||||
[
|
||||
{
|
||||
"company_name": "...",
|
||||
"email": "...",
|
||||
"phone": "...",
|
||||
"adress": "...",
|
||||
"url": "..."
|
||||
}
|
||||
]
|
||||
|
||||
ПРАВИЛА:
|
||||
- Минимум 15 компаний, максимум 100
|
||||
- Только валидный JSON массив, без текста вокруг
|
||||
- email и url всегда заполнены (не null)
|
||||
- Если другие поля пустые, то можно оставить пустую строку -> ""
|
||||
- Сортируй по релевантности`, tzText)
|
||||
|
||||
reqBody := perplexityRequest{
|
||||
Model: "llama-3.1-sonar-large-128k-online",
|
||||
Messages: []perplexityMessage{
|
||||
{
|
||||
Role: "user",
|
||||
Content: prompt,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
jsonData, err := json.Marshal(reqBody)
|
||||
if err != nil {
|
||||
return nil, 0, 0, errors.NewInternalError(errors.AIAPIError, "failed to marshal request", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", "https://api.perplexity.ai/chat/completions", bytes.NewBuffer(jsonData))
|
||||
if err != nil {
|
||||
return nil, 0, 0, errors.NewInternalError(errors.AIAPIError, "failed to create request", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+c.apiKey)
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, 0, 0, errors.NewInternalError(errors.AIAPIError, "failed to send request", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, 0, 0, errors.NewInternalError(errors.AIAPIError, "failed to read response", err)
|
||||
}
|
||||
|
||||
var aiResp perplexityResponse
|
||||
if err := json.Unmarshal(body, &aiResp); err != nil {
|
||||
return nil, 0, 0, errors.NewInternalError(errors.AIAPIError, "failed to unmarshal response", err)
|
||||
}
|
||||
|
||||
if aiResp.Error != nil {
|
||||
return nil, 0, 0, errors.NewInternalError(errors.AIAPIError, aiResp.Error.Message, nil)
|
||||
}
|
||||
|
||||
if len(aiResp.Choices) == 0 {
|
||||
return nil, 0, 0, errors.NewInternalError(errors.AIAPIError, "no choices in response", nil)
|
||||
}
|
||||
|
||||
content := aiResp.Choices[0].Message.Content
|
||||
|
||||
content = strings.TrimPrefix(content, "```json")
|
||||
content = strings.TrimPrefix(content, "```")
|
||||
content = strings.TrimSuffix(content, "```")
|
||||
content = strings.TrimSpace(content)
|
||||
|
||||
var supplierDataList []supplierData
|
||||
if err := json.Unmarshal([]byte(content), &supplierDataList); err != nil {
|
||||
re := regexp.MustCompile(`\[[\s\S]*\]`)
|
||||
match := re.FindString(content)
|
||||
if match != "" {
|
||||
if err := json.Unmarshal([]byte(match), &supplierDataList); err != nil {
|
||||
return nil, 0, 0, errors.NewInternalError(errors.AIAPIError, "failed to parse suppliers response", err)
|
||||
}
|
||||
} else {
|
||||
return nil, 0, 0, errors.NewInternalError(errors.AIAPIError, "failed to parse suppliers response", err)
|
||||
}
|
||||
}
|
||||
|
||||
suppliers := make([]*model.Supplier, 0, len(supplierDataList))
|
||||
for _, sd := range supplierDataList {
|
||||
suppliers = append(suppliers, &model.Supplier{
|
||||
Name: sd.CompanyName,
|
||||
Email: sd.Email,
|
||||
Phone: sd.Phone,
|
||||
Address: sd.Address,
|
||||
URL: sd.URL,
|
||||
})
|
||||
}
|
||||
|
||||
promptTokens := 0
|
||||
responseTokens := 0
|
||||
if aiResp.Usage != nil {
|
||||
promptTokens = aiResp.Usage.PromptTokens
|
||||
responseTokens = aiResp.Usage.CompletionTokens
|
||||
}
|
||||
|
||||
return suppliers, promptTokens, responseTokens, nil
|
||||
}
|
||||
|
||||
func (c *PerplexityClient) generateMockSuppliers() []*model.Supplier {
|
||||
return []*model.Supplier{
|
||||
{
|
||||
Name: "ООО Поставщик-1 (Mock)",
|
||||
Email: "supplier1@example.com",
|
||||
Phone: "+7 (495) 123-45-67",
|
||||
Address: "г. Москва, ул. Примерная, д. 1",
|
||||
URL: "https://supplier1.example.com",
|
||||
},
|
||||
{
|
||||
Name: "ООО Поставщик-2 (Mock)",
|
||||
Email: "supplier2@example.com",
|
||||
Phone: "+7 (495) 234-56-78",
|
||||
Address: "г. Москва, ул. Примерная, д. 2",
|
||||
URL: "https://supplier2.example.com",
|
||||
},
|
||||
{
|
||||
Name: "ООО Поставщик-3 (Mock)",
|
||||
Email: "supplier3@example.com",
|
||||
Phone: "+7 (495) 345-67-89",
|
||||
Address: "г. Москва, ул. Примерная, д. 3",
|
||||
URL: "https://supplier3.example.com",
|
||||
},
|
||||
{
|
||||
Name: "ООО Производитель-1 (Mock)",
|
||||
Email: "producer1@example.com",
|
||||
Phone: "+7 (495) 456-78-90",
|
||||
Address: "г. Санкт-Петербург, ул. Тестовая, д. 10",
|
||||
URL: "https://producer1.example.com",
|
||||
},
|
||||
{
|
||||
Name: "ООО Производитель-2 (Mock)",
|
||||
Email: "producer2@example.com",
|
||||
Phone: "+7 (495) 567-89-01",
|
||||
Address: "г. Санкт-Петербург, ул. Тестовая, д. 20",
|
||||
URL: "https://producer2.example.com",
|
||||
},
|
||||
{
|
||||
Name: "ООО Дистрибьютор-1 (Mock)",
|
||||
Email: "distributor1@example.com",
|
||||
Phone: "+7 (495) 678-90-12",
|
||||
Address: "г. Казань, ул. Демо, д. 5",
|
||||
URL: "https://distributor1.example.com",
|
||||
},
|
||||
{
|
||||
Name: "ООО Дистрибьютор-2 (Mock)",
|
||||
Email: "distributor2@example.com",
|
||||
Phone: "+7 (495) 789-01-23",
|
||||
Address: "г. Казань, ул. Демо, д. 15",
|
||||
URL: "https://distributor2.example.com",
|
||||
},
|
||||
{
|
||||
Name: "ООО Импортер-1 (Mock)",
|
||||
Email: "importer1@example.com",
|
||||
Phone: "+7 (495) 890-12-34",
|
||||
Address: "г. Новосибирск, ул. Примера, д. 100",
|
||||
URL: "https://importer1.example.com",
|
||||
},
|
||||
{
|
||||
Name: "ООО Импортер-2 (Mock)",
|
||||
Email: "importer2@example.com",
|
||||
Phone: "+7 (495) 901-23-45",
|
||||
Address: "г. Новосибирск, ул. Примера, д. 200",
|
||||
URL: "https://importer2.example.com",
|
||||
},
|
||||
{
|
||||
Name: "ООО Оптовик-1 (Mock)",
|
||||
Email: "wholesale1@example.com",
|
||||
Phone: "+7 (495) 012-34-56",
|
||||
Address: "г. Екатеринбург, ул. Тестовая, д. 50",
|
||||
URL: "https://wholesale1.example.com",
|
||||
},
|
||||
{
|
||||
Name: "ООО Оптовик-2 (Mock)",
|
||||
Email: "wholesale2@example.com",
|
||||
Phone: "+7 (495) 123-45-67",
|
||||
Address: "г. Екатеринбург, ул. Тестовая, д. 60",
|
||||
URL: "https://wholesale2.example.com",
|
||||
},
|
||||
{
|
||||
Name: "ООО Фабрика-1 (Mock)",
|
||||
Email: "factory1@example.com",
|
||||
Phone: "+7 (495) 234-56-78",
|
||||
Address: "г. Нижний Новгород, Промзона, д. 1",
|
||||
URL: "https://factory1.example.com",
|
||||
},
|
||||
{
|
||||
Name: "ООО Фабрика-2 (Mock)",
|
||||
Email: "factory2@example.com",
|
||||
Phone: "+7 (495) 345-67-89",
|
||||
Address: "г. Нижний Новгород, Промзона, д. 2",
|
||||
URL: "https://factory2.example.com",
|
||||
},
|
||||
{
|
||||
Name: "ООО Завод-1 (Mock)",
|
||||
Email: "plant1@example.com",
|
||||
Phone: "+7 (495) 456-78-90",
|
||||
Address: "г. Челябинск, Индустриальная, д. 10",
|
||||
URL: "https://plant1.example.com",
|
||||
},
|
||||
{
|
||||
Name: "ООО Завод-2 (Mock)",
|
||||
Email: "plant2@example.com",
|
||||
Phone: "+7 (495) 567-89-01",
|
||||
Address: "г. Челябинск, Индустриальная, д. 20",
|
||||
URL: "https://plant2.example.com",
|
||||
},
|
||||
}
|
||||
}
|
||||
111
internal/config/config.go
Normal file
111
internal/config/config.go
Normal file
@@ -0,0 +1,111 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Database DatabaseConfig `yaml:"database"`
|
||||
AI AIConfig `yaml:"ai"`
|
||||
Security SecurityConfig `yaml:"security"`
|
||||
GRPC GRPCConfig `yaml:"grpc"`
|
||||
Logging LoggingConfig `yaml:"logging"`
|
||||
}
|
||||
|
||||
type DatabaseConfig struct {
|
||||
Host string `yaml:"host"`
|
||||
Port int `yaml:"port"`
|
||||
Name string `yaml:"name"`
|
||||
User string `yaml:"user"`
|
||||
Password string `yaml:"password"`
|
||||
SSLMode string `yaml:"ssl_mode"`
|
||||
MaxConns int `yaml:"max_conns"`
|
||||
MinConns int `yaml:"min_conns"`
|
||||
}
|
||||
|
||||
type AIConfig struct {
|
||||
OpenAIKey string `yaml:"openai_key"`
|
||||
PerplexityKey string `yaml:"perplexity_key"`
|
||||
}
|
||||
|
||||
type SecurityConfig struct {
|
||||
JWTSecret string `yaml:"jwt_secret"`
|
||||
CryptoSecret string `yaml:"crypto_secret"`
|
||||
}
|
||||
|
||||
type GRPCConfig struct {
|
||||
Port int `yaml:"port"`
|
||||
MaxConnections int `yaml:"max_connections"`
|
||||
}
|
||||
|
||||
type LoggingConfig struct {
|
||||
Level string `yaml:"level"`
|
||||
}
|
||||
|
||||
func Load(path string) (*Config, error) {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read config file: %w", err)
|
||||
}
|
||||
|
||||
data = []byte(expandEnvWithDefaults(string(data)))
|
||||
|
||||
var cfg Config
|
||||
if err := yaml.Unmarshal(data, &cfg); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal config: %w", err)
|
||||
}
|
||||
|
||||
if err := cfg.validate(); err != nil {
|
||||
return nil, fmt.Errorf("invalid config: %w", err)
|
||||
}
|
||||
|
||||
return &cfg, nil
|
||||
}
|
||||
|
||||
func expandEnvWithDefaults(s string) string {
|
||||
re := regexp.MustCompile(`\$\{([^:}]+):([^}]*)\}`)
|
||||
result := re.ReplaceAllStringFunc(s, func(match string) string {
|
||||
parts := re.FindStringSubmatch(match)
|
||||
if len(parts) != 3 {
|
||||
return match
|
||||
}
|
||||
envVar := parts[1]
|
||||
defaultVal := parts[2]
|
||||
if val := os.Getenv(envVar); val != "" {
|
||||
return val
|
||||
}
|
||||
return defaultVal
|
||||
})
|
||||
return os.ExpandEnv(result)
|
||||
}
|
||||
|
||||
func (c *Config) validate() error {
|
||||
if c.Database.Host == "" {
|
||||
return fmt.Errorf("database host is required")
|
||||
}
|
||||
if c.Database.Name == "" {
|
||||
return fmt.Errorf("database name is required")
|
||||
}
|
||||
if c.Database.User == "" {
|
||||
return fmt.Errorf("database user is required")
|
||||
}
|
||||
if c.Database.Password == "" {
|
||||
return fmt.Errorf("database password is required")
|
||||
}
|
||||
if c.Security.JWTSecret == "" {
|
||||
return fmt.Errorf("JWT secret is required")
|
||||
}
|
||||
if c.Security.CryptoSecret == "" {
|
||||
return fmt.Errorf("crypto secret is required")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) DatabaseURL() string {
|
||||
return fmt.Sprintf("postgres://%s:%s@%s:%d/%s?sslmode=%s",
|
||||
c.Database.User, c.Database.Password, c.Database.Host, c.Database.Port, c.Database.Name, c.Database.SSLMode)
|
||||
}
|
||||
31
internal/database/migrations.go
Normal file
31
internal/database/migrations.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
_ "github.com/jackc/pgx/v5/stdlib"
|
||||
"github.com/pressly/goose/v3"
|
||||
)
|
||||
|
||||
func RunMigrations(databaseURL string) error {
|
||||
db, err := sql.Open("pgx", databaseURL)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open database connection for migrations: %w", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
if err := db.Ping(); err != nil {
|
||||
return fmt.Errorf("failed to ping database before migrations: %w", err)
|
||||
}
|
||||
|
||||
if err := goose.SetDialect("postgres"); err != nil {
|
||||
return fmt.Errorf("failed to set goose dialect: %w", err)
|
||||
}
|
||||
|
||||
if err := goose.Up(db, "migrations"); err != nil {
|
||||
return fmt.Errorf("failed to run migrations: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
70
internal/grpc/auth_handler.go
Normal file
70
internal/grpc/auth_handler.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"smart-search-back/pkg/errors"
|
||||
pb "smart-search-back/pkg/pb/api/proto/auth"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
func (h *AuthHandler) Login(ctx context.Context, req *pb.LoginRequest) (*pb.LoginResponse, error) {
|
||||
accessToken, refreshToken, err := h.authService.Login(
|
||||
ctx,
|
||||
req.Email,
|
||||
req.Password,
|
||||
req.Ip,
|
||||
req.UserAgent,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errors.ToGRPCError(err, h.logger, "AuthService.Login")
|
||||
}
|
||||
|
||||
return &pb.LoginResponse{
|
||||
AccessToken: accessToken,
|
||||
RefreshToken: refreshToken,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *AuthHandler) Refresh(ctx context.Context, req *pb.RefreshRequest) (*pb.RefreshResponse, error) {
|
||||
accessToken, err := h.authService.Refresh(ctx, req.RefreshToken)
|
||||
if err != nil {
|
||||
return nil, errors.ToGRPCError(err, h.logger, "AuthService.Refresh")
|
||||
}
|
||||
|
||||
return &pb.RefreshResponse{
|
||||
AccessToken: accessToken,
|
||||
RefreshToken: req.RefreshToken,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *AuthHandler) Validate(ctx context.Context, req *pb.ValidateRequest) (*pb.ValidateResponse, error) {
|
||||
userID, err := h.authService.Validate(ctx, req.AccessToken)
|
||||
if err != nil {
|
||||
h.logger.Warn("Token validation failed",
|
||||
zap.String("method", "AuthService.Validate"),
|
||||
zap.Error(err),
|
||||
)
|
||||
return &pb.ValidateResponse{
|
||||
Valid: false,
|
||||
UserId: 0,
|
||||
}, nil
|
||||
}
|
||||
|
||||
return &pb.ValidateResponse{
|
||||
Valid: true,
|
||||
UserId: int64(userID),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *AuthHandler) Logout(ctx context.Context, req *pb.LogoutRequest) (*pb.LogoutResponse, error) {
|
||||
err := h.authService.Logout(ctx, req.AccessToken)
|
||||
if err != nil {
|
||||
return nil, errors.ToGRPCError(err, h.logger, "AuthService.Logout")
|
||||
}
|
||||
|
||||
return &pb.LogoutResponse{
|
||||
Success: true,
|
||||
}, nil
|
||||
}
|
||||
45
internal/grpc/invite_handler.go
Normal file
45
internal/grpc/invite_handler.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
"smart-search-back/pkg/errors"
|
||||
pb "smart-search-back/pkg/pb/api/proto/invite"
|
||||
)
|
||||
|
||||
func (h *InviteHandler) Generate(ctx context.Context, req *pb.GenerateRequest) (*pb.GenerateResponse, error) {
|
||||
invite, err := h.inviteService.Generate(ctx, int(req.UserId), int(req.TtlDays), int(req.MaxUses))
|
||||
if err != nil {
|
||||
return nil, errors.ToGRPCError(err, h.logger, "InviteService.Generate")
|
||||
}
|
||||
|
||||
return &pb.GenerateResponse{
|
||||
Code: strconv.FormatInt(invite.Code, 10),
|
||||
MaxUses: int32(invite.CanBeUsedCount),
|
||||
ExpiresAt: timestamppb.New(invite.ExpiresAt),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *InviteHandler) GetInfo(ctx context.Context, req *pb.GetInfoRequest) (*pb.GetInfoResponse, error) {
|
||||
code, err := strconv.ParseInt(req.Code, 10, 64)
|
||||
if err != nil {
|
||||
return nil, errors.ToGRPCError(err, h.logger, "InviteService.GetInfo")
|
||||
}
|
||||
|
||||
invite, err := h.inviteService.GetInfo(ctx, code)
|
||||
if err != nil {
|
||||
return nil, errors.ToGRPCError(err, h.logger, "InviteService.GetInfo")
|
||||
}
|
||||
|
||||
return &pb.GetInfoResponse{
|
||||
Code: strconv.FormatInt(invite.Code, 10),
|
||||
UserId: int64(invite.UserID),
|
||||
CanBeUsedCount: int32(invite.CanBeUsedCount),
|
||||
UsedCount: int32(invite.UsedCount),
|
||||
ExpiresAt: timestamppb.New(invite.ExpiresAt),
|
||||
IsActive: invite.IsActive,
|
||||
CreatedAt: timestamppb.New(invite.CreatedAt),
|
||||
}, nil
|
||||
}
|
||||
91
internal/grpc/request_handler.go
Normal file
91
internal/grpc/request_handler.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
"smart-search-back/pkg/errors"
|
||||
pb "smart-search-back/pkg/pb/api/proto/request"
|
||||
)
|
||||
|
||||
func (h *RequestHandler) CreateTZ(ctx context.Context, req *pb.CreateTZRequest) (*pb.CreateTZResponse, error) {
|
||||
requestTxt := req.RequestTxt
|
||||
if len(req.FileData) > 0 {
|
||||
requestTxt += "\n[File: " + req.FileName + "]"
|
||||
}
|
||||
|
||||
requestID, tzText, err := h.requestService.CreateTZ(ctx, int(req.UserId), requestTxt)
|
||||
if err != nil {
|
||||
return nil, errors.ToGRPCError(err, h.logger, "RequestService.CreateTZ")
|
||||
}
|
||||
|
||||
return &pb.CreateTZResponse{
|
||||
RequestId: requestID.String(),
|
||||
TzText: tzText,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *RequestHandler) ApproveTZ(ctx context.Context, req *pb.ApproveTZRequest) (*pb.ApproveTZResponse, error) {
|
||||
requestID, err := uuid.Parse(req.RequestId)
|
||||
if err != nil {
|
||||
return nil, errors.ToGRPCError(err, h.logger, "RequestService.ApproveTZ")
|
||||
}
|
||||
|
||||
_, err = h.requestService.ApproveTZ(ctx, requestID, req.FinalTz, int(req.UserId))
|
||||
if err != nil {
|
||||
return nil, errors.ToGRPCError(err, h.logger, "RequestService.ApproveTZ")
|
||||
}
|
||||
|
||||
return &pb.ApproveTZResponse{
|
||||
Success: true,
|
||||
MailingStatus: "sent",
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *RequestHandler) GetMailingList(ctx context.Context, req *pb.GetMailingListRequest) (*pb.GetMailingListResponse, error) {
|
||||
requests, err := h.requestService.GetMailingList(ctx, int(req.UserId))
|
||||
if err != nil {
|
||||
return nil, errors.ToGRPCError(err, h.logger, "RequestService.GetMailingList")
|
||||
}
|
||||
|
||||
items := make([]*pb.MailingItem, 0, len(requests))
|
||||
for _, r := range requests {
|
||||
items = append(items, &pb.MailingItem{
|
||||
RequestId: r.ID.String(),
|
||||
RequestTxt: r.RequestTxt,
|
||||
FinalTz: r.FinalTZ,
|
||||
MailingStatus: r.MailingStatus,
|
||||
CreatedAt: timestamppb.New(r.CreatedAt),
|
||||
SuppliersFound: 0,
|
||||
})
|
||||
}
|
||||
|
||||
return &pb.GetMailingListResponse{
|
||||
Items: items,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *RequestHandler) GetMailingListByID(ctx context.Context, req *pb.GetMailingListByIDRequest) (*pb.GetMailingListByIDResponse, error) {
|
||||
requestID, err := uuid.Parse(req.RequestId)
|
||||
if err != nil {
|
||||
return nil, errors.ToGRPCError(err, h.logger, "RequestService.GetMailingListByID")
|
||||
}
|
||||
|
||||
detail, err := h.requestService.GetMailingListByID(ctx, requestID)
|
||||
if err != nil {
|
||||
return nil, errors.ToGRPCError(err, h.logger, "RequestService.GetMailingListByID")
|
||||
}
|
||||
|
||||
return &pb.GetMailingListByIDResponse{
|
||||
Item: &pb.MailingItem{
|
||||
RequestId: detail.RequestID.String(),
|
||||
RequestTxt: detail.Title,
|
||||
FinalTz: detail.MailText,
|
||||
MailingStatus: "sent",
|
||||
CreatedAt: timestamppb.New(time.Now()),
|
||||
SuppliersFound: int32(len(detail.Suppliers)),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
78
internal/grpc/server.go
Normal file
78
internal/grpc/server.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"smart-search-back/internal/ai"
|
||||
"smart-search-back/internal/repository"
|
||||
"smart-search-back/internal/service"
|
||||
authpb "smart-search-back/pkg/pb/api/proto/auth"
|
||||
invitepb "smart-search-back/pkg/pb/api/proto/invite"
|
||||
requestpb "smart-search-back/pkg/pb/api/proto/request"
|
||||
supplierpb "smart-search-back/pkg/pb/api/proto/supplier"
|
||||
userpb "smart-search-back/pkg/pb/api/proto/user"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
type AuthHandler struct {
|
||||
authpb.UnimplementedAuthServiceServer
|
||||
authService service.AuthService
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
type UserHandler struct {
|
||||
userpb.UnimplementedUserServiceServer
|
||||
userService service.UserService
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
type InviteHandler struct {
|
||||
invitepb.UnimplementedInviteServiceServer
|
||||
inviteService service.InviteService
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
type RequestHandler struct {
|
||||
requestpb.UnimplementedRequestServiceServer
|
||||
requestService service.RequestService
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
type SupplierHandler struct {
|
||||
supplierpb.UnimplementedSupplierServiceServer
|
||||
supplierService service.SupplierService
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
func NewHandlers(pool *pgxpool.Pool, jwtSecret, cryptoSecret, openAIKey, perplexityKey string, logger *zap.Logger) (*AuthHandler, *UserHandler, *InviteHandler, *RequestHandler, *SupplierHandler) {
|
||||
userRepo := repository.NewUserRepository(pool, cryptoSecret)
|
||||
sessionRepo := repository.NewSessionRepository(pool)
|
||||
inviteRepo := repository.NewInviteRepository(pool)
|
||||
requestRepo := repository.NewRequestRepository(pool)
|
||||
supplierRepo := repository.NewSupplierRepository(pool)
|
||||
tokenUsageRepo := repository.NewTokenUsageRepository(pool)
|
||||
|
||||
openAIClient := ai.NewOpenAIClient(openAIKey)
|
||||
perplexityClient := ai.NewPerplexityClient(perplexityKey)
|
||||
|
||||
authService := service.NewAuthService(userRepo, sessionRepo, jwtSecret, cryptoSecret)
|
||||
userService := service.NewUserService(userRepo, requestRepo, cryptoSecret)
|
||||
inviteService := service.NewInviteService(inviteRepo, userRepo)
|
||||
requestService := service.NewRequestService(requestRepo, supplierRepo, tokenUsageRepo, userRepo, openAIClient, perplexityClient)
|
||||
supplierService := service.NewSupplierService(supplierRepo)
|
||||
|
||||
return &AuthHandler{authService: authService, logger: logger},
|
||||
&UserHandler{userService: userService, logger: logger},
|
||||
&InviteHandler{inviteService: inviteService, logger: logger},
|
||||
&RequestHandler{requestService: requestService, logger: logger},
|
||||
&SupplierHandler{supplierService: supplierService, logger: logger}
|
||||
}
|
||||
|
||||
func RegisterServices(s *grpc.Server, authH *AuthHandler, userH *UserHandler, inviteH *InviteHandler, requestH *RequestHandler, supplierH *SupplierHandler) {
|
||||
authpb.RegisterAuthServiceServer(s, authH)
|
||||
userpb.RegisterUserServiceServer(s, userH)
|
||||
invitepb.RegisterInviteServiceServer(s, inviteH)
|
||||
requestpb.RegisterRequestServiceServer(s, requestH)
|
||||
supplierpb.RegisterSupplierServiceServer(s, supplierH)
|
||||
}
|
||||
29
internal/grpc/supplier_handler.go
Normal file
29
internal/grpc/supplier_handler.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"smart-search-back/pkg/errors"
|
||||
pb "smart-search-back/pkg/pb/api/proto/supplier"
|
||||
)
|
||||
|
||||
func (h *SupplierHandler) ExportExcel(ctx context.Context, req *pb.ExportExcelRequest) (*pb.ExportExcelResponse, error) {
|
||||
requestID, err := uuid.Parse(req.RequestId)
|
||||
if err != nil {
|
||||
return nil, errors.ToGRPCError(err, h.logger, "SupplierService.ExportExcel")
|
||||
}
|
||||
|
||||
fileData, err := h.supplierService.ExportExcel(ctx, requestID)
|
||||
if err != nil {
|
||||
return nil, errors.ToGRPCError(err, h.logger, "SupplierService.ExportExcel")
|
||||
}
|
||||
|
||||
fileName := "suppliers_" + requestID.String() + ".xlsx"
|
||||
|
||||
return &pb.ExportExcelResponse{
|
||||
FileData: fileData,
|
||||
FileName: fileName,
|
||||
MimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
}, nil
|
||||
}
|
||||
66
internal/grpc/user_handler.go
Normal file
66
internal/grpc/user_handler.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package grpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"smart-search-back/pkg/errors"
|
||||
pb "smart-search-back/pkg/pb/api/proto/user"
|
||||
)
|
||||
|
||||
func (h *UserHandler) GetInfo(ctx context.Context, req *pb.GetInfoRequest) (*pb.GetInfoResponse, error) {
|
||||
user, err := h.userService.GetInfo(ctx, int(req.UserId))
|
||||
if err != nil {
|
||||
return nil, errors.ToGRPCError(err, h.logger, "UserService.GetInfo")
|
||||
}
|
||||
|
||||
return &pb.GetInfoResponse{
|
||||
Email: user.Email,
|
||||
Name: user.Name,
|
||||
Phone: user.Phone,
|
||||
CompanyName: user.CompanyName,
|
||||
PaymentStatus: user.PaymentStatus,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *UserHandler) GetBalance(ctx context.Context, req *pb.GetBalanceRequest) (*pb.GetBalanceResponse, error) {
|
||||
balance, err := h.userService.GetBalance(ctx, int(req.UserId))
|
||||
if err != nil {
|
||||
return nil, errors.ToGRPCError(err, h.logger, "UserService.GetBalance")
|
||||
}
|
||||
|
||||
return &pb.GetBalanceResponse{
|
||||
Balance: balance,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *UserHandler) GetStatistics(ctx context.Context, req *pb.GetStatisticsRequest) (*pb.GetStatisticsResponse, error) {
|
||||
stats, err := h.userService.GetStatistics(ctx, int(req.UserId))
|
||||
if err != nil {
|
||||
return nil, errors.ToGRPCError(err, h.logger, "UserService.GetStatistics")
|
||||
}
|
||||
|
||||
return &pb.GetStatisticsResponse{
|
||||
TotalRequests: int32(stats.RequestsCount),
|
||||
SuccessfulRequests: int32(stats.SuppliersCount),
|
||||
FailedRequests: 0,
|
||||
TotalSpent: 0,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *UserHandler) GetBalanceStatistics(ctx context.Context, req *pb.GetBalanceStatisticsRequest) (*pb.GetBalanceStatisticsResponse, error) {
|
||||
balance, err := h.userService.GetBalance(ctx, int(req.UserId))
|
||||
if err != nil {
|
||||
return nil, errors.ToGRPCError(err, h.logger, "UserService.GetBalanceStatistics")
|
||||
}
|
||||
|
||||
stats, err := h.userService.GetStatistics(ctx, int(req.UserId))
|
||||
if err != nil {
|
||||
return nil, errors.ToGRPCError(err, h.logger, "UserService.GetBalanceStatistics")
|
||||
}
|
||||
|
||||
return &pb.GetBalanceStatisticsResponse{
|
||||
Balance: balance,
|
||||
TotalRequests: int32(stats.RequestsCount),
|
||||
TotalSpent: 0,
|
||||
}, nil
|
||||
}
|
||||
1578
internal/mocks/auth_service_mock.go
Normal file
1578
internal/mocks/auth_service_mock.go
Normal file
File diff suppressed because it is too large
Load Diff
1809
internal/mocks/invite_repository_mock.go
Normal file
1809
internal/mocks/invite_repository_mock.go
Normal file
File diff suppressed because it is too large
Load Diff
836
internal/mocks/invite_service_mock.go
Normal file
836
internal/mocks/invite_service_mock.go
Normal file
@@ -0,0 +1,836 @@
|
||||
// Code generated by http://github.com/gojuno/minimock (v3.4.7). DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
//go:generate minimock -i smart-search-back/internal/service.InviteService -o invite_service_mock.go -n InviteServiceMock -p mocks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"smart-search-back/internal/model"
|
||||
"sync"
|
||||
mm_atomic "sync/atomic"
|
||||
mm_time "time"
|
||||
|
||||
"github.com/gojuno/minimock/v3"
|
||||
)
|
||||
|
||||
// InviteServiceMock implements mm_service.InviteService
|
||||
type InviteServiceMock struct {
|
||||
t minimock.Tester
|
||||
finishOnce sync.Once
|
||||
|
||||
funcGenerate func(ctx context.Context, userID int, maxUses int, ttlDays int) (ip1 *model.InviteCode, err error)
|
||||
funcGenerateOrigin string
|
||||
inspectFuncGenerate func(ctx context.Context, userID int, maxUses int, ttlDays int)
|
||||
afterGenerateCounter uint64
|
||||
beforeGenerateCounter uint64
|
||||
GenerateMock mInviteServiceMockGenerate
|
||||
|
||||
funcGetInfo func(ctx context.Context, code int64) (ip1 *model.InviteCode, err error)
|
||||
funcGetInfoOrigin string
|
||||
inspectFuncGetInfo func(ctx context.Context, code int64)
|
||||
afterGetInfoCounter uint64
|
||||
beforeGetInfoCounter uint64
|
||||
GetInfoMock mInviteServiceMockGetInfo
|
||||
}
|
||||
|
||||
// NewInviteServiceMock returns a mock for mm_service.InviteService
|
||||
func NewInviteServiceMock(t minimock.Tester) *InviteServiceMock {
|
||||
m := &InviteServiceMock{t: t}
|
||||
|
||||
if controller, ok := t.(minimock.MockController); ok {
|
||||
controller.RegisterMocker(m)
|
||||
}
|
||||
|
||||
m.GenerateMock = mInviteServiceMockGenerate{mock: m}
|
||||
m.GenerateMock.callArgs = []*InviteServiceMockGenerateParams{}
|
||||
|
||||
m.GetInfoMock = mInviteServiceMockGetInfo{mock: m}
|
||||
m.GetInfoMock.callArgs = []*InviteServiceMockGetInfoParams{}
|
||||
|
||||
t.Cleanup(m.MinimockFinish)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
type mInviteServiceMockGenerate struct {
|
||||
optional bool
|
||||
mock *InviteServiceMock
|
||||
defaultExpectation *InviteServiceMockGenerateExpectation
|
||||
expectations []*InviteServiceMockGenerateExpectation
|
||||
|
||||
callArgs []*InviteServiceMockGenerateParams
|
||||
mutex sync.RWMutex
|
||||
|
||||
expectedInvocations uint64
|
||||
expectedInvocationsOrigin string
|
||||
}
|
||||
|
||||
// InviteServiceMockGenerateExpectation specifies expectation struct of the InviteService.Generate
|
||||
type InviteServiceMockGenerateExpectation struct {
|
||||
mock *InviteServiceMock
|
||||
params *InviteServiceMockGenerateParams
|
||||
paramPtrs *InviteServiceMockGenerateParamPtrs
|
||||
expectationOrigins InviteServiceMockGenerateExpectationOrigins
|
||||
results *InviteServiceMockGenerateResults
|
||||
returnOrigin string
|
||||
Counter uint64
|
||||
}
|
||||
|
||||
// InviteServiceMockGenerateParams contains parameters of the InviteService.Generate
|
||||
type InviteServiceMockGenerateParams struct {
|
||||
ctx context.Context
|
||||
userID int
|
||||
maxUses int
|
||||
ttlDays int
|
||||
}
|
||||
|
||||
// InviteServiceMockGenerateParamPtrs contains pointers to parameters of the InviteService.Generate
|
||||
type InviteServiceMockGenerateParamPtrs struct {
|
||||
ctx *context.Context
|
||||
userID *int
|
||||
maxUses *int
|
||||
ttlDays *int
|
||||
}
|
||||
|
||||
// InviteServiceMockGenerateResults contains results of the InviteService.Generate
|
||||
type InviteServiceMockGenerateResults struct {
|
||||
ip1 *model.InviteCode
|
||||
err error
|
||||
}
|
||||
|
||||
// InviteServiceMockGenerateOrigins contains origins of expectations of the InviteService.Generate
|
||||
type InviteServiceMockGenerateExpectationOrigins struct {
|
||||
origin string
|
||||
originCtx string
|
||||
originUserID string
|
||||
originMaxUses string
|
||||
originTtlDays string
|
||||
}
|
||||
|
||||
// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
|
||||
// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
|
||||
// Optional() makes method check to work in '0 or more' mode.
|
||||
// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
|
||||
// catch the problems when the expected method call is totally skipped during test run.
|
||||
func (mmGenerate *mInviteServiceMockGenerate) Optional() *mInviteServiceMockGenerate {
|
||||
mmGenerate.optional = true
|
||||
return mmGenerate
|
||||
}
|
||||
|
||||
// Expect sets up expected params for InviteService.Generate
|
||||
func (mmGenerate *mInviteServiceMockGenerate) Expect(ctx context.Context, userID int, maxUses int, ttlDays int) *mInviteServiceMockGenerate {
|
||||
if mmGenerate.mock.funcGenerate != nil {
|
||||
mmGenerate.mock.t.Fatalf("InviteServiceMock.Generate mock is already set by Set")
|
||||
}
|
||||
|
||||
if mmGenerate.defaultExpectation == nil {
|
||||
mmGenerate.defaultExpectation = &InviteServiceMockGenerateExpectation{}
|
||||
}
|
||||
|
||||
if mmGenerate.defaultExpectation.paramPtrs != nil {
|
||||
mmGenerate.mock.t.Fatalf("InviteServiceMock.Generate mock is already set by ExpectParams functions")
|
||||
}
|
||||
|
||||
mmGenerate.defaultExpectation.params = &InviteServiceMockGenerateParams{ctx, userID, maxUses, ttlDays}
|
||||
mmGenerate.defaultExpectation.expectationOrigins.origin = minimock.CallerInfo(1)
|
||||
for _, e := range mmGenerate.expectations {
|
||||
if minimock.Equal(e.params, mmGenerate.defaultExpectation.params) {
|
||||
mmGenerate.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmGenerate.defaultExpectation.params)
|
||||
}
|
||||
}
|
||||
|
||||
return mmGenerate
|
||||
}
|
||||
|
||||
// ExpectCtxParam1 sets up expected param ctx for InviteService.Generate
|
||||
func (mmGenerate *mInviteServiceMockGenerate) ExpectCtxParam1(ctx context.Context) *mInviteServiceMockGenerate {
|
||||
if mmGenerate.mock.funcGenerate != nil {
|
||||
mmGenerate.mock.t.Fatalf("InviteServiceMock.Generate mock is already set by Set")
|
||||
}
|
||||
|
||||
if mmGenerate.defaultExpectation == nil {
|
||||
mmGenerate.defaultExpectation = &InviteServiceMockGenerateExpectation{}
|
||||
}
|
||||
|
||||
if mmGenerate.defaultExpectation.params != nil {
|
||||
mmGenerate.mock.t.Fatalf("InviteServiceMock.Generate mock is already set by Expect")
|
||||
}
|
||||
|
||||
if mmGenerate.defaultExpectation.paramPtrs == nil {
|
||||
mmGenerate.defaultExpectation.paramPtrs = &InviteServiceMockGenerateParamPtrs{}
|
||||
}
|
||||
mmGenerate.defaultExpectation.paramPtrs.ctx = &ctx
|
||||
mmGenerate.defaultExpectation.expectationOrigins.originCtx = minimock.CallerInfo(1)
|
||||
|
||||
return mmGenerate
|
||||
}
|
||||
|
||||
// ExpectUserIDParam2 sets up expected param userID for InviteService.Generate
|
||||
func (mmGenerate *mInviteServiceMockGenerate) ExpectUserIDParam2(userID int) *mInviteServiceMockGenerate {
|
||||
if mmGenerate.mock.funcGenerate != nil {
|
||||
mmGenerate.mock.t.Fatalf("InviteServiceMock.Generate mock is already set by Set")
|
||||
}
|
||||
|
||||
if mmGenerate.defaultExpectation == nil {
|
||||
mmGenerate.defaultExpectation = &InviteServiceMockGenerateExpectation{}
|
||||
}
|
||||
|
||||
if mmGenerate.defaultExpectation.params != nil {
|
||||
mmGenerate.mock.t.Fatalf("InviteServiceMock.Generate mock is already set by Expect")
|
||||
}
|
||||
|
||||
if mmGenerate.defaultExpectation.paramPtrs == nil {
|
||||
mmGenerate.defaultExpectation.paramPtrs = &InviteServiceMockGenerateParamPtrs{}
|
||||
}
|
||||
mmGenerate.defaultExpectation.paramPtrs.userID = &userID
|
||||
mmGenerate.defaultExpectation.expectationOrigins.originUserID = minimock.CallerInfo(1)
|
||||
|
||||
return mmGenerate
|
||||
}
|
||||
|
||||
// ExpectMaxUsesParam3 sets up expected param maxUses for InviteService.Generate
|
||||
func (mmGenerate *mInviteServiceMockGenerate) ExpectMaxUsesParam3(maxUses int) *mInviteServiceMockGenerate {
|
||||
if mmGenerate.mock.funcGenerate != nil {
|
||||
mmGenerate.mock.t.Fatalf("InviteServiceMock.Generate mock is already set by Set")
|
||||
}
|
||||
|
||||
if mmGenerate.defaultExpectation == nil {
|
||||
mmGenerate.defaultExpectation = &InviteServiceMockGenerateExpectation{}
|
||||
}
|
||||
|
||||
if mmGenerate.defaultExpectation.params != nil {
|
||||
mmGenerate.mock.t.Fatalf("InviteServiceMock.Generate mock is already set by Expect")
|
||||
}
|
||||
|
||||
if mmGenerate.defaultExpectation.paramPtrs == nil {
|
||||
mmGenerate.defaultExpectation.paramPtrs = &InviteServiceMockGenerateParamPtrs{}
|
||||
}
|
||||
mmGenerate.defaultExpectation.paramPtrs.maxUses = &maxUses
|
||||
mmGenerate.defaultExpectation.expectationOrigins.originMaxUses = minimock.CallerInfo(1)
|
||||
|
||||
return mmGenerate
|
||||
}
|
||||
|
||||
// ExpectTtlDaysParam4 sets up expected param ttlDays for InviteService.Generate
|
||||
func (mmGenerate *mInviteServiceMockGenerate) ExpectTtlDaysParam4(ttlDays int) *mInviteServiceMockGenerate {
|
||||
if mmGenerate.mock.funcGenerate != nil {
|
||||
mmGenerate.mock.t.Fatalf("InviteServiceMock.Generate mock is already set by Set")
|
||||
}
|
||||
|
||||
if mmGenerate.defaultExpectation == nil {
|
||||
mmGenerate.defaultExpectation = &InviteServiceMockGenerateExpectation{}
|
||||
}
|
||||
|
||||
if mmGenerate.defaultExpectation.params != nil {
|
||||
mmGenerate.mock.t.Fatalf("InviteServiceMock.Generate mock is already set by Expect")
|
||||
}
|
||||
|
||||
if mmGenerate.defaultExpectation.paramPtrs == nil {
|
||||
mmGenerate.defaultExpectation.paramPtrs = &InviteServiceMockGenerateParamPtrs{}
|
||||
}
|
||||
mmGenerate.defaultExpectation.paramPtrs.ttlDays = &ttlDays
|
||||
mmGenerate.defaultExpectation.expectationOrigins.originTtlDays = minimock.CallerInfo(1)
|
||||
|
||||
return mmGenerate
|
||||
}
|
||||
|
||||
// Inspect accepts an inspector function that has same arguments as the InviteService.Generate
|
||||
func (mmGenerate *mInviteServiceMockGenerate) Inspect(f func(ctx context.Context, userID int, maxUses int, ttlDays int)) *mInviteServiceMockGenerate {
|
||||
if mmGenerate.mock.inspectFuncGenerate != nil {
|
||||
mmGenerate.mock.t.Fatalf("Inspect function is already set for InviteServiceMock.Generate")
|
||||
}
|
||||
|
||||
mmGenerate.mock.inspectFuncGenerate = f
|
||||
|
||||
return mmGenerate
|
||||
}
|
||||
|
||||
// Return sets up results that will be returned by InviteService.Generate
|
||||
func (mmGenerate *mInviteServiceMockGenerate) Return(ip1 *model.InviteCode, err error) *InviteServiceMock {
|
||||
if mmGenerate.mock.funcGenerate != nil {
|
||||
mmGenerate.mock.t.Fatalf("InviteServiceMock.Generate mock is already set by Set")
|
||||
}
|
||||
|
||||
if mmGenerate.defaultExpectation == nil {
|
||||
mmGenerate.defaultExpectation = &InviteServiceMockGenerateExpectation{mock: mmGenerate.mock}
|
||||
}
|
||||
mmGenerate.defaultExpectation.results = &InviteServiceMockGenerateResults{ip1, err}
|
||||
mmGenerate.defaultExpectation.returnOrigin = minimock.CallerInfo(1)
|
||||
return mmGenerate.mock
|
||||
}
|
||||
|
||||
// Set uses given function f to mock the InviteService.Generate method
|
||||
func (mmGenerate *mInviteServiceMockGenerate) Set(f func(ctx context.Context, userID int, maxUses int, ttlDays int) (ip1 *model.InviteCode, err error)) *InviteServiceMock {
|
||||
if mmGenerate.defaultExpectation != nil {
|
||||
mmGenerate.mock.t.Fatalf("Default expectation is already set for the InviteService.Generate method")
|
||||
}
|
||||
|
||||
if len(mmGenerate.expectations) > 0 {
|
||||
mmGenerate.mock.t.Fatalf("Some expectations are already set for the InviteService.Generate method")
|
||||
}
|
||||
|
||||
mmGenerate.mock.funcGenerate = f
|
||||
mmGenerate.mock.funcGenerateOrigin = minimock.CallerInfo(1)
|
||||
return mmGenerate.mock
|
||||
}
|
||||
|
||||
// When sets expectation for the InviteService.Generate which will trigger the result defined by the following
|
||||
// Then helper
|
||||
func (mmGenerate *mInviteServiceMockGenerate) When(ctx context.Context, userID int, maxUses int, ttlDays int) *InviteServiceMockGenerateExpectation {
|
||||
if mmGenerate.mock.funcGenerate != nil {
|
||||
mmGenerate.mock.t.Fatalf("InviteServiceMock.Generate mock is already set by Set")
|
||||
}
|
||||
|
||||
expectation := &InviteServiceMockGenerateExpectation{
|
||||
mock: mmGenerate.mock,
|
||||
params: &InviteServiceMockGenerateParams{ctx, userID, maxUses, ttlDays},
|
||||
expectationOrigins: InviteServiceMockGenerateExpectationOrigins{origin: minimock.CallerInfo(1)},
|
||||
}
|
||||
mmGenerate.expectations = append(mmGenerate.expectations, expectation)
|
||||
return expectation
|
||||
}
|
||||
|
||||
// Then sets up InviteService.Generate return parameters for the expectation previously defined by the When method
|
||||
func (e *InviteServiceMockGenerateExpectation) Then(ip1 *model.InviteCode, err error) *InviteServiceMock {
|
||||
e.results = &InviteServiceMockGenerateResults{ip1, err}
|
||||
return e.mock
|
||||
}
|
||||
|
||||
// Times sets number of times InviteService.Generate should be invoked
|
||||
func (mmGenerate *mInviteServiceMockGenerate) Times(n uint64) *mInviteServiceMockGenerate {
|
||||
if n == 0 {
|
||||
mmGenerate.mock.t.Fatalf("Times of InviteServiceMock.Generate mock can not be zero")
|
||||
}
|
||||
mm_atomic.StoreUint64(&mmGenerate.expectedInvocations, n)
|
||||
mmGenerate.expectedInvocationsOrigin = minimock.CallerInfo(1)
|
||||
return mmGenerate
|
||||
}
|
||||
|
||||
func (mmGenerate *mInviteServiceMockGenerate) invocationsDone() bool {
|
||||
if len(mmGenerate.expectations) == 0 && mmGenerate.defaultExpectation == nil && mmGenerate.mock.funcGenerate == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
totalInvocations := mm_atomic.LoadUint64(&mmGenerate.mock.afterGenerateCounter)
|
||||
expectedInvocations := mm_atomic.LoadUint64(&mmGenerate.expectedInvocations)
|
||||
|
||||
return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
|
||||
}
|
||||
|
||||
// Generate implements mm_service.InviteService
|
||||
func (mmGenerate *InviteServiceMock) Generate(ctx context.Context, userID int, maxUses int, ttlDays int) (ip1 *model.InviteCode, err error) {
|
||||
mm_atomic.AddUint64(&mmGenerate.beforeGenerateCounter, 1)
|
||||
defer mm_atomic.AddUint64(&mmGenerate.afterGenerateCounter, 1)
|
||||
|
||||
mmGenerate.t.Helper()
|
||||
|
||||
if mmGenerate.inspectFuncGenerate != nil {
|
||||
mmGenerate.inspectFuncGenerate(ctx, userID, maxUses, ttlDays)
|
||||
}
|
||||
|
||||
mm_params := InviteServiceMockGenerateParams{ctx, userID, maxUses, ttlDays}
|
||||
|
||||
// Record call args
|
||||
mmGenerate.GenerateMock.mutex.Lock()
|
||||
mmGenerate.GenerateMock.callArgs = append(mmGenerate.GenerateMock.callArgs, &mm_params)
|
||||
mmGenerate.GenerateMock.mutex.Unlock()
|
||||
|
||||
for _, e := range mmGenerate.GenerateMock.expectations {
|
||||
if minimock.Equal(*e.params, mm_params) {
|
||||
mm_atomic.AddUint64(&e.Counter, 1)
|
||||
return e.results.ip1, e.results.err
|
||||
}
|
||||
}
|
||||
|
||||
if mmGenerate.GenerateMock.defaultExpectation != nil {
|
||||
mm_atomic.AddUint64(&mmGenerate.GenerateMock.defaultExpectation.Counter, 1)
|
||||
mm_want := mmGenerate.GenerateMock.defaultExpectation.params
|
||||
mm_want_ptrs := mmGenerate.GenerateMock.defaultExpectation.paramPtrs
|
||||
|
||||
mm_got := InviteServiceMockGenerateParams{ctx, userID, maxUses, ttlDays}
|
||||
|
||||
if mm_want_ptrs != nil {
|
||||
|
||||
if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
|
||||
mmGenerate.t.Errorf("InviteServiceMock.Generate got unexpected parameter ctx, expected at\n%s:\nwant: %#v\n got: %#v%s\n",
|
||||
mmGenerate.GenerateMock.defaultExpectation.expectationOrigins.originCtx, *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
|
||||
}
|
||||
|
||||
if mm_want_ptrs.userID != nil && !minimock.Equal(*mm_want_ptrs.userID, mm_got.userID) {
|
||||
mmGenerate.t.Errorf("InviteServiceMock.Generate got unexpected parameter userID, expected at\n%s:\nwant: %#v\n got: %#v%s\n",
|
||||
mmGenerate.GenerateMock.defaultExpectation.expectationOrigins.originUserID, *mm_want_ptrs.userID, mm_got.userID, minimock.Diff(*mm_want_ptrs.userID, mm_got.userID))
|
||||
}
|
||||
|
||||
if mm_want_ptrs.maxUses != nil && !minimock.Equal(*mm_want_ptrs.maxUses, mm_got.maxUses) {
|
||||
mmGenerate.t.Errorf("InviteServiceMock.Generate got unexpected parameter maxUses, expected at\n%s:\nwant: %#v\n got: %#v%s\n",
|
||||
mmGenerate.GenerateMock.defaultExpectation.expectationOrigins.originMaxUses, *mm_want_ptrs.maxUses, mm_got.maxUses, minimock.Diff(*mm_want_ptrs.maxUses, mm_got.maxUses))
|
||||
}
|
||||
|
||||
if mm_want_ptrs.ttlDays != nil && !minimock.Equal(*mm_want_ptrs.ttlDays, mm_got.ttlDays) {
|
||||
mmGenerate.t.Errorf("InviteServiceMock.Generate got unexpected parameter ttlDays, expected at\n%s:\nwant: %#v\n got: %#v%s\n",
|
||||
mmGenerate.GenerateMock.defaultExpectation.expectationOrigins.originTtlDays, *mm_want_ptrs.ttlDays, mm_got.ttlDays, minimock.Diff(*mm_want_ptrs.ttlDays, mm_got.ttlDays))
|
||||
}
|
||||
|
||||
} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
|
||||
mmGenerate.t.Errorf("InviteServiceMock.Generate got unexpected parameters, expected at\n%s:\nwant: %#v\n got: %#v%s\n",
|
||||
mmGenerate.GenerateMock.defaultExpectation.expectationOrigins.origin, *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
|
||||
}
|
||||
|
||||
mm_results := mmGenerate.GenerateMock.defaultExpectation.results
|
||||
if mm_results == nil {
|
||||
mmGenerate.t.Fatal("No results are set for the InviteServiceMock.Generate")
|
||||
}
|
||||
return (*mm_results).ip1, (*mm_results).err
|
||||
}
|
||||
if mmGenerate.funcGenerate != nil {
|
||||
return mmGenerate.funcGenerate(ctx, userID, maxUses, ttlDays)
|
||||
}
|
||||
mmGenerate.t.Fatalf("Unexpected call to InviteServiceMock.Generate. %v %v %v %v", ctx, userID, maxUses, ttlDays)
|
||||
return
|
||||
}
|
||||
|
||||
// GenerateAfterCounter returns a count of finished InviteServiceMock.Generate invocations
|
||||
func (mmGenerate *InviteServiceMock) GenerateAfterCounter() uint64 {
|
||||
return mm_atomic.LoadUint64(&mmGenerate.afterGenerateCounter)
|
||||
}
|
||||
|
||||
// GenerateBeforeCounter returns a count of InviteServiceMock.Generate invocations
|
||||
func (mmGenerate *InviteServiceMock) GenerateBeforeCounter() uint64 {
|
||||
return mm_atomic.LoadUint64(&mmGenerate.beforeGenerateCounter)
|
||||
}
|
||||
|
||||
// Calls returns a list of arguments used in each call to InviteServiceMock.Generate.
|
||||
// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
|
||||
func (mmGenerate *mInviteServiceMockGenerate) Calls() []*InviteServiceMockGenerateParams {
|
||||
mmGenerate.mutex.RLock()
|
||||
|
||||
argCopy := make([]*InviteServiceMockGenerateParams, len(mmGenerate.callArgs))
|
||||
copy(argCopy, mmGenerate.callArgs)
|
||||
|
||||
mmGenerate.mutex.RUnlock()
|
||||
|
||||
return argCopy
|
||||
}
|
||||
|
||||
// MinimockGenerateDone returns true if the count of the Generate invocations corresponds
|
||||
// the number of defined expectations
|
||||
func (m *InviteServiceMock) MinimockGenerateDone() bool {
|
||||
if m.GenerateMock.optional {
|
||||
// Optional methods provide '0 or more' call count restriction.
|
||||
return true
|
||||
}
|
||||
|
||||
for _, e := range m.GenerateMock.expectations {
|
||||
if mm_atomic.LoadUint64(&e.Counter) < 1 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return m.GenerateMock.invocationsDone()
|
||||
}
|
||||
|
||||
// MinimockGenerateInspect logs each unmet expectation
|
||||
func (m *InviteServiceMock) MinimockGenerateInspect() {
|
||||
for _, e := range m.GenerateMock.expectations {
|
||||
if mm_atomic.LoadUint64(&e.Counter) < 1 {
|
||||
m.t.Errorf("Expected call to InviteServiceMock.Generate at\n%s with params: %#v", e.expectationOrigins.origin, *e.params)
|
||||
}
|
||||
}
|
||||
|
||||
afterGenerateCounter := mm_atomic.LoadUint64(&m.afterGenerateCounter)
|
||||
// if default expectation was set then invocations count should be greater than zero
|
||||
if m.GenerateMock.defaultExpectation != nil && afterGenerateCounter < 1 {
|
||||
if m.GenerateMock.defaultExpectation.params == nil {
|
||||
m.t.Errorf("Expected call to InviteServiceMock.Generate at\n%s", m.GenerateMock.defaultExpectation.returnOrigin)
|
||||
} else {
|
||||
m.t.Errorf("Expected call to InviteServiceMock.Generate at\n%s with params: %#v", m.GenerateMock.defaultExpectation.expectationOrigins.origin, *m.GenerateMock.defaultExpectation.params)
|
||||
}
|
||||
}
|
||||
// if func was set then invocations count should be greater than zero
|
||||
if m.funcGenerate != nil && afterGenerateCounter < 1 {
|
||||
m.t.Errorf("Expected call to InviteServiceMock.Generate at\n%s", m.funcGenerateOrigin)
|
||||
}
|
||||
|
||||
if !m.GenerateMock.invocationsDone() && afterGenerateCounter > 0 {
|
||||
m.t.Errorf("Expected %d calls to InviteServiceMock.Generate at\n%s but found %d calls",
|
||||
mm_atomic.LoadUint64(&m.GenerateMock.expectedInvocations), m.GenerateMock.expectedInvocationsOrigin, afterGenerateCounter)
|
||||
}
|
||||
}
|
||||
|
||||
type mInviteServiceMockGetInfo struct {
|
||||
optional bool
|
||||
mock *InviteServiceMock
|
||||
defaultExpectation *InviteServiceMockGetInfoExpectation
|
||||
expectations []*InviteServiceMockGetInfoExpectation
|
||||
|
||||
callArgs []*InviteServiceMockGetInfoParams
|
||||
mutex sync.RWMutex
|
||||
|
||||
expectedInvocations uint64
|
||||
expectedInvocationsOrigin string
|
||||
}
|
||||
|
||||
// InviteServiceMockGetInfoExpectation specifies expectation struct of the InviteService.GetInfo
|
||||
type InviteServiceMockGetInfoExpectation struct {
|
||||
mock *InviteServiceMock
|
||||
params *InviteServiceMockGetInfoParams
|
||||
paramPtrs *InviteServiceMockGetInfoParamPtrs
|
||||
expectationOrigins InviteServiceMockGetInfoExpectationOrigins
|
||||
results *InviteServiceMockGetInfoResults
|
||||
returnOrigin string
|
||||
Counter uint64
|
||||
}
|
||||
|
||||
// InviteServiceMockGetInfoParams contains parameters of the InviteService.GetInfo
|
||||
type InviteServiceMockGetInfoParams struct {
|
||||
ctx context.Context
|
||||
code int64
|
||||
}
|
||||
|
||||
// InviteServiceMockGetInfoParamPtrs contains pointers to parameters of the InviteService.GetInfo
|
||||
type InviteServiceMockGetInfoParamPtrs struct {
|
||||
ctx *context.Context
|
||||
code *int64
|
||||
}
|
||||
|
||||
// InviteServiceMockGetInfoResults contains results of the InviteService.GetInfo
|
||||
type InviteServiceMockGetInfoResults struct {
|
||||
ip1 *model.InviteCode
|
||||
err error
|
||||
}
|
||||
|
||||
// InviteServiceMockGetInfoOrigins contains origins of expectations of the InviteService.GetInfo
|
||||
type InviteServiceMockGetInfoExpectationOrigins struct {
|
||||
origin string
|
||||
originCtx string
|
||||
originCode string
|
||||
}
|
||||
|
||||
// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
|
||||
// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
|
||||
// Optional() makes method check to work in '0 or more' mode.
|
||||
// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
|
||||
// catch the problems when the expected method call is totally skipped during test run.
|
||||
func (mmGetInfo *mInviteServiceMockGetInfo) Optional() *mInviteServiceMockGetInfo {
|
||||
mmGetInfo.optional = true
|
||||
return mmGetInfo
|
||||
}
|
||||
|
||||
// Expect sets up expected params for InviteService.GetInfo
|
||||
func (mmGetInfo *mInviteServiceMockGetInfo) Expect(ctx context.Context, code int64) *mInviteServiceMockGetInfo {
|
||||
if mmGetInfo.mock.funcGetInfo != nil {
|
||||
mmGetInfo.mock.t.Fatalf("InviteServiceMock.GetInfo mock is already set by Set")
|
||||
}
|
||||
|
||||
if mmGetInfo.defaultExpectation == nil {
|
||||
mmGetInfo.defaultExpectation = &InviteServiceMockGetInfoExpectation{}
|
||||
}
|
||||
|
||||
if mmGetInfo.defaultExpectation.paramPtrs != nil {
|
||||
mmGetInfo.mock.t.Fatalf("InviteServiceMock.GetInfo mock is already set by ExpectParams functions")
|
||||
}
|
||||
|
||||
mmGetInfo.defaultExpectation.params = &InviteServiceMockGetInfoParams{ctx, code}
|
||||
mmGetInfo.defaultExpectation.expectationOrigins.origin = minimock.CallerInfo(1)
|
||||
for _, e := range mmGetInfo.expectations {
|
||||
if minimock.Equal(e.params, mmGetInfo.defaultExpectation.params) {
|
||||
mmGetInfo.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmGetInfo.defaultExpectation.params)
|
||||
}
|
||||
}
|
||||
|
||||
return mmGetInfo
|
||||
}
|
||||
|
||||
// ExpectCtxParam1 sets up expected param ctx for InviteService.GetInfo
|
||||
func (mmGetInfo *mInviteServiceMockGetInfo) ExpectCtxParam1(ctx context.Context) *mInviteServiceMockGetInfo {
|
||||
if mmGetInfo.mock.funcGetInfo != nil {
|
||||
mmGetInfo.mock.t.Fatalf("InviteServiceMock.GetInfo mock is already set by Set")
|
||||
}
|
||||
|
||||
if mmGetInfo.defaultExpectation == nil {
|
||||
mmGetInfo.defaultExpectation = &InviteServiceMockGetInfoExpectation{}
|
||||
}
|
||||
|
||||
if mmGetInfo.defaultExpectation.params != nil {
|
||||
mmGetInfo.mock.t.Fatalf("InviteServiceMock.GetInfo mock is already set by Expect")
|
||||
}
|
||||
|
||||
if mmGetInfo.defaultExpectation.paramPtrs == nil {
|
||||
mmGetInfo.defaultExpectation.paramPtrs = &InviteServiceMockGetInfoParamPtrs{}
|
||||
}
|
||||
mmGetInfo.defaultExpectation.paramPtrs.ctx = &ctx
|
||||
mmGetInfo.defaultExpectation.expectationOrigins.originCtx = minimock.CallerInfo(1)
|
||||
|
||||
return mmGetInfo
|
||||
}
|
||||
|
||||
// ExpectCodeParam2 sets up expected param code for InviteService.GetInfo
|
||||
func (mmGetInfo *mInviteServiceMockGetInfo) ExpectCodeParam2(code int64) *mInviteServiceMockGetInfo {
|
||||
if mmGetInfo.mock.funcGetInfo != nil {
|
||||
mmGetInfo.mock.t.Fatalf("InviteServiceMock.GetInfo mock is already set by Set")
|
||||
}
|
||||
|
||||
if mmGetInfo.defaultExpectation == nil {
|
||||
mmGetInfo.defaultExpectation = &InviteServiceMockGetInfoExpectation{}
|
||||
}
|
||||
|
||||
if mmGetInfo.defaultExpectation.params != nil {
|
||||
mmGetInfo.mock.t.Fatalf("InviteServiceMock.GetInfo mock is already set by Expect")
|
||||
}
|
||||
|
||||
if mmGetInfo.defaultExpectation.paramPtrs == nil {
|
||||
mmGetInfo.defaultExpectation.paramPtrs = &InviteServiceMockGetInfoParamPtrs{}
|
||||
}
|
||||
mmGetInfo.defaultExpectation.paramPtrs.code = &code
|
||||
mmGetInfo.defaultExpectation.expectationOrigins.originCode = minimock.CallerInfo(1)
|
||||
|
||||
return mmGetInfo
|
||||
}
|
||||
|
||||
// Inspect accepts an inspector function that has same arguments as the InviteService.GetInfo
|
||||
func (mmGetInfo *mInviteServiceMockGetInfo) Inspect(f func(ctx context.Context, code int64)) *mInviteServiceMockGetInfo {
|
||||
if mmGetInfo.mock.inspectFuncGetInfo != nil {
|
||||
mmGetInfo.mock.t.Fatalf("Inspect function is already set for InviteServiceMock.GetInfo")
|
||||
}
|
||||
|
||||
mmGetInfo.mock.inspectFuncGetInfo = f
|
||||
|
||||
return mmGetInfo
|
||||
}
|
||||
|
||||
// Return sets up results that will be returned by InviteService.GetInfo
|
||||
func (mmGetInfo *mInviteServiceMockGetInfo) Return(ip1 *model.InviteCode, err error) *InviteServiceMock {
|
||||
if mmGetInfo.mock.funcGetInfo != nil {
|
||||
mmGetInfo.mock.t.Fatalf("InviteServiceMock.GetInfo mock is already set by Set")
|
||||
}
|
||||
|
||||
if mmGetInfo.defaultExpectation == nil {
|
||||
mmGetInfo.defaultExpectation = &InviteServiceMockGetInfoExpectation{mock: mmGetInfo.mock}
|
||||
}
|
||||
mmGetInfo.defaultExpectation.results = &InviteServiceMockGetInfoResults{ip1, err}
|
||||
mmGetInfo.defaultExpectation.returnOrigin = minimock.CallerInfo(1)
|
||||
return mmGetInfo.mock
|
||||
}
|
||||
|
||||
// Set uses given function f to mock the InviteService.GetInfo method
|
||||
func (mmGetInfo *mInviteServiceMockGetInfo) Set(f func(ctx context.Context, code int64) (ip1 *model.InviteCode, err error)) *InviteServiceMock {
|
||||
if mmGetInfo.defaultExpectation != nil {
|
||||
mmGetInfo.mock.t.Fatalf("Default expectation is already set for the InviteService.GetInfo method")
|
||||
}
|
||||
|
||||
if len(mmGetInfo.expectations) > 0 {
|
||||
mmGetInfo.mock.t.Fatalf("Some expectations are already set for the InviteService.GetInfo method")
|
||||
}
|
||||
|
||||
mmGetInfo.mock.funcGetInfo = f
|
||||
mmGetInfo.mock.funcGetInfoOrigin = minimock.CallerInfo(1)
|
||||
return mmGetInfo.mock
|
||||
}
|
||||
|
||||
// When sets expectation for the InviteService.GetInfo which will trigger the result defined by the following
|
||||
// Then helper
|
||||
func (mmGetInfo *mInviteServiceMockGetInfo) When(ctx context.Context, code int64) *InviteServiceMockGetInfoExpectation {
|
||||
if mmGetInfo.mock.funcGetInfo != nil {
|
||||
mmGetInfo.mock.t.Fatalf("InviteServiceMock.GetInfo mock is already set by Set")
|
||||
}
|
||||
|
||||
expectation := &InviteServiceMockGetInfoExpectation{
|
||||
mock: mmGetInfo.mock,
|
||||
params: &InviteServiceMockGetInfoParams{ctx, code},
|
||||
expectationOrigins: InviteServiceMockGetInfoExpectationOrigins{origin: minimock.CallerInfo(1)},
|
||||
}
|
||||
mmGetInfo.expectations = append(mmGetInfo.expectations, expectation)
|
||||
return expectation
|
||||
}
|
||||
|
||||
// Then sets up InviteService.GetInfo return parameters for the expectation previously defined by the When method
|
||||
func (e *InviteServiceMockGetInfoExpectation) Then(ip1 *model.InviteCode, err error) *InviteServiceMock {
|
||||
e.results = &InviteServiceMockGetInfoResults{ip1, err}
|
||||
return e.mock
|
||||
}
|
||||
|
||||
// Times sets number of times InviteService.GetInfo should be invoked
|
||||
func (mmGetInfo *mInviteServiceMockGetInfo) Times(n uint64) *mInviteServiceMockGetInfo {
|
||||
if n == 0 {
|
||||
mmGetInfo.mock.t.Fatalf("Times of InviteServiceMock.GetInfo mock can not be zero")
|
||||
}
|
||||
mm_atomic.StoreUint64(&mmGetInfo.expectedInvocations, n)
|
||||
mmGetInfo.expectedInvocationsOrigin = minimock.CallerInfo(1)
|
||||
return mmGetInfo
|
||||
}
|
||||
|
||||
func (mmGetInfo *mInviteServiceMockGetInfo) invocationsDone() bool {
|
||||
if len(mmGetInfo.expectations) == 0 && mmGetInfo.defaultExpectation == nil && mmGetInfo.mock.funcGetInfo == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
totalInvocations := mm_atomic.LoadUint64(&mmGetInfo.mock.afterGetInfoCounter)
|
||||
expectedInvocations := mm_atomic.LoadUint64(&mmGetInfo.expectedInvocations)
|
||||
|
||||
return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
|
||||
}
|
||||
|
||||
// GetInfo implements mm_service.InviteService
|
||||
func (mmGetInfo *InviteServiceMock) GetInfo(ctx context.Context, code int64) (ip1 *model.InviteCode, err error) {
|
||||
mm_atomic.AddUint64(&mmGetInfo.beforeGetInfoCounter, 1)
|
||||
defer mm_atomic.AddUint64(&mmGetInfo.afterGetInfoCounter, 1)
|
||||
|
||||
mmGetInfo.t.Helper()
|
||||
|
||||
if mmGetInfo.inspectFuncGetInfo != nil {
|
||||
mmGetInfo.inspectFuncGetInfo(ctx, code)
|
||||
}
|
||||
|
||||
mm_params := InviteServiceMockGetInfoParams{ctx, code}
|
||||
|
||||
// Record call args
|
||||
mmGetInfo.GetInfoMock.mutex.Lock()
|
||||
mmGetInfo.GetInfoMock.callArgs = append(mmGetInfo.GetInfoMock.callArgs, &mm_params)
|
||||
mmGetInfo.GetInfoMock.mutex.Unlock()
|
||||
|
||||
for _, e := range mmGetInfo.GetInfoMock.expectations {
|
||||
if minimock.Equal(*e.params, mm_params) {
|
||||
mm_atomic.AddUint64(&e.Counter, 1)
|
||||
return e.results.ip1, e.results.err
|
||||
}
|
||||
}
|
||||
|
||||
if mmGetInfo.GetInfoMock.defaultExpectation != nil {
|
||||
mm_atomic.AddUint64(&mmGetInfo.GetInfoMock.defaultExpectation.Counter, 1)
|
||||
mm_want := mmGetInfo.GetInfoMock.defaultExpectation.params
|
||||
mm_want_ptrs := mmGetInfo.GetInfoMock.defaultExpectation.paramPtrs
|
||||
|
||||
mm_got := InviteServiceMockGetInfoParams{ctx, code}
|
||||
|
||||
if mm_want_ptrs != nil {
|
||||
|
||||
if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
|
||||
mmGetInfo.t.Errorf("InviteServiceMock.GetInfo got unexpected parameter ctx, expected at\n%s:\nwant: %#v\n got: %#v%s\n",
|
||||
mmGetInfo.GetInfoMock.defaultExpectation.expectationOrigins.originCtx, *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
|
||||
}
|
||||
|
||||
if mm_want_ptrs.code != nil && !minimock.Equal(*mm_want_ptrs.code, mm_got.code) {
|
||||
mmGetInfo.t.Errorf("InviteServiceMock.GetInfo got unexpected parameter code, expected at\n%s:\nwant: %#v\n got: %#v%s\n",
|
||||
mmGetInfo.GetInfoMock.defaultExpectation.expectationOrigins.originCode, *mm_want_ptrs.code, mm_got.code, minimock.Diff(*mm_want_ptrs.code, mm_got.code))
|
||||
}
|
||||
|
||||
} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
|
||||
mmGetInfo.t.Errorf("InviteServiceMock.GetInfo got unexpected parameters, expected at\n%s:\nwant: %#v\n got: %#v%s\n",
|
||||
mmGetInfo.GetInfoMock.defaultExpectation.expectationOrigins.origin, *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
|
||||
}
|
||||
|
||||
mm_results := mmGetInfo.GetInfoMock.defaultExpectation.results
|
||||
if mm_results == nil {
|
||||
mmGetInfo.t.Fatal("No results are set for the InviteServiceMock.GetInfo")
|
||||
}
|
||||
return (*mm_results).ip1, (*mm_results).err
|
||||
}
|
||||
if mmGetInfo.funcGetInfo != nil {
|
||||
return mmGetInfo.funcGetInfo(ctx, code)
|
||||
}
|
||||
mmGetInfo.t.Fatalf("Unexpected call to InviteServiceMock.GetInfo. %v %v", ctx, code)
|
||||
return
|
||||
}
|
||||
|
||||
// GetInfoAfterCounter returns a count of finished InviteServiceMock.GetInfo invocations
|
||||
func (mmGetInfo *InviteServiceMock) GetInfoAfterCounter() uint64 {
|
||||
return mm_atomic.LoadUint64(&mmGetInfo.afterGetInfoCounter)
|
||||
}
|
||||
|
||||
// GetInfoBeforeCounter returns a count of InviteServiceMock.GetInfo invocations
|
||||
func (mmGetInfo *InviteServiceMock) GetInfoBeforeCounter() uint64 {
|
||||
return mm_atomic.LoadUint64(&mmGetInfo.beforeGetInfoCounter)
|
||||
}
|
||||
|
||||
// Calls returns a list of arguments used in each call to InviteServiceMock.GetInfo.
|
||||
// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
|
||||
func (mmGetInfo *mInviteServiceMockGetInfo) Calls() []*InviteServiceMockGetInfoParams {
|
||||
mmGetInfo.mutex.RLock()
|
||||
|
||||
argCopy := make([]*InviteServiceMockGetInfoParams, len(mmGetInfo.callArgs))
|
||||
copy(argCopy, mmGetInfo.callArgs)
|
||||
|
||||
mmGetInfo.mutex.RUnlock()
|
||||
|
||||
return argCopy
|
||||
}
|
||||
|
||||
// MinimockGetInfoDone returns true if the count of the GetInfo invocations corresponds
|
||||
// the number of defined expectations
|
||||
func (m *InviteServiceMock) MinimockGetInfoDone() bool {
|
||||
if m.GetInfoMock.optional {
|
||||
// Optional methods provide '0 or more' call count restriction.
|
||||
return true
|
||||
}
|
||||
|
||||
for _, e := range m.GetInfoMock.expectations {
|
||||
if mm_atomic.LoadUint64(&e.Counter) < 1 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return m.GetInfoMock.invocationsDone()
|
||||
}
|
||||
|
||||
// MinimockGetInfoInspect logs each unmet expectation
|
||||
func (m *InviteServiceMock) MinimockGetInfoInspect() {
|
||||
for _, e := range m.GetInfoMock.expectations {
|
||||
if mm_atomic.LoadUint64(&e.Counter) < 1 {
|
||||
m.t.Errorf("Expected call to InviteServiceMock.GetInfo at\n%s with params: %#v", e.expectationOrigins.origin, *e.params)
|
||||
}
|
||||
}
|
||||
|
||||
afterGetInfoCounter := mm_atomic.LoadUint64(&m.afterGetInfoCounter)
|
||||
// if default expectation was set then invocations count should be greater than zero
|
||||
if m.GetInfoMock.defaultExpectation != nil && afterGetInfoCounter < 1 {
|
||||
if m.GetInfoMock.defaultExpectation.params == nil {
|
||||
m.t.Errorf("Expected call to InviteServiceMock.GetInfo at\n%s", m.GetInfoMock.defaultExpectation.returnOrigin)
|
||||
} else {
|
||||
m.t.Errorf("Expected call to InviteServiceMock.GetInfo at\n%s with params: %#v", m.GetInfoMock.defaultExpectation.expectationOrigins.origin, *m.GetInfoMock.defaultExpectation.params)
|
||||
}
|
||||
}
|
||||
// if func was set then invocations count should be greater than zero
|
||||
if m.funcGetInfo != nil && afterGetInfoCounter < 1 {
|
||||
m.t.Errorf("Expected call to InviteServiceMock.GetInfo at\n%s", m.funcGetInfoOrigin)
|
||||
}
|
||||
|
||||
if !m.GetInfoMock.invocationsDone() && afterGetInfoCounter > 0 {
|
||||
m.t.Errorf("Expected %d calls to InviteServiceMock.GetInfo at\n%s but found %d calls",
|
||||
mm_atomic.LoadUint64(&m.GetInfoMock.expectedInvocations), m.GetInfoMock.expectedInvocationsOrigin, afterGetInfoCounter)
|
||||
}
|
||||
}
|
||||
|
||||
// MinimockFinish checks that all mocked methods have been called the expected number of times
|
||||
func (m *InviteServiceMock) MinimockFinish() {
|
||||
m.finishOnce.Do(func() {
|
||||
if !m.minimockDone() {
|
||||
m.MinimockGenerateInspect()
|
||||
|
||||
m.MinimockGetInfoInspect()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// MinimockWait waits for all mocked methods to be called the expected number of times
|
||||
func (m *InviteServiceMock) MinimockWait(timeout mm_time.Duration) {
|
||||
timeoutCh := mm_time.After(timeout)
|
||||
for {
|
||||
if m.minimockDone() {
|
||||
return
|
||||
}
|
||||
select {
|
||||
case <-timeoutCh:
|
||||
m.MinimockFinish()
|
||||
return
|
||||
case <-mm_time.After(10 * mm_time.Millisecond):
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *InviteServiceMock) minimockDone() bool {
|
||||
done := true
|
||||
return done &&
|
||||
m.MinimockGenerateDone() &&
|
||||
m.MinimockGetInfoDone()
|
||||
}
|
||||
2647
internal/mocks/request_repository_mock.go
Normal file
2647
internal/mocks/request_repository_mock.go
Normal file
File diff suppressed because it is too large
Load Diff
1581
internal/mocks/request_service_mock.go
Normal file
1581
internal/mocks/request_service_mock.go
Normal file
File diff suppressed because it is too large
Load Diff
1839
internal/mocks/session_repository_mock.go
Normal file
1839
internal/mocks/session_repository_mock.go
Normal file
File diff suppressed because it is too large
Load Diff
1160
internal/mocks/supplier_repository_mock.go
Normal file
1160
internal/mocks/supplier_repository_mock.go
Normal file
File diff suppressed because it is too large
Load Diff
418
internal/mocks/supplier_service_mock.go
Normal file
418
internal/mocks/supplier_service_mock.go
Normal file
@@ -0,0 +1,418 @@
|
||||
// Code generated by http://github.com/gojuno/minimock (v3.4.7). DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
//go:generate minimock -i smart-search-back/internal/service.SupplierService -o supplier_service_mock.go -n SupplierServiceMock -p mocks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
mm_atomic "sync/atomic"
|
||||
mm_time "time"
|
||||
|
||||
"github.com/gojuno/minimock/v3"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// SupplierServiceMock implements mm_service.SupplierService
|
||||
type SupplierServiceMock struct {
|
||||
t minimock.Tester
|
||||
finishOnce sync.Once
|
||||
|
||||
funcExportExcel func(ctx context.Context, requestID uuid.UUID) (ba1 []byte, err error)
|
||||
funcExportExcelOrigin string
|
||||
inspectFuncExportExcel func(ctx context.Context, requestID uuid.UUID)
|
||||
afterExportExcelCounter uint64
|
||||
beforeExportExcelCounter uint64
|
||||
ExportExcelMock mSupplierServiceMockExportExcel
|
||||
}
|
||||
|
||||
// NewSupplierServiceMock returns a mock for mm_service.SupplierService
|
||||
func NewSupplierServiceMock(t minimock.Tester) *SupplierServiceMock {
|
||||
m := &SupplierServiceMock{t: t}
|
||||
|
||||
if controller, ok := t.(minimock.MockController); ok {
|
||||
controller.RegisterMocker(m)
|
||||
}
|
||||
|
||||
m.ExportExcelMock = mSupplierServiceMockExportExcel{mock: m}
|
||||
m.ExportExcelMock.callArgs = []*SupplierServiceMockExportExcelParams{}
|
||||
|
||||
t.Cleanup(m.MinimockFinish)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
type mSupplierServiceMockExportExcel struct {
|
||||
optional bool
|
||||
mock *SupplierServiceMock
|
||||
defaultExpectation *SupplierServiceMockExportExcelExpectation
|
||||
expectations []*SupplierServiceMockExportExcelExpectation
|
||||
|
||||
callArgs []*SupplierServiceMockExportExcelParams
|
||||
mutex sync.RWMutex
|
||||
|
||||
expectedInvocations uint64
|
||||
expectedInvocationsOrigin string
|
||||
}
|
||||
|
||||
// SupplierServiceMockExportExcelExpectation specifies expectation struct of the SupplierService.ExportExcel
|
||||
type SupplierServiceMockExportExcelExpectation struct {
|
||||
mock *SupplierServiceMock
|
||||
params *SupplierServiceMockExportExcelParams
|
||||
paramPtrs *SupplierServiceMockExportExcelParamPtrs
|
||||
expectationOrigins SupplierServiceMockExportExcelExpectationOrigins
|
||||
results *SupplierServiceMockExportExcelResults
|
||||
returnOrigin string
|
||||
Counter uint64
|
||||
}
|
||||
|
||||
// SupplierServiceMockExportExcelParams contains parameters of the SupplierService.ExportExcel
|
||||
type SupplierServiceMockExportExcelParams struct {
|
||||
ctx context.Context
|
||||
requestID uuid.UUID
|
||||
}
|
||||
|
||||
// SupplierServiceMockExportExcelParamPtrs contains pointers to parameters of the SupplierService.ExportExcel
|
||||
type SupplierServiceMockExportExcelParamPtrs struct {
|
||||
ctx *context.Context
|
||||
requestID *uuid.UUID
|
||||
}
|
||||
|
||||
// SupplierServiceMockExportExcelResults contains results of the SupplierService.ExportExcel
|
||||
type SupplierServiceMockExportExcelResults struct {
|
||||
ba1 []byte
|
||||
err error
|
||||
}
|
||||
|
||||
// SupplierServiceMockExportExcelOrigins contains origins of expectations of the SupplierService.ExportExcel
|
||||
type SupplierServiceMockExportExcelExpectationOrigins struct {
|
||||
origin string
|
||||
originCtx string
|
||||
originRequestID string
|
||||
}
|
||||
|
||||
// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
|
||||
// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
|
||||
// Optional() makes method check to work in '0 or more' mode.
|
||||
// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
|
||||
// catch the problems when the expected method call is totally skipped during test run.
|
||||
func (mmExportExcel *mSupplierServiceMockExportExcel) Optional() *mSupplierServiceMockExportExcel {
|
||||
mmExportExcel.optional = true
|
||||
return mmExportExcel
|
||||
}
|
||||
|
||||
// Expect sets up expected params for SupplierService.ExportExcel
|
||||
func (mmExportExcel *mSupplierServiceMockExportExcel) Expect(ctx context.Context, requestID uuid.UUID) *mSupplierServiceMockExportExcel {
|
||||
if mmExportExcel.mock.funcExportExcel != nil {
|
||||
mmExportExcel.mock.t.Fatalf("SupplierServiceMock.ExportExcel mock is already set by Set")
|
||||
}
|
||||
|
||||
if mmExportExcel.defaultExpectation == nil {
|
||||
mmExportExcel.defaultExpectation = &SupplierServiceMockExportExcelExpectation{}
|
||||
}
|
||||
|
||||
if mmExportExcel.defaultExpectation.paramPtrs != nil {
|
||||
mmExportExcel.mock.t.Fatalf("SupplierServiceMock.ExportExcel mock is already set by ExpectParams functions")
|
||||
}
|
||||
|
||||
mmExportExcel.defaultExpectation.params = &SupplierServiceMockExportExcelParams{ctx, requestID}
|
||||
mmExportExcel.defaultExpectation.expectationOrigins.origin = minimock.CallerInfo(1)
|
||||
for _, e := range mmExportExcel.expectations {
|
||||
if minimock.Equal(e.params, mmExportExcel.defaultExpectation.params) {
|
||||
mmExportExcel.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmExportExcel.defaultExpectation.params)
|
||||
}
|
||||
}
|
||||
|
||||
return mmExportExcel
|
||||
}
|
||||
|
||||
// ExpectCtxParam1 sets up expected param ctx for SupplierService.ExportExcel
|
||||
func (mmExportExcel *mSupplierServiceMockExportExcel) ExpectCtxParam1(ctx context.Context) *mSupplierServiceMockExportExcel {
|
||||
if mmExportExcel.mock.funcExportExcel != nil {
|
||||
mmExportExcel.mock.t.Fatalf("SupplierServiceMock.ExportExcel mock is already set by Set")
|
||||
}
|
||||
|
||||
if mmExportExcel.defaultExpectation == nil {
|
||||
mmExportExcel.defaultExpectation = &SupplierServiceMockExportExcelExpectation{}
|
||||
}
|
||||
|
||||
if mmExportExcel.defaultExpectation.params != nil {
|
||||
mmExportExcel.mock.t.Fatalf("SupplierServiceMock.ExportExcel mock is already set by Expect")
|
||||
}
|
||||
|
||||
if mmExportExcel.defaultExpectation.paramPtrs == nil {
|
||||
mmExportExcel.defaultExpectation.paramPtrs = &SupplierServiceMockExportExcelParamPtrs{}
|
||||
}
|
||||
mmExportExcel.defaultExpectation.paramPtrs.ctx = &ctx
|
||||
mmExportExcel.defaultExpectation.expectationOrigins.originCtx = minimock.CallerInfo(1)
|
||||
|
||||
return mmExportExcel
|
||||
}
|
||||
|
||||
// ExpectRequestIDParam2 sets up expected param requestID for SupplierService.ExportExcel
|
||||
func (mmExportExcel *mSupplierServiceMockExportExcel) ExpectRequestIDParam2(requestID uuid.UUID) *mSupplierServiceMockExportExcel {
|
||||
if mmExportExcel.mock.funcExportExcel != nil {
|
||||
mmExportExcel.mock.t.Fatalf("SupplierServiceMock.ExportExcel mock is already set by Set")
|
||||
}
|
||||
|
||||
if mmExportExcel.defaultExpectation == nil {
|
||||
mmExportExcel.defaultExpectation = &SupplierServiceMockExportExcelExpectation{}
|
||||
}
|
||||
|
||||
if mmExportExcel.defaultExpectation.params != nil {
|
||||
mmExportExcel.mock.t.Fatalf("SupplierServiceMock.ExportExcel mock is already set by Expect")
|
||||
}
|
||||
|
||||
if mmExportExcel.defaultExpectation.paramPtrs == nil {
|
||||
mmExportExcel.defaultExpectation.paramPtrs = &SupplierServiceMockExportExcelParamPtrs{}
|
||||
}
|
||||
mmExportExcel.defaultExpectation.paramPtrs.requestID = &requestID
|
||||
mmExportExcel.defaultExpectation.expectationOrigins.originRequestID = minimock.CallerInfo(1)
|
||||
|
||||
return mmExportExcel
|
||||
}
|
||||
|
||||
// Inspect accepts an inspector function that has same arguments as the SupplierService.ExportExcel
|
||||
func (mmExportExcel *mSupplierServiceMockExportExcel) Inspect(f func(ctx context.Context, requestID uuid.UUID)) *mSupplierServiceMockExportExcel {
|
||||
if mmExportExcel.mock.inspectFuncExportExcel != nil {
|
||||
mmExportExcel.mock.t.Fatalf("Inspect function is already set for SupplierServiceMock.ExportExcel")
|
||||
}
|
||||
|
||||
mmExportExcel.mock.inspectFuncExportExcel = f
|
||||
|
||||
return mmExportExcel
|
||||
}
|
||||
|
||||
// Return sets up results that will be returned by SupplierService.ExportExcel
|
||||
func (mmExportExcel *mSupplierServiceMockExportExcel) Return(ba1 []byte, err error) *SupplierServiceMock {
|
||||
if mmExportExcel.mock.funcExportExcel != nil {
|
||||
mmExportExcel.mock.t.Fatalf("SupplierServiceMock.ExportExcel mock is already set by Set")
|
||||
}
|
||||
|
||||
if mmExportExcel.defaultExpectation == nil {
|
||||
mmExportExcel.defaultExpectation = &SupplierServiceMockExportExcelExpectation{mock: mmExportExcel.mock}
|
||||
}
|
||||
mmExportExcel.defaultExpectation.results = &SupplierServiceMockExportExcelResults{ba1, err}
|
||||
mmExportExcel.defaultExpectation.returnOrigin = minimock.CallerInfo(1)
|
||||
return mmExportExcel.mock
|
||||
}
|
||||
|
||||
// Set uses given function f to mock the SupplierService.ExportExcel method
|
||||
func (mmExportExcel *mSupplierServiceMockExportExcel) Set(f func(ctx context.Context, requestID uuid.UUID) (ba1 []byte, err error)) *SupplierServiceMock {
|
||||
if mmExportExcel.defaultExpectation != nil {
|
||||
mmExportExcel.mock.t.Fatalf("Default expectation is already set for the SupplierService.ExportExcel method")
|
||||
}
|
||||
|
||||
if len(mmExportExcel.expectations) > 0 {
|
||||
mmExportExcel.mock.t.Fatalf("Some expectations are already set for the SupplierService.ExportExcel method")
|
||||
}
|
||||
|
||||
mmExportExcel.mock.funcExportExcel = f
|
||||
mmExportExcel.mock.funcExportExcelOrigin = minimock.CallerInfo(1)
|
||||
return mmExportExcel.mock
|
||||
}
|
||||
|
||||
// When sets expectation for the SupplierService.ExportExcel which will trigger the result defined by the following
|
||||
// Then helper
|
||||
func (mmExportExcel *mSupplierServiceMockExportExcel) When(ctx context.Context, requestID uuid.UUID) *SupplierServiceMockExportExcelExpectation {
|
||||
if mmExportExcel.mock.funcExportExcel != nil {
|
||||
mmExportExcel.mock.t.Fatalf("SupplierServiceMock.ExportExcel mock is already set by Set")
|
||||
}
|
||||
|
||||
expectation := &SupplierServiceMockExportExcelExpectation{
|
||||
mock: mmExportExcel.mock,
|
||||
params: &SupplierServiceMockExportExcelParams{ctx, requestID},
|
||||
expectationOrigins: SupplierServiceMockExportExcelExpectationOrigins{origin: minimock.CallerInfo(1)},
|
||||
}
|
||||
mmExportExcel.expectations = append(mmExportExcel.expectations, expectation)
|
||||
return expectation
|
||||
}
|
||||
|
||||
// Then sets up SupplierService.ExportExcel return parameters for the expectation previously defined by the When method
|
||||
func (e *SupplierServiceMockExportExcelExpectation) Then(ba1 []byte, err error) *SupplierServiceMock {
|
||||
e.results = &SupplierServiceMockExportExcelResults{ba1, err}
|
||||
return e.mock
|
||||
}
|
||||
|
||||
// Times sets number of times SupplierService.ExportExcel should be invoked
|
||||
func (mmExportExcel *mSupplierServiceMockExportExcel) Times(n uint64) *mSupplierServiceMockExportExcel {
|
||||
if n == 0 {
|
||||
mmExportExcel.mock.t.Fatalf("Times of SupplierServiceMock.ExportExcel mock can not be zero")
|
||||
}
|
||||
mm_atomic.StoreUint64(&mmExportExcel.expectedInvocations, n)
|
||||
mmExportExcel.expectedInvocationsOrigin = minimock.CallerInfo(1)
|
||||
return mmExportExcel
|
||||
}
|
||||
|
||||
func (mmExportExcel *mSupplierServiceMockExportExcel) invocationsDone() bool {
|
||||
if len(mmExportExcel.expectations) == 0 && mmExportExcel.defaultExpectation == nil && mmExportExcel.mock.funcExportExcel == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
totalInvocations := mm_atomic.LoadUint64(&mmExportExcel.mock.afterExportExcelCounter)
|
||||
expectedInvocations := mm_atomic.LoadUint64(&mmExportExcel.expectedInvocations)
|
||||
|
||||
return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
|
||||
}
|
||||
|
||||
// ExportExcel implements mm_service.SupplierService
|
||||
func (mmExportExcel *SupplierServiceMock) ExportExcel(ctx context.Context, requestID uuid.UUID) (ba1 []byte, err error) {
|
||||
mm_atomic.AddUint64(&mmExportExcel.beforeExportExcelCounter, 1)
|
||||
defer mm_atomic.AddUint64(&mmExportExcel.afterExportExcelCounter, 1)
|
||||
|
||||
mmExportExcel.t.Helper()
|
||||
|
||||
if mmExportExcel.inspectFuncExportExcel != nil {
|
||||
mmExportExcel.inspectFuncExportExcel(ctx, requestID)
|
||||
}
|
||||
|
||||
mm_params := SupplierServiceMockExportExcelParams{ctx, requestID}
|
||||
|
||||
// Record call args
|
||||
mmExportExcel.ExportExcelMock.mutex.Lock()
|
||||
mmExportExcel.ExportExcelMock.callArgs = append(mmExportExcel.ExportExcelMock.callArgs, &mm_params)
|
||||
mmExportExcel.ExportExcelMock.mutex.Unlock()
|
||||
|
||||
for _, e := range mmExportExcel.ExportExcelMock.expectations {
|
||||
if minimock.Equal(*e.params, mm_params) {
|
||||
mm_atomic.AddUint64(&e.Counter, 1)
|
||||
return e.results.ba1, e.results.err
|
||||
}
|
||||
}
|
||||
|
||||
if mmExportExcel.ExportExcelMock.defaultExpectation != nil {
|
||||
mm_atomic.AddUint64(&mmExportExcel.ExportExcelMock.defaultExpectation.Counter, 1)
|
||||
mm_want := mmExportExcel.ExportExcelMock.defaultExpectation.params
|
||||
mm_want_ptrs := mmExportExcel.ExportExcelMock.defaultExpectation.paramPtrs
|
||||
|
||||
mm_got := SupplierServiceMockExportExcelParams{ctx, requestID}
|
||||
|
||||
if mm_want_ptrs != nil {
|
||||
|
||||
if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
|
||||
mmExportExcel.t.Errorf("SupplierServiceMock.ExportExcel got unexpected parameter ctx, expected at\n%s:\nwant: %#v\n got: %#v%s\n",
|
||||
mmExportExcel.ExportExcelMock.defaultExpectation.expectationOrigins.originCtx, *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
|
||||
}
|
||||
|
||||
if mm_want_ptrs.requestID != nil && !minimock.Equal(*mm_want_ptrs.requestID, mm_got.requestID) {
|
||||
mmExportExcel.t.Errorf("SupplierServiceMock.ExportExcel got unexpected parameter requestID, expected at\n%s:\nwant: %#v\n got: %#v%s\n",
|
||||
mmExportExcel.ExportExcelMock.defaultExpectation.expectationOrigins.originRequestID, *mm_want_ptrs.requestID, mm_got.requestID, minimock.Diff(*mm_want_ptrs.requestID, mm_got.requestID))
|
||||
}
|
||||
|
||||
} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
|
||||
mmExportExcel.t.Errorf("SupplierServiceMock.ExportExcel got unexpected parameters, expected at\n%s:\nwant: %#v\n got: %#v%s\n",
|
||||
mmExportExcel.ExportExcelMock.defaultExpectation.expectationOrigins.origin, *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
|
||||
}
|
||||
|
||||
mm_results := mmExportExcel.ExportExcelMock.defaultExpectation.results
|
||||
if mm_results == nil {
|
||||
mmExportExcel.t.Fatal("No results are set for the SupplierServiceMock.ExportExcel")
|
||||
}
|
||||
return (*mm_results).ba1, (*mm_results).err
|
||||
}
|
||||
if mmExportExcel.funcExportExcel != nil {
|
||||
return mmExportExcel.funcExportExcel(ctx, requestID)
|
||||
}
|
||||
mmExportExcel.t.Fatalf("Unexpected call to SupplierServiceMock.ExportExcel. %v %v", ctx, requestID)
|
||||
return
|
||||
}
|
||||
|
||||
// ExportExcelAfterCounter returns a count of finished SupplierServiceMock.ExportExcel invocations
|
||||
func (mmExportExcel *SupplierServiceMock) ExportExcelAfterCounter() uint64 {
|
||||
return mm_atomic.LoadUint64(&mmExportExcel.afterExportExcelCounter)
|
||||
}
|
||||
|
||||
// ExportExcelBeforeCounter returns a count of SupplierServiceMock.ExportExcel invocations
|
||||
func (mmExportExcel *SupplierServiceMock) ExportExcelBeforeCounter() uint64 {
|
||||
return mm_atomic.LoadUint64(&mmExportExcel.beforeExportExcelCounter)
|
||||
}
|
||||
|
||||
// Calls returns a list of arguments used in each call to SupplierServiceMock.ExportExcel.
|
||||
// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
|
||||
func (mmExportExcel *mSupplierServiceMockExportExcel) Calls() []*SupplierServiceMockExportExcelParams {
|
||||
mmExportExcel.mutex.RLock()
|
||||
|
||||
argCopy := make([]*SupplierServiceMockExportExcelParams, len(mmExportExcel.callArgs))
|
||||
copy(argCopy, mmExportExcel.callArgs)
|
||||
|
||||
mmExportExcel.mutex.RUnlock()
|
||||
|
||||
return argCopy
|
||||
}
|
||||
|
||||
// MinimockExportExcelDone returns true if the count of the ExportExcel invocations corresponds
|
||||
// the number of defined expectations
|
||||
func (m *SupplierServiceMock) MinimockExportExcelDone() bool {
|
||||
if m.ExportExcelMock.optional {
|
||||
// Optional methods provide '0 or more' call count restriction.
|
||||
return true
|
||||
}
|
||||
|
||||
for _, e := range m.ExportExcelMock.expectations {
|
||||
if mm_atomic.LoadUint64(&e.Counter) < 1 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return m.ExportExcelMock.invocationsDone()
|
||||
}
|
||||
|
||||
// MinimockExportExcelInspect logs each unmet expectation
|
||||
func (m *SupplierServiceMock) MinimockExportExcelInspect() {
|
||||
for _, e := range m.ExportExcelMock.expectations {
|
||||
if mm_atomic.LoadUint64(&e.Counter) < 1 {
|
||||
m.t.Errorf("Expected call to SupplierServiceMock.ExportExcel at\n%s with params: %#v", e.expectationOrigins.origin, *e.params)
|
||||
}
|
||||
}
|
||||
|
||||
afterExportExcelCounter := mm_atomic.LoadUint64(&m.afterExportExcelCounter)
|
||||
// if default expectation was set then invocations count should be greater than zero
|
||||
if m.ExportExcelMock.defaultExpectation != nil && afterExportExcelCounter < 1 {
|
||||
if m.ExportExcelMock.defaultExpectation.params == nil {
|
||||
m.t.Errorf("Expected call to SupplierServiceMock.ExportExcel at\n%s", m.ExportExcelMock.defaultExpectation.returnOrigin)
|
||||
} else {
|
||||
m.t.Errorf("Expected call to SupplierServiceMock.ExportExcel at\n%s with params: %#v", m.ExportExcelMock.defaultExpectation.expectationOrigins.origin, *m.ExportExcelMock.defaultExpectation.params)
|
||||
}
|
||||
}
|
||||
// if func was set then invocations count should be greater than zero
|
||||
if m.funcExportExcel != nil && afterExportExcelCounter < 1 {
|
||||
m.t.Errorf("Expected call to SupplierServiceMock.ExportExcel at\n%s", m.funcExportExcelOrigin)
|
||||
}
|
||||
|
||||
if !m.ExportExcelMock.invocationsDone() && afterExportExcelCounter > 0 {
|
||||
m.t.Errorf("Expected %d calls to SupplierServiceMock.ExportExcel at\n%s but found %d calls",
|
||||
mm_atomic.LoadUint64(&m.ExportExcelMock.expectedInvocations), m.ExportExcelMock.expectedInvocationsOrigin, afterExportExcelCounter)
|
||||
}
|
||||
}
|
||||
|
||||
// MinimockFinish checks that all mocked methods have been called the expected number of times
|
||||
func (m *SupplierServiceMock) MinimockFinish() {
|
||||
m.finishOnce.Do(func() {
|
||||
if !m.minimockDone() {
|
||||
m.MinimockExportExcelInspect()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// MinimockWait waits for all mocked methods to be called the expected number of times
|
||||
func (m *SupplierServiceMock) MinimockWait(timeout mm_time.Duration) {
|
||||
timeoutCh := mm_time.After(timeout)
|
||||
for {
|
||||
if m.minimockDone() {
|
||||
return
|
||||
}
|
||||
select {
|
||||
case <-timeoutCh:
|
||||
m.MinimockFinish()
|
||||
return
|
||||
case <-mm_time.After(10 * mm_time.Millisecond):
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *SupplierServiceMock) minimockDone() bool {
|
||||
done := true
|
||||
return done &&
|
||||
m.MinimockExportExcelDone()
|
||||
}
|
||||
417
internal/mocks/token_usage_repository_mock.go
Normal file
417
internal/mocks/token_usage_repository_mock.go
Normal file
@@ -0,0 +1,417 @@
|
||||
// Code generated by http://github.com/gojuno/minimock (v3.4.7). DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
//go:generate minimock -i smart-search-back/internal/repository.TokenUsageRepository -o token_usage_repository_mock.go -n TokenUsageRepositoryMock -p mocks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"smart-search-back/internal/model"
|
||||
"sync"
|
||||
mm_atomic "sync/atomic"
|
||||
mm_time "time"
|
||||
|
||||
"github.com/gojuno/minimock/v3"
|
||||
)
|
||||
|
||||
// TokenUsageRepositoryMock implements mm_repository.TokenUsageRepository
|
||||
type TokenUsageRepositoryMock struct {
|
||||
t minimock.Tester
|
||||
finishOnce sync.Once
|
||||
|
||||
funcCreate func(ctx context.Context, usage *model.TokenUsage) (err error)
|
||||
funcCreateOrigin string
|
||||
inspectFuncCreate func(ctx context.Context, usage *model.TokenUsage)
|
||||
afterCreateCounter uint64
|
||||
beforeCreateCounter uint64
|
||||
CreateMock mTokenUsageRepositoryMockCreate
|
||||
}
|
||||
|
||||
// NewTokenUsageRepositoryMock returns a mock for mm_repository.TokenUsageRepository
|
||||
func NewTokenUsageRepositoryMock(t minimock.Tester) *TokenUsageRepositoryMock {
|
||||
m := &TokenUsageRepositoryMock{t: t}
|
||||
|
||||
if controller, ok := t.(minimock.MockController); ok {
|
||||
controller.RegisterMocker(m)
|
||||
}
|
||||
|
||||
m.CreateMock = mTokenUsageRepositoryMockCreate{mock: m}
|
||||
m.CreateMock.callArgs = []*TokenUsageRepositoryMockCreateParams{}
|
||||
|
||||
t.Cleanup(m.MinimockFinish)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
type mTokenUsageRepositoryMockCreate struct {
|
||||
optional bool
|
||||
mock *TokenUsageRepositoryMock
|
||||
defaultExpectation *TokenUsageRepositoryMockCreateExpectation
|
||||
expectations []*TokenUsageRepositoryMockCreateExpectation
|
||||
|
||||
callArgs []*TokenUsageRepositoryMockCreateParams
|
||||
mutex sync.RWMutex
|
||||
|
||||
expectedInvocations uint64
|
||||
expectedInvocationsOrigin string
|
||||
}
|
||||
|
||||
// TokenUsageRepositoryMockCreateExpectation specifies expectation struct of the TokenUsageRepository.Create
|
||||
type TokenUsageRepositoryMockCreateExpectation struct {
|
||||
mock *TokenUsageRepositoryMock
|
||||
params *TokenUsageRepositoryMockCreateParams
|
||||
paramPtrs *TokenUsageRepositoryMockCreateParamPtrs
|
||||
expectationOrigins TokenUsageRepositoryMockCreateExpectationOrigins
|
||||
results *TokenUsageRepositoryMockCreateResults
|
||||
returnOrigin string
|
||||
Counter uint64
|
||||
}
|
||||
|
||||
// TokenUsageRepositoryMockCreateParams contains parameters of the TokenUsageRepository.Create
|
||||
type TokenUsageRepositoryMockCreateParams struct {
|
||||
ctx context.Context
|
||||
usage *model.TokenUsage
|
||||
}
|
||||
|
||||
// TokenUsageRepositoryMockCreateParamPtrs contains pointers to parameters of the TokenUsageRepository.Create
|
||||
type TokenUsageRepositoryMockCreateParamPtrs struct {
|
||||
ctx *context.Context
|
||||
usage **model.TokenUsage
|
||||
}
|
||||
|
||||
// TokenUsageRepositoryMockCreateResults contains results of the TokenUsageRepository.Create
|
||||
type TokenUsageRepositoryMockCreateResults struct {
|
||||
err error
|
||||
}
|
||||
|
||||
// TokenUsageRepositoryMockCreateOrigins contains origins of expectations of the TokenUsageRepository.Create
|
||||
type TokenUsageRepositoryMockCreateExpectationOrigins struct {
|
||||
origin string
|
||||
originCtx string
|
||||
originUsage string
|
||||
}
|
||||
|
||||
// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
|
||||
// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
|
||||
// Optional() makes method check to work in '0 or more' mode.
|
||||
// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
|
||||
// catch the problems when the expected method call is totally skipped during test run.
|
||||
func (mmCreate *mTokenUsageRepositoryMockCreate) Optional() *mTokenUsageRepositoryMockCreate {
|
||||
mmCreate.optional = true
|
||||
return mmCreate
|
||||
}
|
||||
|
||||
// Expect sets up expected params for TokenUsageRepository.Create
|
||||
func (mmCreate *mTokenUsageRepositoryMockCreate) Expect(ctx context.Context, usage *model.TokenUsage) *mTokenUsageRepositoryMockCreate {
|
||||
if mmCreate.mock.funcCreate != nil {
|
||||
mmCreate.mock.t.Fatalf("TokenUsageRepositoryMock.Create mock is already set by Set")
|
||||
}
|
||||
|
||||
if mmCreate.defaultExpectation == nil {
|
||||
mmCreate.defaultExpectation = &TokenUsageRepositoryMockCreateExpectation{}
|
||||
}
|
||||
|
||||
if mmCreate.defaultExpectation.paramPtrs != nil {
|
||||
mmCreate.mock.t.Fatalf("TokenUsageRepositoryMock.Create mock is already set by ExpectParams functions")
|
||||
}
|
||||
|
||||
mmCreate.defaultExpectation.params = &TokenUsageRepositoryMockCreateParams{ctx, usage}
|
||||
mmCreate.defaultExpectation.expectationOrigins.origin = minimock.CallerInfo(1)
|
||||
for _, e := range mmCreate.expectations {
|
||||
if minimock.Equal(e.params, mmCreate.defaultExpectation.params) {
|
||||
mmCreate.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmCreate.defaultExpectation.params)
|
||||
}
|
||||
}
|
||||
|
||||
return mmCreate
|
||||
}
|
||||
|
||||
// ExpectCtxParam1 sets up expected param ctx for TokenUsageRepository.Create
|
||||
func (mmCreate *mTokenUsageRepositoryMockCreate) ExpectCtxParam1(ctx context.Context) *mTokenUsageRepositoryMockCreate {
|
||||
if mmCreate.mock.funcCreate != nil {
|
||||
mmCreate.mock.t.Fatalf("TokenUsageRepositoryMock.Create mock is already set by Set")
|
||||
}
|
||||
|
||||
if mmCreate.defaultExpectation == nil {
|
||||
mmCreate.defaultExpectation = &TokenUsageRepositoryMockCreateExpectation{}
|
||||
}
|
||||
|
||||
if mmCreate.defaultExpectation.params != nil {
|
||||
mmCreate.mock.t.Fatalf("TokenUsageRepositoryMock.Create mock is already set by Expect")
|
||||
}
|
||||
|
||||
if mmCreate.defaultExpectation.paramPtrs == nil {
|
||||
mmCreate.defaultExpectation.paramPtrs = &TokenUsageRepositoryMockCreateParamPtrs{}
|
||||
}
|
||||
mmCreate.defaultExpectation.paramPtrs.ctx = &ctx
|
||||
mmCreate.defaultExpectation.expectationOrigins.originCtx = minimock.CallerInfo(1)
|
||||
|
||||
return mmCreate
|
||||
}
|
||||
|
||||
// ExpectUsageParam2 sets up expected param usage for TokenUsageRepository.Create
|
||||
func (mmCreate *mTokenUsageRepositoryMockCreate) ExpectUsageParam2(usage *model.TokenUsage) *mTokenUsageRepositoryMockCreate {
|
||||
if mmCreate.mock.funcCreate != nil {
|
||||
mmCreate.mock.t.Fatalf("TokenUsageRepositoryMock.Create mock is already set by Set")
|
||||
}
|
||||
|
||||
if mmCreate.defaultExpectation == nil {
|
||||
mmCreate.defaultExpectation = &TokenUsageRepositoryMockCreateExpectation{}
|
||||
}
|
||||
|
||||
if mmCreate.defaultExpectation.params != nil {
|
||||
mmCreate.mock.t.Fatalf("TokenUsageRepositoryMock.Create mock is already set by Expect")
|
||||
}
|
||||
|
||||
if mmCreate.defaultExpectation.paramPtrs == nil {
|
||||
mmCreate.defaultExpectation.paramPtrs = &TokenUsageRepositoryMockCreateParamPtrs{}
|
||||
}
|
||||
mmCreate.defaultExpectation.paramPtrs.usage = &usage
|
||||
mmCreate.defaultExpectation.expectationOrigins.originUsage = minimock.CallerInfo(1)
|
||||
|
||||
return mmCreate
|
||||
}
|
||||
|
||||
// Inspect accepts an inspector function that has same arguments as the TokenUsageRepository.Create
|
||||
func (mmCreate *mTokenUsageRepositoryMockCreate) Inspect(f func(ctx context.Context, usage *model.TokenUsage)) *mTokenUsageRepositoryMockCreate {
|
||||
if mmCreate.mock.inspectFuncCreate != nil {
|
||||
mmCreate.mock.t.Fatalf("Inspect function is already set for TokenUsageRepositoryMock.Create")
|
||||
}
|
||||
|
||||
mmCreate.mock.inspectFuncCreate = f
|
||||
|
||||
return mmCreate
|
||||
}
|
||||
|
||||
// Return sets up results that will be returned by TokenUsageRepository.Create
|
||||
func (mmCreate *mTokenUsageRepositoryMockCreate) Return(err error) *TokenUsageRepositoryMock {
|
||||
if mmCreate.mock.funcCreate != nil {
|
||||
mmCreate.mock.t.Fatalf("TokenUsageRepositoryMock.Create mock is already set by Set")
|
||||
}
|
||||
|
||||
if mmCreate.defaultExpectation == nil {
|
||||
mmCreate.defaultExpectation = &TokenUsageRepositoryMockCreateExpectation{mock: mmCreate.mock}
|
||||
}
|
||||
mmCreate.defaultExpectation.results = &TokenUsageRepositoryMockCreateResults{err}
|
||||
mmCreate.defaultExpectation.returnOrigin = minimock.CallerInfo(1)
|
||||
return mmCreate.mock
|
||||
}
|
||||
|
||||
// Set uses given function f to mock the TokenUsageRepository.Create method
|
||||
func (mmCreate *mTokenUsageRepositoryMockCreate) Set(f func(ctx context.Context, usage *model.TokenUsage) (err error)) *TokenUsageRepositoryMock {
|
||||
if mmCreate.defaultExpectation != nil {
|
||||
mmCreate.mock.t.Fatalf("Default expectation is already set for the TokenUsageRepository.Create method")
|
||||
}
|
||||
|
||||
if len(mmCreate.expectations) > 0 {
|
||||
mmCreate.mock.t.Fatalf("Some expectations are already set for the TokenUsageRepository.Create method")
|
||||
}
|
||||
|
||||
mmCreate.mock.funcCreate = f
|
||||
mmCreate.mock.funcCreateOrigin = minimock.CallerInfo(1)
|
||||
return mmCreate.mock
|
||||
}
|
||||
|
||||
// When sets expectation for the TokenUsageRepository.Create which will trigger the result defined by the following
|
||||
// Then helper
|
||||
func (mmCreate *mTokenUsageRepositoryMockCreate) When(ctx context.Context, usage *model.TokenUsage) *TokenUsageRepositoryMockCreateExpectation {
|
||||
if mmCreate.mock.funcCreate != nil {
|
||||
mmCreate.mock.t.Fatalf("TokenUsageRepositoryMock.Create mock is already set by Set")
|
||||
}
|
||||
|
||||
expectation := &TokenUsageRepositoryMockCreateExpectation{
|
||||
mock: mmCreate.mock,
|
||||
params: &TokenUsageRepositoryMockCreateParams{ctx, usage},
|
||||
expectationOrigins: TokenUsageRepositoryMockCreateExpectationOrigins{origin: minimock.CallerInfo(1)},
|
||||
}
|
||||
mmCreate.expectations = append(mmCreate.expectations, expectation)
|
||||
return expectation
|
||||
}
|
||||
|
||||
// Then sets up TokenUsageRepository.Create return parameters for the expectation previously defined by the When method
|
||||
func (e *TokenUsageRepositoryMockCreateExpectation) Then(err error) *TokenUsageRepositoryMock {
|
||||
e.results = &TokenUsageRepositoryMockCreateResults{err}
|
||||
return e.mock
|
||||
}
|
||||
|
||||
// Times sets number of times TokenUsageRepository.Create should be invoked
|
||||
func (mmCreate *mTokenUsageRepositoryMockCreate) Times(n uint64) *mTokenUsageRepositoryMockCreate {
|
||||
if n == 0 {
|
||||
mmCreate.mock.t.Fatalf("Times of TokenUsageRepositoryMock.Create mock can not be zero")
|
||||
}
|
||||
mm_atomic.StoreUint64(&mmCreate.expectedInvocations, n)
|
||||
mmCreate.expectedInvocationsOrigin = minimock.CallerInfo(1)
|
||||
return mmCreate
|
||||
}
|
||||
|
||||
func (mmCreate *mTokenUsageRepositoryMockCreate) invocationsDone() bool {
|
||||
if len(mmCreate.expectations) == 0 && mmCreate.defaultExpectation == nil && mmCreate.mock.funcCreate == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
totalInvocations := mm_atomic.LoadUint64(&mmCreate.mock.afterCreateCounter)
|
||||
expectedInvocations := mm_atomic.LoadUint64(&mmCreate.expectedInvocations)
|
||||
|
||||
return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
|
||||
}
|
||||
|
||||
// Create implements mm_repository.TokenUsageRepository
|
||||
func (mmCreate *TokenUsageRepositoryMock) Create(ctx context.Context, usage *model.TokenUsage) (err error) {
|
||||
mm_atomic.AddUint64(&mmCreate.beforeCreateCounter, 1)
|
||||
defer mm_atomic.AddUint64(&mmCreate.afterCreateCounter, 1)
|
||||
|
||||
mmCreate.t.Helper()
|
||||
|
||||
if mmCreate.inspectFuncCreate != nil {
|
||||
mmCreate.inspectFuncCreate(ctx, usage)
|
||||
}
|
||||
|
||||
mm_params := TokenUsageRepositoryMockCreateParams{ctx, usage}
|
||||
|
||||
// Record call args
|
||||
mmCreate.CreateMock.mutex.Lock()
|
||||
mmCreate.CreateMock.callArgs = append(mmCreate.CreateMock.callArgs, &mm_params)
|
||||
mmCreate.CreateMock.mutex.Unlock()
|
||||
|
||||
for _, e := range mmCreate.CreateMock.expectations {
|
||||
if minimock.Equal(*e.params, mm_params) {
|
||||
mm_atomic.AddUint64(&e.Counter, 1)
|
||||
return e.results.err
|
||||
}
|
||||
}
|
||||
|
||||
if mmCreate.CreateMock.defaultExpectation != nil {
|
||||
mm_atomic.AddUint64(&mmCreate.CreateMock.defaultExpectation.Counter, 1)
|
||||
mm_want := mmCreate.CreateMock.defaultExpectation.params
|
||||
mm_want_ptrs := mmCreate.CreateMock.defaultExpectation.paramPtrs
|
||||
|
||||
mm_got := TokenUsageRepositoryMockCreateParams{ctx, usage}
|
||||
|
||||
if mm_want_ptrs != nil {
|
||||
|
||||
if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
|
||||
mmCreate.t.Errorf("TokenUsageRepositoryMock.Create got unexpected parameter ctx, expected at\n%s:\nwant: %#v\n got: %#v%s\n",
|
||||
mmCreate.CreateMock.defaultExpectation.expectationOrigins.originCtx, *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
|
||||
}
|
||||
|
||||
if mm_want_ptrs.usage != nil && !minimock.Equal(*mm_want_ptrs.usage, mm_got.usage) {
|
||||
mmCreate.t.Errorf("TokenUsageRepositoryMock.Create got unexpected parameter usage, expected at\n%s:\nwant: %#v\n got: %#v%s\n",
|
||||
mmCreate.CreateMock.defaultExpectation.expectationOrigins.originUsage, *mm_want_ptrs.usage, mm_got.usage, minimock.Diff(*mm_want_ptrs.usage, mm_got.usage))
|
||||
}
|
||||
|
||||
} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
|
||||
mmCreate.t.Errorf("TokenUsageRepositoryMock.Create got unexpected parameters, expected at\n%s:\nwant: %#v\n got: %#v%s\n",
|
||||
mmCreate.CreateMock.defaultExpectation.expectationOrigins.origin, *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
|
||||
}
|
||||
|
||||
mm_results := mmCreate.CreateMock.defaultExpectation.results
|
||||
if mm_results == nil {
|
||||
mmCreate.t.Fatal("No results are set for the TokenUsageRepositoryMock.Create")
|
||||
}
|
||||
return (*mm_results).err
|
||||
}
|
||||
if mmCreate.funcCreate != nil {
|
||||
return mmCreate.funcCreate(ctx, usage)
|
||||
}
|
||||
mmCreate.t.Fatalf("Unexpected call to TokenUsageRepositoryMock.Create. %v %v", ctx, usage)
|
||||
return
|
||||
}
|
||||
|
||||
// CreateAfterCounter returns a count of finished TokenUsageRepositoryMock.Create invocations
|
||||
func (mmCreate *TokenUsageRepositoryMock) CreateAfterCounter() uint64 {
|
||||
return mm_atomic.LoadUint64(&mmCreate.afterCreateCounter)
|
||||
}
|
||||
|
||||
// CreateBeforeCounter returns a count of TokenUsageRepositoryMock.Create invocations
|
||||
func (mmCreate *TokenUsageRepositoryMock) CreateBeforeCounter() uint64 {
|
||||
return mm_atomic.LoadUint64(&mmCreate.beforeCreateCounter)
|
||||
}
|
||||
|
||||
// Calls returns a list of arguments used in each call to TokenUsageRepositoryMock.Create.
|
||||
// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
|
||||
func (mmCreate *mTokenUsageRepositoryMockCreate) Calls() []*TokenUsageRepositoryMockCreateParams {
|
||||
mmCreate.mutex.RLock()
|
||||
|
||||
argCopy := make([]*TokenUsageRepositoryMockCreateParams, len(mmCreate.callArgs))
|
||||
copy(argCopy, mmCreate.callArgs)
|
||||
|
||||
mmCreate.mutex.RUnlock()
|
||||
|
||||
return argCopy
|
||||
}
|
||||
|
||||
// MinimockCreateDone returns true if the count of the Create invocations corresponds
|
||||
// the number of defined expectations
|
||||
func (m *TokenUsageRepositoryMock) MinimockCreateDone() bool {
|
||||
if m.CreateMock.optional {
|
||||
// Optional methods provide '0 or more' call count restriction.
|
||||
return true
|
||||
}
|
||||
|
||||
for _, e := range m.CreateMock.expectations {
|
||||
if mm_atomic.LoadUint64(&e.Counter) < 1 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return m.CreateMock.invocationsDone()
|
||||
}
|
||||
|
||||
// MinimockCreateInspect logs each unmet expectation
|
||||
func (m *TokenUsageRepositoryMock) MinimockCreateInspect() {
|
||||
for _, e := range m.CreateMock.expectations {
|
||||
if mm_atomic.LoadUint64(&e.Counter) < 1 {
|
||||
m.t.Errorf("Expected call to TokenUsageRepositoryMock.Create at\n%s with params: %#v", e.expectationOrigins.origin, *e.params)
|
||||
}
|
||||
}
|
||||
|
||||
afterCreateCounter := mm_atomic.LoadUint64(&m.afterCreateCounter)
|
||||
// if default expectation was set then invocations count should be greater than zero
|
||||
if m.CreateMock.defaultExpectation != nil && afterCreateCounter < 1 {
|
||||
if m.CreateMock.defaultExpectation.params == nil {
|
||||
m.t.Errorf("Expected call to TokenUsageRepositoryMock.Create at\n%s", m.CreateMock.defaultExpectation.returnOrigin)
|
||||
} else {
|
||||
m.t.Errorf("Expected call to TokenUsageRepositoryMock.Create at\n%s with params: %#v", m.CreateMock.defaultExpectation.expectationOrigins.origin, *m.CreateMock.defaultExpectation.params)
|
||||
}
|
||||
}
|
||||
// if func was set then invocations count should be greater than zero
|
||||
if m.funcCreate != nil && afterCreateCounter < 1 {
|
||||
m.t.Errorf("Expected call to TokenUsageRepositoryMock.Create at\n%s", m.funcCreateOrigin)
|
||||
}
|
||||
|
||||
if !m.CreateMock.invocationsDone() && afterCreateCounter > 0 {
|
||||
m.t.Errorf("Expected %d calls to TokenUsageRepositoryMock.Create at\n%s but found %d calls",
|
||||
mm_atomic.LoadUint64(&m.CreateMock.expectedInvocations), m.CreateMock.expectedInvocationsOrigin, afterCreateCounter)
|
||||
}
|
||||
}
|
||||
|
||||
// MinimockFinish checks that all mocked methods have been called the expected number of times
|
||||
func (m *TokenUsageRepositoryMock) MinimockFinish() {
|
||||
m.finishOnce.Do(func() {
|
||||
if !m.minimockDone() {
|
||||
m.MinimockCreateInspect()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// MinimockWait waits for all mocked methods to be called the expected number of times
|
||||
func (m *TokenUsageRepositoryMock) MinimockWait(timeout mm_time.Duration) {
|
||||
timeoutCh := mm_time.After(timeout)
|
||||
for {
|
||||
if m.minimockDone() {
|
||||
return
|
||||
}
|
||||
select {
|
||||
case <-timeoutCh:
|
||||
m.MinimockFinish()
|
||||
return
|
||||
case <-mm_time.After(10 * mm_time.Millisecond):
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *TokenUsageRepositoryMock) minimockDone() bool {
|
||||
done := true
|
||||
return done &&
|
||||
m.MinimockCreateDone()
|
||||
}
|
||||
2582
internal/mocks/user_repository_mock.go
Normal file
2582
internal/mocks/user_repository_mock.go
Normal file
File diff suppressed because it is too large
Load Diff
1130
internal/mocks/user_service_mock.go
Normal file
1130
internal/mocks/user_service_mock.go
Normal file
File diff suppressed because it is too large
Load Diff
14
internal/model/invite.go
Normal file
14
internal/model/invite.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
type InviteCode struct {
|
||||
ID int
|
||||
UserID int
|
||||
Code int64
|
||||
CanBeUsedCount int
|
||||
UsedCount int
|
||||
IsActive bool
|
||||
CreatedAt time.Time
|
||||
ExpiresAt time.Time
|
||||
}
|
||||
40
internal/model/request.go
Normal file
40
internal/model/request.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Request struct {
|
||||
ID uuid.UUID
|
||||
UserID int
|
||||
RequestTxt string
|
||||
GeneratedTZ bool
|
||||
FinalTZ string
|
||||
GeneratedFinalTZ bool
|
||||
FinalUpdateTZ string
|
||||
MailingStatusID int
|
||||
MailingStatus string
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
type MailingStatus struct {
|
||||
ID int
|
||||
StatusName string
|
||||
}
|
||||
|
||||
type RequestDetail struct {
|
||||
RequestID uuid.UUID
|
||||
Title string
|
||||
MailText string
|
||||
Suppliers []SupplierInfo
|
||||
}
|
||||
|
||||
type SupplierInfo struct {
|
||||
CompanyID int `json:"company_id"`
|
||||
Email string `json:"email"`
|
||||
Phone string `json:"phone"`
|
||||
CompanyName string `json:"company_name"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
15
internal/model/session.go
Normal file
15
internal/model/session.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
type Session struct {
|
||||
ID int
|
||||
UserID int
|
||||
AccessToken string
|
||||
RefreshToken string
|
||||
IP string
|
||||
UserAgent string
|
||||
CreatedAt time.Time
|
||||
ExpiresAt time.Time
|
||||
RevokedAt *time.Time
|
||||
}
|
||||
28
internal/model/supplier.go
Normal file
28
internal/model/supplier.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Supplier struct {
|
||||
ID int
|
||||
RequestID uuid.UUID
|
||||
Name string
|
||||
Email string
|
||||
Phone string
|
||||
Address string
|
||||
URL string
|
||||
CreatedAt time.Time
|
||||
}
|
||||
|
||||
type TokenUsage struct {
|
||||
ID int
|
||||
RequestID uuid.UUID
|
||||
RequestTokenCount int
|
||||
ResponseTokenCount int
|
||||
TokenCost float64
|
||||
Type string
|
||||
CreatedAt time.Time
|
||||
}
|
||||
18
internal/model/user.go
Normal file
18
internal/model/user.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package model
|
||||
|
||||
import "time"
|
||||
|
||||
type User struct {
|
||||
ID int
|
||||
Email string
|
||||
EmailHash string
|
||||
PasswordHash string
|
||||
Phone string
|
||||
UserName string
|
||||
CompanyName string
|
||||
Balance float64
|
||||
PaymentStatus string
|
||||
InvitesIssued int
|
||||
InvitesLimit int
|
||||
CreatedAt time.Time
|
||||
}
|
||||
54
internal/repository/interfaces.go
Normal file
54
internal/repository/interfaces.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"smart-search-back/internal/model"
|
||||
)
|
||||
|
||||
type UserRepository interface {
|
||||
FindByEmailHash(ctx context.Context, emailHash string) (*model.User, error)
|
||||
FindByID(ctx context.Context, userID int) (*model.User, error)
|
||||
Create(ctx context.Context, user *model.User) error
|
||||
UpdateBalance(ctx context.Context, userID int, delta float64) error
|
||||
GetBalance(ctx context.Context, userID int) (float64, error)
|
||||
IncrementInvitesIssued(ctx context.Context, userID int) error
|
||||
CheckInviteLimit(ctx context.Context, userID int) (bool, error)
|
||||
}
|
||||
|
||||
type SessionRepository interface {
|
||||
Create(ctx context.Context, session *model.Session) error
|
||||
FindByRefreshToken(ctx context.Context, token string) (*model.Session, error)
|
||||
UpdateAccessToken(ctx context.Context, refreshToken, newAccessToken string) error
|
||||
Revoke(ctx context.Context, refreshToken string) error
|
||||
DeleteExpired(ctx context.Context) (int, error)
|
||||
}
|
||||
|
||||
type InviteRepository interface {
|
||||
Create(ctx context.Context, invite *model.InviteCode) error
|
||||
FindByCode(ctx context.Context, code int64) (*model.InviteCode, error)
|
||||
IncrementUsedCount(ctx context.Context, code int64) error
|
||||
DeactivateExpired(ctx context.Context) (int, error)
|
||||
GetUserInvites(ctx context.Context, userID int) ([]*model.InviteCode, error)
|
||||
}
|
||||
|
||||
type RequestRepository interface {
|
||||
Create(ctx context.Context, req *model.Request) error
|
||||
UpdateWithTZ(ctx context.Context, id uuid.UUID, tz string, generated bool) error
|
||||
UpdateFinalTZ(ctx context.Context, id uuid.UUID, finalTZ string) error
|
||||
GetByUserID(ctx context.Context, userID int) ([]*model.Request, error)
|
||||
GetByID(ctx context.Context, id uuid.UUID) (*model.Request, error)
|
||||
GetDetailByID(ctx context.Context, id uuid.UUID) (*model.RequestDetail, error)
|
||||
GetUserStatistics(ctx context.Context, userID int) (requestsCount, suppliersCount, createdTZ int, err error)
|
||||
}
|
||||
|
||||
type SupplierRepository interface {
|
||||
BulkInsert(ctx context.Context, requestID uuid.UUID, suppliers []*model.Supplier) error
|
||||
GetByRequestID(ctx context.Context, requestID uuid.UUID) ([]*model.Supplier, error)
|
||||
DeleteByRequestID(ctx context.Context, requestID uuid.UUID) error
|
||||
}
|
||||
|
||||
type TokenUsageRepository interface {
|
||||
Create(ctx context.Context, usage *model.TokenUsage) error
|
||||
}
|
||||
146
internal/repository/invite.go
Normal file
146
internal/repository/invite.go
Normal file
@@ -0,0 +1,146 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"smart-search-back/internal/model"
|
||||
errs "smart-search-back/pkg/errors"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
type inviteRepository struct {
|
||||
pool *pgxpool.Pool
|
||||
qb sq.StatementBuilderType
|
||||
}
|
||||
|
||||
func NewInviteRepository(pool *pgxpool.Pool) InviteRepository {
|
||||
return &inviteRepository{
|
||||
pool: pool,
|
||||
qb: sq.StatementBuilder.PlaceholderFormat(sq.Dollar),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *inviteRepository) Create(ctx context.Context, invite *model.InviteCode) error {
|
||||
query := r.qb.Insert("invite_codes").Columns(
|
||||
"user_id", "code", "can_be_used_count", "expires_at",
|
||||
).Values(
|
||||
invite.UserID, invite.Code, invite.CanBeUsedCount, invite.ExpiresAt,
|
||||
).Suffix("RETURNING id, created_at")
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
err = r.pool.QueryRow(ctx, sqlQuery, args...).Scan(&invite.ID, &invite.CreatedAt)
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to create invite code", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *inviteRepository) FindByCode(ctx context.Context, code int64) (*model.InviteCode, error) {
|
||||
query := r.qb.Select(
|
||||
"id", "user_id", "code", "can_be_used_count", "used_count",
|
||||
"is_active", "created_at", "expires_at",
|
||||
).From("invite_codes").Where(sq.Eq{"code": code})
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return nil, errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
invite := &model.InviteCode{}
|
||||
err = r.pool.QueryRow(ctx, sqlQuery, args...).Scan(
|
||||
&invite.ID, &invite.UserID, &invite.Code, &invite.CanBeUsedCount,
|
||||
&invite.UsedCount, &invite.IsActive, &invite.CreatedAt, &invite.ExpiresAt,
|
||||
)
|
||||
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, errs.NewBusinessError(errs.UserNotFound, "invite code not found")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errs.NewInternalError(errs.DatabaseError, "failed to find invite code", err)
|
||||
}
|
||||
|
||||
return invite, nil
|
||||
}
|
||||
|
||||
func (r *inviteRepository) IncrementUsedCount(ctx context.Context, code int64) error {
|
||||
query := r.qb.Update("invite_codes").
|
||||
Set("used_count", sq.Expr("used_count + 1")).
|
||||
Where(sq.Eq{"code": code})
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
_, err = r.pool.Exec(ctx, sqlQuery, args...)
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to increment used count", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *inviteRepository) DeactivateExpired(ctx context.Context) (int, error) {
|
||||
query := r.qb.Update("invite_codes").
|
||||
Set("is_active", false).
|
||||
Where(sq.And{
|
||||
sq.Expr("expires_at < now()"),
|
||||
sq.Eq{"is_active": true},
|
||||
})
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return 0, errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
result, err := r.pool.Exec(ctx, sqlQuery, args...)
|
||||
if err != nil {
|
||||
return 0, errs.NewInternalError(errs.DatabaseError, "failed to deactivate expired invites", err)
|
||||
}
|
||||
|
||||
return int(result.RowsAffected()), nil
|
||||
}
|
||||
|
||||
func (r *inviteRepository) GetUserInvites(ctx context.Context, userID int) ([]*model.InviteCode, error) {
|
||||
query := r.qb.Select(
|
||||
"id", "user_id", "code", "can_be_used_count", "used_count",
|
||||
"is_active", "created_at", "expires_at",
|
||||
).From("invite_codes").
|
||||
Where(sq.Eq{"user_id": userID}).
|
||||
OrderBy("created_at DESC")
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return nil, errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
rows, err := r.pool.Query(ctx, sqlQuery, args...)
|
||||
if err != nil {
|
||||
return nil, errs.NewInternalError(errs.DatabaseError, "failed to get user invites", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var invites []*model.InviteCode
|
||||
for rows.Next() {
|
||||
invite := &model.InviteCode{}
|
||||
err := rows.Scan(
|
||||
&invite.ID, &invite.UserID, &invite.Code, &invite.CanBeUsedCount,
|
||||
&invite.UsedCount, &invite.IsActive, &invite.CreatedAt, &invite.ExpiresAt,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errs.NewInternalError(errs.DatabaseError, "failed to scan invite", err)
|
||||
}
|
||||
invites = append(invites, invite)
|
||||
}
|
||||
|
||||
return invites, nil
|
||||
}
|
||||
209
internal/repository/request.go
Normal file
209
internal/repository/request.go
Normal file
@@ -0,0 +1,209 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"smart-search-back/internal/model"
|
||||
errs "smart-search-back/pkg/errors"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
type requestRepository struct {
|
||||
pool *pgxpool.Pool
|
||||
qb sq.StatementBuilderType
|
||||
}
|
||||
|
||||
func NewRequestRepository(pool *pgxpool.Pool) RequestRepository {
|
||||
return &requestRepository{
|
||||
pool: pool,
|
||||
qb: sq.StatementBuilder.PlaceholderFormat(sq.Dollar),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *requestRepository) Create(ctx context.Context, req *model.Request) error {
|
||||
query := r.qb.Insert("requests_for_suppliers").Columns(
|
||||
"user_id", "request_txt",
|
||||
).Values(
|
||||
req.UserID, req.RequestTxt,
|
||||
).Suffix("RETURNING id, created_at")
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
err = r.pool.QueryRow(ctx, sqlQuery, args...).Scan(&req.ID, &req.CreatedAt)
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to create request", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *requestRepository) UpdateWithTZ(ctx context.Context, id uuid.UUID, tz string, generated bool) error {
|
||||
query := r.qb.Update("requests_for_suppliers").
|
||||
Set("final_tz", tz).
|
||||
Set("generated_tz", generated).
|
||||
Set("generated_final_tz", generated).
|
||||
Where(sq.Eq{"id": id})
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
_, err = r.pool.Exec(ctx, sqlQuery, args...)
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to update request", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *requestRepository) UpdateFinalTZ(ctx context.Context, id uuid.UUID, finalTZ string) error {
|
||||
query := r.qb.Update("requests_for_suppliers").
|
||||
Set("final_update_tz", finalTZ).
|
||||
Where(sq.Eq{"id": id})
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
_, err = r.pool.Exec(ctx, sqlQuery, args...)
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to update final TZ", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *requestRepository) GetByUserID(ctx context.Context, userID int) ([]*model.Request, error) {
|
||||
query := r.qb.Select(
|
||||
"r.id", "r.request_txt", "ms.status_name as mailing_status",
|
||||
).From("requests_for_suppliers r").
|
||||
Join("mailing_status ms ON r.mailling_status_id = ms.id").
|
||||
Where(sq.Eq{"r.user_id": userID}).
|
||||
OrderBy("r.created_at DESC")
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return nil, errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
rows, err := r.pool.Query(ctx, sqlQuery, args...)
|
||||
if err != nil {
|
||||
return nil, errs.NewInternalError(errs.DatabaseError, "failed to get requests", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var requests []*model.Request
|
||||
for rows.Next() {
|
||||
req := &model.Request{}
|
||||
var statusName string
|
||||
err := rows.Scan(&req.ID, &req.RequestTxt, &statusName)
|
||||
if err != nil {
|
||||
return nil, errs.NewInternalError(errs.DatabaseError, "failed to scan request", err)
|
||||
}
|
||||
requests = append(requests, req)
|
||||
}
|
||||
|
||||
return requests, nil
|
||||
}
|
||||
|
||||
func (r *requestRepository) GetByID(ctx context.Context, id uuid.UUID) (*model.Request, error) {
|
||||
query := r.qb.Select(
|
||||
"id", "user_id", "request_txt", "generated_tz", "final_tz",
|
||||
"generated_final_tz", "final_update_tz", "mailling_status_id", "created_at",
|
||||
).From("requests_for_suppliers").Where(sq.Eq{"id": id})
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return nil, errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
req := &model.Request{}
|
||||
err = r.pool.QueryRow(ctx, sqlQuery, args...).Scan(
|
||||
&req.ID, &req.UserID, &req.RequestTxt, &req.GeneratedTZ,
|
||||
&req.FinalTZ, &req.GeneratedFinalTZ, &req.FinalUpdateTZ,
|
||||
&req.MailingStatusID, &req.CreatedAt,
|
||||
)
|
||||
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, errs.NewBusinessError(errs.RequestNotFound, "request not found")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errs.NewInternalError(errs.DatabaseError, "failed to get request", err)
|
||||
}
|
||||
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func (r *requestRepository) GetDetailByID(ctx context.Context, id uuid.UUID) (*model.RequestDetail, error) {
|
||||
sqlQuery := `
|
||||
SELECT
|
||||
r.id AS request_id,
|
||||
r.request_txt AS title,
|
||||
r.final_update_tz AS mail_text,
|
||||
COALESCE(json_agg(
|
||||
json_build_object(
|
||||
'email', COALESCE(s.email, ''),
|
||||
'phone', COALESCE(s.phone, ''),
|
||||
'company_name', COALESCE(s.name, ''),
|
||||
'company_id', s.id,
|
||||
'url', COALESCE(s.url, '')
|
||||
)
|
||||
) FILTER (WHERE s.id IS NOT NULL), '[]') AS suppliers
|
||||
FROM requests_for_suppliers r
|
||||
LEFT JOIN suppliers s ON s.request_id = r.id
|
||||
WHERE r.id = $1
|
||||
GROUP BY r.id, r.request_txt, r.final_update_tz
|
||||
`
|
||||
|
||||
detail := &model.RequestDetail{}
|
||||
var suppliersJSON []byte
|
||||
|
||||
err := r.pool.QueryRow(ctx, sqlQuery, id).Scan(
|
||||
&detail.RequestID, &detail.Title, &detail.MailText, &suppliersJSON,
|
||||
)
|
||||
|
||||
if err == pgx.ErrNoRows {
|
||||
return nil, errs.NewBusinessError(errs.RequestNotFound, "request not found")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errs.NewInternalError(errs.DatabaseError, "failed to get request detail", err)
|
||||
}
|
||||
|
||||
if len(suppliersJSON) > 0 && string(suppliersJSON) != "[]" {
|
||||
if err := json.Unmarshal(suppliersJSON, &detail.Suppliers); err != nil {
|
||||
return nil, errs.NewInternalError(errs.DatabaseError, "failed to parse suppliers", err)
|
||||
}
|
||||
}
|
||||
|
||||
return detail, nil
|
||||
}
|
||||
|
||||
func (r *requestRepository) GetUserStatistics(ctx context.Context, userID int) (requestsCount, suppliersCount, createdTZ int, err error) {
|
||||
sqlQuery := `
|
||||
SELECT
|
||||
COUNT(DISTINCT r.id) AS requests_count,
|
||||
COUNT(s.id) AS suppliers_count,
|
||||
COUNT(r.request_txt) AS created_tz
|
||||
FROM requests_for_suppliers r
|
||||
LEFT JOIN suppliers s ON s.request_id = r.id
|
||||
WHERE r.user_id = $1
|
||||
`
|
||||
|
||||
err = r.pool.QueryRow(ctx, sqlQuery, userID).Scan(&requestsCount, &suppliersCount, &createdTZ)
|
||||
if err != nil {
|
||||
return 0, 0, 0, errs.NewInternalError(errs.DatabaseError, "failed to get statistics", err)
|
||||
}
|
||||
|
||||
return requestsCount, suppliersCount, createdTZ, nil
|
||||
}
|
||||
134
internal/repository/session.go
Normal file
134
internal/repository/session.go
Normal file
@@ -0,0 +1,134 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"smart-search-back/internal/model"
|
||||
errs "smart-search-back/pkg/errors"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
type sessionRepository struct {
|
||||
pool *pgxpool.Pool
|
||||
qb sq.StatementBuilderType
|
||||
}
|
||||
|
||||
func NewSessionRepository(pool *pgxpool.Pool) SessionRepository {
|
||||
return &sessionRepository{
|
||||
pool: pool,
|
||||
qb: sq.StatementBuilder.PlaceholderFormat(sq.Dollar),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *sessionRepository) Create(ctx context.Context, session *model.Session) error {
|
||||
query := r.qb.Insert("sessions").Columns(
|
||||
"user_id", "access_token", "refresh_token", "ip", "user_agent", "expires_at",
|
||||
).Values(
|
||||
session.UserID, session.AccessToken, session.RefreshToken,
|
||||
session.IP, session.UserAgent, session.ExpiresAt,
|
||||
).Suffix("RETURNING id")
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
err = r.pool.QueryRow(ctx, sqlQuery, args...).Scan(&session.ID)
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to create session", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *sessionRepository) FindByRefreshToken(ctx context.Context, token string) (*model.Session, error) {
|
||||
query := r.qb.Select(
|
||||
"id", "user_id", "access_token", "refresh_token", "ip",
|
||||
"user_agent", "created_at", "expires_at", "revoked_at",
|
||||
).From("sessions").Where(sq.And{
|
||||
sq.Eq{"refresh_token": token},
|
||||
sq.Expr("revoked_at IS NULL"),
|
||||
sq.Expr("expires_at > now()"),
|
||||
})
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return nil, errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
session := &model.Session{}
|
||||
err = r.pool.QueryRow(ctx, sqlQuery, args...).Scan(
|
||||
&session.ID, &session.UserID, &session.AccessToken, &session.RefreshToken,
|
||||
&session.IP, &session.UserAgent, &session.CreatedAt, &session.ExpiresAt,
|
||||
&session.RevokedAt,
|
||||
)
|
||||
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, errs.NewBusinessError(errs.RefreshInvalid, "refresh token is invalid or expired")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errs.NewInternalError(errs.DatabaseError, "failed to find session", err)
|
||||
}
|
||||
|
||||
return session, nil
|
||||
}
|
||||
|
||||
func (r *sessionRepository) UpdateAccessToken(ctx context.Context, refreshToken, newAccessToken string) error {
|
||||
query := r.qb.Update("sessions").
|
||||
Set("access_token", newAccessToken).
|
||||
Where(sq.Eq{"refresh_token": refreshToken})
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
_, err = r.pool.Exec(ctx, sqlQuery, args...)
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to update access token", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *sessionRepository) Revoke(ctx context.Context, refreshToken string) error {
|
||||
query := r.qb.Update("sessions").
|
||||
Set("revoked_at", time.Now()).
|
||||
Where(sq.Eq{"refresh_token": refreshToken})
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
_, err = r.pool.Exec(ctx, sqlQuery, args...)
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to revoke session", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *sessionRepository) DeleteExpired(ctx context.Context) (int, error) {
|
||||
query := r.qb.Delete("sessions").Where(sq.Or{
|
||||
sq.Expr("expires_at < now()"),
|
||||
sq.Expr("(revoked_at IS NOT NULL AND revoked_at < now() - interval '30 days')"),
|
||||
})
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return 0, errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
result, err := r.pool.Exec(ctx, sqlQuery, args...)
|
||||
if err != nil {
|
||||
return 0, errs.NewInternalError(errs.DatabaseError, "failed to delete expired sessions", err)
|
||||
}
|
||||
|
||||
return int(result.RowsAffected()), nil
|
||||
}
|
||||
97
internal/repository/supplier.go
Normal file
97
internal/repository/supplier.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"smart-search-back/internal/model"
|
||||
errs "smart-search-back/pkg/errors"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
type supplierRepository struct {
|
||||
pool *pgxpool.Pool
|
||||
qb sq.StatementBuilderType
|
||||
}
|
||||
|
||||
func NewSupplierRepository(pool *pgxpool.Pool) SupplierRepository {
|
||||
return &supplierRepository{
|
||||
pool: pool,
|
||||
qb: sq.StatementBuilder.PlaceholderFormat(sq.Dollar),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *supplierRepository) BulkInsert(ctx context.Context, requestID uuid.UUID, suppliers []*model.Supplier) error {
|
||||
if len(suppliers) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
query := r.qb.Insert("suppliers").Columns(
|
||||
"request_id", "name", "email", "phone", "adress", "url",
|
||||
)
|
||||
|
||||
for _, s := range suppliers {
|
||||
query = query.Values(requestID, s.Name, s.Email, s.Phone, s.Address, s.URL)
|
||||
}
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
_, err = r.pool.Exec(ctx, sqlQuery, args...)
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to bulk insert suppliers", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *supplierRepository) GetByRequestID(ctx context.Context, requestID uuid.UUID) ([]*model.Supplier, error) {
|
||||
query := r.qb.Select(
|
||||
"id", "request_id", "name", "email", "phone", "adress", "url", "created_at",
|
||||
).From("suppliers").Where(sq.Eq{"request_id": requestID}).OrderBy("id")
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return nil, errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
rows, err := r.pool.Query(ctx, sqlQuery, args...)
|
||||
if err != nil {
|
||||
return nil, errs.NewInternalError(errs.DatabaseError, "failed to get suppliers", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var suppliers []*model.Supplier
|
||||
for rows.Next() {
|
||||
s := &model.Supplier{}
|
||||
err := rows.Scan(
|
||||
&s.ID, &s.RequestID, &s.Name, &s.Email, &s.Phone, &s.Address, &s.URL, &s.CreatedAt,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, errs.NewInternalError(errs.DatabaseError, "failed to scan supplier", err)
|
||||
}
|
||||
suppliers = append(suppliers, s)
|
||||
}
|
||||
|
||||
return suppliers, nil
|
||||
}
|
||||
|
||||
func (r *supplierRepository) DeleteByRequestID(ctx context.Context, requestID uuid.UUID) error {
|
||||
query := r.qb.Delete("suppliers").Where(sq.Eq{"request_id": requestID})
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
_, err = r.pool.Exec(ctx, sqlQuery, args...)
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to delete suppliers", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
43
internal/repository/token_usage.go
Normal file
43
internal/repository/token_usage.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"smart-search-back/internal/model"
|
||||
errs "smart-search-back/pkg/errors"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
type tokenUsageRepository struct {
|
||||
pool *pgxpool.Pool
|
||||
qb sq.StatementBuilderType
|
||||
}
|
||||
|
||||
func NewTokenUsageRepository(pool *pgxpool.Pool) TokenUsageRepository {
|
||||
return &tokenUsageRepository{
|
||||
pool: pool,
|
||||
qb: sq.StatementBuilder.PlaceholderFormat(sq.Dollar),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *tokenUsageRepository) Create(ctx context.Context, usage *model.TokenUsage) error {
|
||||
query := r.qb.Insert("request_token_usage").Columns(
|
||||
"request_id", "request_token_count", "response_token_count", "token_cost", "type",
|
||||
).Values(
|
||||
usage.RequestID, usage.RequestTokenCount, usage.ResponseTokenCount, usage.TokenCost, usage.Type,
|
||||
).Suffix("RETURNING id, created_at")
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
err = r.pool.QueryRow(ctx, sqlQuery, args...).Scan(&usage.ID, &usage.CreatedAt)
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to create token usage", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
199
internal/repository/user.go
Normal file
199
internal/repository/user.go
Normal file
@@ -0,0 +1,199 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"smart-search-back/internal/model"
|
||||
"smart-search-back/pkg/crypto"
|
||||
errs "smart-search-back/pkg/errors"
|
||||
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
type userRepository struct {
|
||||
pool *pgxpool.Pool
|
||||
qb sq.StatementBuilderType
|
||||
cryptoHelper *crypto.Crypto
|
||||
}
|
||||
|
||||
func NewUserRepository(pool *pgxpool.Pool, cryptoSecret string) UserRepository {
|
||||
return &userRepository{
|
||||
pool: pool,
|
||||
qb: sq.StatementBuilder.PlaceholderFormat(sq.Dollar),
|
||||
cryptoHelper: crypto.NewCrypto(cryptoSecret),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *userRepository) FindByEmailHash(ctx context.Context, emailHash string) (*model.User, error) {
|
||||
query := r.qb.Select(
|
||||
"id", "email", "email_hash", "password_hash", "phone",
|
||||
"user_name", "company_name", "balance", "payment_status",
|
||||
"invites_issued", "invites_limit", "created_at",
|
||||
).From("users").Where(sq.Eq{"email_hash": emailHash})
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return nil, errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
user := &model.User{}
|
||||
err = r.pool.QueryRow(ctx, sqlQuery, args...).Scan(
|
||||
&user.ID, &user.Email, &user.EmailHash, &user.PasswordHash,
|
||||
&user.Phone, &user.UserName, &user.CompanyName, &user.Balance,
|
||||
&user.PaymentStatus, &user.InvitesIssued, &user.InvitesLimit, &user.CreatedAt,
|
||||
)
|
||||
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, errs.NewBusinessError(errs.UserNotFound, "user not found")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errs.NewInternalError(errs.DatabaseError, "failed to find user", err)
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (r *userRepository) FindByID(ctx context.Context, userID int) (*model.User, error) {
|
||||
query := r.qb.Select(
|
||||
"id", "email", "email_hash", "password_hash", "phone",
|
||||
"user_name", "company_name", "balance", "payment_status",
|
||||
"invites_issued", "invites_limit", "created_at",
|
||||
).From("users").Where(sq.Eq{"id": userID})
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return nil, errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
user := &model.User{}
|
||||
err = r.pool.QueryRow(ctx, sqlQuery, args...).Scan(
|
||||
&user.ID, &user.Email, &user.EmailHash, &user.PasswordHash,
|
||||
&user.Phone, &user.UserName, &user.CompanyName, &user.Balance,
|
||||
&user.PaymentStatus, &user.InvitesIssued, &user.InvitesLimit, &user.CreatedAt,
|
||||
)
|
||||
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, errs.NewBusinessError(errs.UserNotFound, "user not found")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errs.NewInternalError(errs.DatabaseError, "failed to find user", err)
|
||||
}
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (r *userRepository) Create(ctx context.Context, user *model.User) error {
|
||||
encryptedEmail, err := r.cryptoHelper.Encrypt(user.Email)
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.EncryptionError, "failed to encrypt email", err)
|
||||
}
|
||||
|
||||
encryptedPhone, err := r.cryptoHelper.Encrypt(user.Phone)
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.EncryptionError, "failed to encrypt phone", err)
|
||||
}
|
||||
|
||||
encryptedUserName, err := r.cryptoHelper.Encrypt(user.UserName)
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.EncryptionError, "failed to encrypt user name", err)
|
||||
}
|
||||
|
||||
query := r.qb.Insert("users").Columns(
|
||||
"email", "email_hash", "password_hash", "phone", "user_name",
|
||||
"company_name", "balance", "payment_status",
|
||||
).Values(
|
||||
encryptedEmail, user.EmailHash, user.PasswordHash, encryptedPhone,
|
||||
encryptedUserName, user.CompanyName, user.Balance, user.PaymentStatus,
|
||||
).Suffix("RETURNING id")
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
err = r.pool.QueryRow(ctx, sqlQuery, args...).Scan(&user.ID)
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to create user", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *userRepository) UpdateBalance(ctx context.Context, userID int, delta float64) error {
|
||||
query := r.qb.Update("users").
|
||||
Set("balance", sq.Expr("balance + ?", delta)).
|
||||
Where(sq.Eq{"id": userID})
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
_, err = r.pool.Exec(ctx, sqlQuery, args...)
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to update balance", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *userRepository) GetBalance(ctx context.Context, userID int) (float64, error) {
|
||||
query := r.qb.Select("balance").From("users").Where(sq.Eq{"id": userID})
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return 0, errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
var balance float64
|
||||
err = r.pool.QueryRow(ctx, sqlQuery, args...).Scan(&balance)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return 0, errs.NewBusinessError(errs.UserNotFound, "user not found")
|
||||
}
|
||||
if err != nil {
|
||||
return 0, errs.NewInternalError(errs.DatabaseError, "failed to get balance", err)
|
||||
}
|
||||
|
||||
return balance, nil
|
||||
}
|
||||
|
||||
func (r *userRepository) IncrementInvitesIssued(ctx context.Context, userID int) error {
|
||||
query := r.qb.Update("users").
|
||||
Set("invites_issued", sq.Expr("invites_issued + 1")).
|
||||
Where(sq.Eq{"id": userID})
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
_, err = r.pool.Exec(ctx, sqlQuery, args...)
|
||||
if err != nil {
|
||||
return errs.NewInternalError(errs.DatabaseError, "failed to increment invites issued", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *userRepository) CheckInviteLimit(ctx context.Context, userID int) (bool, error) {
|
||||
query := r.qb.Select("invites_issued", "invites_limit").
|
||||
From("users").
|
||||
Where(sq.Eq{"id": userID}).
|
||||
Suffix("FOR UPDATE")
|
||||
|
||||
sqlQuery, args, err := query.ToSql()
|
||||
if err != nil {
|
||||
return false, errs.NewInternalError(errs.DatabaseError, "failed to build query", err)
|
||||
}
|
||||
|
||||
var issued, limit int
|
||||
err = r.pool.QueryRow(ctx, sqlQuery, args...).Scan(&issued, &limit)
|
||||
if err != nil {
|
||||
return false, errs.NewInternalError(errs.DatabaseError, "failed to check invite limit", err)
|
||||
}
|
||||
|
||||
return issued < limit, nil
|
||||
}
|
||||
107
internal/service/auth.go
Normal file
107
internal/service/auth.go
Normal file
@@ -0,0 +1,107 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"smart-search-back/internal/model"
|
||||
"smart-search-back/internal/repository"
|
||||
"smart-search-back/pkg/crypto"
|
||||
"smart-search-back/pkg/errors"
|
||||
"smart-search-back/pkg/jwt"
|
||||
)
|
||||
|
||||
type authService struct {
|
||||
userRepo repository.UserRepository
|
||||
sessionRepo repository.SessionRepository
|
||||
jwtSecret string
|
||||
cryptoHelper *crypto.Crypto
|
||||
}
|
||||
|
||||
func NewAuthService(userRepo repository.UserRepository, sessionRepo repository.SessionRepository, jwtSecret, cryptoSecret string) AuthService {
|
||||
return &authService{
|
||||
userRepo: userRepo,
|
||||
sessionRepo: sessionRepo,
|
||||
jwtSecret: jwtSecret,
|
||||
cryptoHelper: crypto.NewCrypto(cryptoSecret),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *authService) Login(ctx context.Context, email, password, ip, userAgent string) (accessToken, refreshToken string, err error) {
|
||||
emailHash := s.cryptoHelper.EmailHash(email)
|
||||
|
||||
user, err := s.userRepo.FindByEmailHash(ctx, emailHash)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
passwordHash := crypto.PasswordHash(password)
|
||||
if user.PasswordHash != passwordHash {
|
||||
return "", "", errors.NewBusinessError(errors.AuthInvalidCredentials, "Invalid email or password")
|
||||
}
|
||||
|
||||
accessToken, err = jwt.GenerateAccessToken(user.ID, s.jwtSecret)
|
||||
if err != nil {
|
||||
return "", "", errors.NewInternalError(errors.InternalError, "failed to generate access token", err)
|
||||
}
|
||||
|
||||
refreshToken, err = jwt.GenerateRefreshToken(user.ID, s.jwtSecret)
|
||||
if err != nil {
|
||||
return "", "", errors.NewInternalError(errors.InternalError, "failed to generate refresh token", err)
|
||||
}
|
||||
|
||||
session := &model.Session{
|
||||
UserID: user.ID,
|
||||
AccessToken: accessToken,
|
||||
RefreshToken: refreshToken,
|
||||
IP: ip,
|
||||
UserAgent: userAgent,
|
||||
ExpiresAt: time.Now().Add(30 * 24 * time.Hour),
|
||||
}
|
||||
|
||||
if err := s.sessionRepo.Create(ctx, session); err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
return accessToken, refreshToken, nil
|
||||
}
|
||||
|
||||
func (s *authService) Refresh(ctx context.Context, refreshToken string) (string, error) {
|
||||
session, err := s.sessionRepo.FindByRefreshToken(ctx, refreshToken)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
newAccessToken, err := jwt.GenerateAccessToken(session.UserID, s.jwtSecret)
|
||||
if err != nil {
|
||||
return "", errors.NewInternalError(errors.InternalError, "failed to generate access token", err)
|
||||
}
|
||||
|
||||
if err := s.sessionRepo.UpdateAccessToken(ctx, refreshToken, newAccessToken); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return newAccessToken, nil
|
||||
}
|
||||
|
||||
func (s *authService) Validate(ctx context.Context, accessToken string) (int, error) {
|
||||
claims, err := jwt.ValidateToken(accessToken, s.jwtSecret)
|
||||
if err != nil {
|
||||
return 0, errors.NewBusinessError(errors.AuthInvalidToken, "Invalid or expired token")
|
||||
}
|
||||
|
||||
if claims.Type != "access" {
|
||||
return 0, errors.NewBusinessError(errors.AuthInvalidToken, "Token is not an access token")
|
||||
}
|
||||
|
||||
userID, err := jwt.GetUserIDFromToken(accessToken, s.jwtSecret)
|
||||
if err != nil {
|
||||
return 0, errors.NewBusinessError(errors.AuthInvalidToken, "Invalid user ID in token")
|
||||
}
|
||||
|
||||
return userID, nil
|
||||
}
|
||||
|
||||
func (s *authService) Logout(ctx context.Context, refreshToken string) error {
|
||||
return s.sessionRepo.Revoke(ctx, refreshToken)
|
||||
}
|
||||
38
internal/service/interfaces.go
Normal file
38
internal/service/interfaces.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"smart-search-back/internal/model"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type AuthService interface {
|
||||
Login(ctx context.Context, email, password, ip, userAgent string) (accessToken, refreshToken string, err error)
|
||||
Refresh(ctx context.Context, refreshToken string) (string, error)
|
||||
Validate(ctx context.Context, accessToken string) (int, error)
|
||||
Logout(ctx context.Context, refreshToken string) error
|
||||
}
|
||||
|
||||
type UserService interface {
|
||||
GetInfo(ctx context.Context, userID int) (*UserInfo, error)
|
||||
GetBalance(ctx context.Context, userID int) (float64, error)
|
||||
GetStatistics(ctx context.Context, userID int) (*Statistics, error)
|
||||
}
|
||||
|
||||
type InviteService interface {
|
||||
Generate(ctx context.Context, userID, maxUses, ttlDays int) (*model.InviteCode, error)
|
||||
GetInfo(ctx context.Context, code int64) (*model.InviteCode, error)
|
||||
}
|
||||
|
||||
type RequestService interface {
|
||||
CreateTZ(ctx context.Context, userID int, requestTxt string) (uuid.UUID, string, error)
|
||||
ApproveTZ(ctx context.Context, requestID uuid.UUID, tzText string, userID int) ([]*model.Supplier, error)
|
||||
GetMailingList(ctx context.Context, userID int) ([]*model.Request, error)
|
||||
GetMailingListByID(ctx context.Context, requestID uuid.UUID) (*model.RequestDetail, error)
|
||||
}
|
||||
|
||||
type SupplierService interface {
|
||||
ExportExcel(ctx context.Context, requestID uuid.UUID) ([]byte, error)
|
||||
}
|
||||
57
internal/service/invite.go
Normal file
57
internal/service/invite.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"smart-search-back/internal/model"
|
||||
"smart-search-back/internal/repository"
|
||||
"smart-search-back/pkg/errors"
|
||||
)
|
||||
|
||||
type inviteService struct {
|
||||
inviteRepo repository.InviteRepository
|
||||
userRepo repository.UserRepository
|
||||
}
|
||||
|
||||
func NewInviteService(inviteRepo repository.InviteRepository, userRepo repository.UserRepository) InviteService {
|
||||
return &inviteService{
|
||||
inviteRepo: inviteRepo,
|
||||
userRepo: userRepo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *inviteService) Generate(ctx context.Context, userID, maxUses, ttlDays int) (*model.InviteCode, error) {
|
||||
canIssue, err := s.userRepo.CheckInviteLimit(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !canIssue {
|
||||
return nil, errors.NewBusinessError(errors.InviteLimitReached, "User reached maximum invite codes limit")
|
||||
}
|
||||
|
||||
code := rand.Int63n(90000000) + 10000000
|
||||
|
||||
invite := &model.InviteCode{
|
||||
UserID: userID,
|
||||
Code: code,
|
||||
CanBeUsedCount: maxUses,
|
||||
ExpiresAt: time.Now().Add(time.Duration(ttlDays) * 24 * time.Hour),
|
||||
}
|
||||
|
||||
if err := s.inviteRepo.Create(ctx, invite); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := s.userRepo.IncrementInvitesIssued(ctx, userID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return invite, nil
|
||||
}
|
||||
|
||||
func (s *inviteService) GetInfo(ctx context.Context, code int64) (*model.InviteCode, error) {
|
||||
return s.inviteRepo.FindByCode(ctx, code)
|
||||
}
|
||||
154
internal/service/request.go
Normal file
154
internal/service/request.go
Normal file
@@ -0,0 +1,154 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"smart-search-back/internal/ai"
|
||||
"smart-search-back/internal/model"
|
||||
"smart-search-back/internal/repository"
|
||||
"smart-search-back/pkg/errors"
|
||||
)
|
||||
|
||||
type requestService struct {
|
||||
requestRepo repository.RequestRepository
|
||||
supplierRepo repository.SupplierRepository
|
||||
tokenUsageRepo repository.TokenUsageRepository
|
||||
userRepo repository.UserRepository
|
||||
openAI *ai.OpenAIClient
|
||||
perplexity *ai.PerplexityClient
|
||||
}
|
||||
|
||||
func NewRequestService(
|
||||
requestRepo repository.RequestRepository,
|
||||
supplierRepo repository.SupplierRepository,
|
||||
tokenUsageRepo repository.TokenUsageRepository,
|
||||
userRepo repository.UserRepository,
|
||||
openAI *ai.OpenAIClient,
|
||||
perplexity *ai.PerplexityClient,
|
||||
) RequestService {
|
||||
return &requestService{
|
||||
requestRepo: requestRepo,
|
||||
supplierRepo: supplierRepo,
|
||||
tokenUsageRepo: tokenUsageRepo,
|
||||
userRepo: userRepo,
|
||||
openAI: openAI,
|
||||
perplexity: perplexity,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *requestService) CreateTZ(ctx context.Context, userID int, requestTxt string) (uuid.UUID, string, error) {
|
||||
req := &model.Request{
|
||||
UserID: userID,
|
||||
RequestTxt: requestTxt,
|
||||
}
|
||||
|
||||
if err := s.requestRepo.Create(ctx, req); err != nil {
|
||||
return uuid.Nil, "", err
|
||||
}
|
||||
|
||||
if requestTxt == "" {
|
||||
return req.ID, "", nil
|
||||
}
|
||||
|
||||
tzText, err := s.openAI.GenerateTZ(requestTxt)
|
||||
if err != nil {
|
||||
if err := s.requestRepo.UpdateWithTZ(ctx, req.ID, "", false); err != nil {
|
||||
return req.ID, "", err
|
||||
}
|
||||
return req.ID, "", err
|
||||
}
|
||||
|
||||
inputLen := len(requestTxt)
|
||||
outputLen := len(tzText)
|
||||
promptTokens := 500
|
||||
|
||||
inputTokens := int(math.Ceil(float64(inputLen) / 2.0))
|
||||
outputTokens := int(math.Ceil(float64(outputLen) / 2.0))
|
||||
|
||||
totalTokens := inputTokens + outputTokens + promptTokens
|
||||
tokenPrice := 25000.0 / 1000000.0
|
||||
cost := float64(totalTokens) * tokenPrice
|
||||
|
||||
tokenUsage := &model.TokenUsage{
|
||||
RequestID: req.ID,
|
||||
RequestTokenCount: inputTokens + promptTokens,
|
||||
ResponseTokenCount: outputTokens,
|
||||
TokenCost: cost,
|
||||
Type: "tz",
|
||||
}
|
||||
|
||||
if err := s.tokenUsageRepo.Create(ctx, tokenUsage); err != nil {
|
||||
return req.ID, "", err
|
||||
}
|
||||
|
||||
if err := s.userRepo.UpdateBalance(ctx, userID, -cost); err != nil {
|
||||
return req.ID, "", err
|
||||
}
|
||||
|
||||
if err := s.requestRepo.UpdateWithTZ(ctx, req.ID, tzText, true); err != nil {
|
||||
return req.ID, "", err
|
||||
}
|
||||
|
||||
return req.ID, tzText, nil
|
||||
}
|
||||
|
||||
func (s *requestService) ApproveTZ(ctx context.Context, requestID uuid.UUID, tzText string, userID int) ([]*model.Supplier, error) {
|
||||
if err := s.requestRepo.UpdateFinalTZ(ctx, requestID, tzText); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var suppliers []*model.Supplier
|
||||
var promptTokens, responseTokens int
|
||||
var err error
|
||||
|
||||
for attempt := 0; attempt < 3; attempt++ {
|
||||
suppliers, promptTokens, responseTokens, err = s.perplexity.FindSuppliers(tzText)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(suppliers) == 0 {
|
||||
return nil, errors.NewInternalError(errors.AIAPIError, "no suppliers found", nil)
|
||||
}
|
||||
|
||||
if err := s.supplierRepo.BulkInsert(ctx, requestID, suppliers); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tokenPrice := 25000.0 / 1000000.0
|
||||
totalTokens := promptTokens + responseTokens
|
||||
cost := float64(totalTokens) * tokenPrice
|
||||
|
||||
tokenUsage := &model.TokenUsage{
|
||||
RequestID: requestID,
|
||||
RequestTokenCount: promptTokens,
|
||||
ResponseTokenCount: responseTokens,
|
||||
TokenCost: cost,
|
||||
Type: "suppliers",
|
||||
}
|
||||
|
||||
if err := s.tokenUsageRepo.Create(ctx, tokenUsage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := s.userRepo.UpdateBalance(ctx, userID, -cost); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return suppliers, nil
|
||||
}
|
||||
|
||||
func (s *requestService) GetMailingList(ctx context.Context, userID int) ([]*model.Request, error) {
|
||||
return s.requestRepo.GetByUserID(ctx, userID)
|
||||
}
|
||||
|
||||
func (s *requestService) GetMailingListByID(ctx context.Context, requestID uuid.UUID) (*model.RequestDetail, error) {
|
||||
return s.requestRepo.GetDetailByID(ctx, requestID)
|
||||
}
|
||||
75
internal/service/supplier.go
Normal file
75
internal/service/supplier.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/xuri/excelize/v2"
|
||||
"smart-search-back/internal/repository"
|
||||
)
|
||||
|
||||
type supplierService struct {
|
||||
supplierRepo repository.SupplierRepository
|
||||
}
|
||||
|
||||
func NewSupplierService(supplierRepo repository.SupplierRepository) SupplierService {
|
||||
return &supplierService{
|
||||
supplierRepo: supplierRepo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *supplierService) ExportExcel(ctx context.Context, requestID uuid.UUID) ([]byte, error) {
|
||||
suppliers, err := s.supplierRepo.GetByRequestID(ctx, requestID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
f := excelize.NewFile()
|
||||
defer f.Close()
|
||||
|
||||
sheetName := "Suppliers"
|
||||
index, err := f.NewSheet(sheetName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
headers := []string{"Company ID", "Email", "Phone", "Company Name", "URL"}
|
||||
for i, header := range headers {
|
||||
cell := fmt.Sprintf("%c1", 'A'+i)
|
||||
f.SetCellValue(sheetName, cell, header)
|
||||
}
|
||||
|
||||
style, err := f.NewStyle(&excelize.Style{
|
||||
Font: &excelize.Font{Bold: true},
|
||||
Fill: excelize.Fill{Type: "pattern", Color: []string{"#E0E0E0"}, Pattern: 1},
|
||||
})
|
||||
if err == nil {
|
||||
f.SetCellStyle(sheetName, "A1", fmt.Sprintf("%c1", 'A'+len(headers)-1), style)
|
||||
}
|
||||
|
||||
for i, supplier := range suppliers {
|
||||
row := i + 2
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("A%d", row), supplier.ID)
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("B%d", row), supplier.Email)
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("C%d", row), supplier.Phone)
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("D%d", row), supplier.Name)
|
||||
f.SetCellValue(sheetName, fmt.Sprintf("E%d", row), supplier.URL)
|
||||
}
|
||||
|
||||
f.SetColWidth(sheetName, "A", "A", 12)
|
||||
f.SetColWidth(sheetName, "B", "B", 30)
|
||||
f.SetColWidth(sheetName, "C", "C", 20)
|
||||
f.SetColWidth(sheetName, "D", "D", 40)
|
||||
f.SetColWidth(sheetName, "E", "E", 40)
|
||||
|
||||
f.SetActiveSheet(index)
|
||||
f.DeleteSheet("Sheet1")
|
||||
|
||||
buffer, err := f.WriteToBuffer()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buffer.Bytes(), nil
|
||||
}
|
||||
449
internal/service/tests/auth_suite_test.go
Normal file
449
internal/service/tests/auth_suite_test.go
Normal file
@@ -0,0 +1,449 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gojuno/minimock/v3"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"smart-search-back/internal/mocks"
|
||||
"smart-search-back/internal/model"
|
||||
"smart-search-back/internal/service"
|
||||
"smart-search-back/pkg/crypto"
|
||||
apperrors "smart-search-back/pkg/errors"
|
||||
"smart-search-back/pkg/jwt"
|
||||
)
|
||||
|
||||
type Suite struct {
|
||||
suite.Suite
|
||||
|
||||
ctx context.Context
|
||||
authService service.AuthService
|
||||
userRepo *mocks.UserRepositoryMock
|
||||
sessionRepo *mocks.SessionRepositoryMock
|
||||
}
|
||||
|
||||
func newSuite(ctx context.Context) *Suite {
|
||||
return &Suite{ctx: ctx}
|
||||
}
|
||||
|
||||
func TestAuthService(t *testing.T) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
suite.Run(t, newSuite(ctx))
|
||||
}
|
||||
|
||||
func (s *Suite) SetupSuite() {
|
||||
s.ctx = context.Background()
|
||||
}
|
||||
|
||||
func (s *Suite) SetupTest() {
|
||||
ctrl := minimock.NewController(s.T())
|
||||
|
||||
s.userRepo = mocks.NewUserRepositoryMock(ctrl)
|
||||
s.sessionRepo = mocks.NewSessionRepositoryMock(ctrl)
|
||||
|
||||
s.authService = service.NewAuthService(s.userRepo, s.sessionRepo)
|
||||
}
|
||||
|
||||
func createTestUser(password string) *model.User {
|
||||
return &model.User{
|
||||
ID: 1,
|
||||
Email: "test@example.com",
|
||||
EmailHash: crypto.EmailHash("test@example.com"),
|
||||
PasswordHash: crypto.PasswordHash(password),
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
func createTestSession(userID int) *model.Session {
|
||||
return &model.Session{
|
||||
ID: 1,
|
||||
UserID: userID,
|
||||
AccessToken: "test-access-token",
|
||||
RefreshToken: "test-refresh-token",
|
||||
IP: "127.0.0.1",
|
||||
UserAgent: "test-agent",
|
||||
CreatedAt: time.Now(),
|
||||
ExpiresAt: time.Now().Add(30 * 24 * time.Hour),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Login_Success() {
|
||||
password := "testpassword"
|
||||
user := createTestUser(password)
|
||||
|
||||
s.userRepo.FindByEmailHashMock.Return(user, nil)
|
||||
s.sessionRepo.CreateMock.Return(nil)
|
||||
|
||||
accessToken, refreshToken, err := s.authService.Login(
|
||||
s.ctx,
|
||||
"test@example.com",
|
||||
password,
|
||||
"127.0.0.1",
|
||||
"test-agent",
|
||||
)
|
||||
|
||||
s.NoError(err)
|
||||
s.NotEmpty(accessToken)
|
||||
s.NotEmpty(refreshToken)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Login_UserNotFound() {
|
||||
err := apperrors.NewBusinessError(apperrors.UserNotFound, "user not found")
|
||||
s.userRepo.FindByEmailHashMock.Return(nil, err)
|
||||
|
||||
accessToken, refreshToken, loginErr := s.authService.Login(
|
||||
s.ctx,
|
||||
"test@example.com",
|
||||
"password",
|
||||
"127.0.0.1",
|
||||
"test-agent",
|
||||
)
|
||||
|
||||
s.Error(loginErr)
|
||||
s.Empty(accessToken)
|
||||
s.Empty(refreshToken)
|
||||
|
||||
var appErr *apperrors.AppError
|
||||
s.True(errors.As(loginErr, &appErr))
|
||||
s.Equal(apperrors.UserNotFound, appErr.Code)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Login_DatabaseError_OnFindUser() {
|
||||
dbErr := apperrors.NewInternalError(apperrors.DatabaseError, "failed to find user", nil)
|
||||
s.userRepo.FindByEmailHashMock.Return(nil, dbErr)
|
||||
|
||||
accessToken, refreshToken, err := s.authService.Login(
|
||||
s.ctx,
|
||||
"test@example.com",
|
||||
"password",
|
||||
"127.0.0.1",
|
||||
"test-agent",
|
||||
)
|
||||
|
||||
s.Error(err)
|
||||
s.Empty(accessToken)
|
||||
s.Empty(refreshToken)
|
||||
|
||||
var appErr *apperrors.AppError
|
||||
s.True(errors.As(err, &appErr))
|
||||
s.Equal(apperrors.InternalErrorType, appErr.Type)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Login_InvalidPassword() {
|
||||
password := "correctpassword"
|
||||
user := createTestUser(password)
|
||||
s.userRepo.FindByEmailHashMock.Return(user, nil)
|
||||
|
||||
accessToken, refreshToken, err := s.authService.Login(
|
||||
s.ctx,
|
||||
"test@example.com",
|
||||
"wrongpassword",
|
||||
"127.0.0.1",
|
||||
"test-agent",
|
||||
)
|
||||
|
||||
s.Error(err)
|
||||
s.Empty(accessToken)
|
||||
s.Empty(refreshToken)
|
||||
|
||||
var appErr *apperrors.AppError
|
||||
s.True(errors.As(err, &appErr))
|
||||
s.Equal(apperrors.AuthInvalidCredentials, appErr.Code)
|
||||
s.Contains(appErr.Message, "Invalid email or password")
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Login_EmptyPassword() {
|
||||
user := createTestUser("")
|
||||
s.userRepo.FindByEmailHashMock.Return(user, nil)
|
||||
s.sessionRepo.CreateMock.Return(nil)
|
||||
|
||||
accessToken, refreshToken, err := s.authService.Login(
|
||||
s.ctx,
|
||||
"test@example.com",
|
||||
"",
|
||||
"127.0.0.1",
|
||||
"test-agent",
|
||||
)
|
||||
|
||||
s.NoError(err)
|
||||
s.NotEmpty(accessToken)
|
||||
s.NotEmpty(refreshToken)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Login_EmailWithSpacesAndCase() {
|
||||
password := "testpassword"
|
||||
normalizedEmail := "test@example.com"
|
||||
user := createTestUser(password)
|
||||
user.EmailHash = crypto.EmailHash(normalizedEmail)
|
||||
s.userRepo.FindByEmailHashMock.Return(user, nil)
|
||||
s.sessionRepo.CreateMock.Return(nil)
|
||||
|
||||
accessToken, refreshToken, err := s.authService.Login(
|
||||
s.ctx,
|
||||
" TEST@EXAMPLE.COM ",
|
||||
password,
|
||||
"127.0.0.1",
|
||||
"test-agent",
|
||||
)
|
||||
|
||||
s.NoError(err)
|
||||
s.NotEmpty(accessToken)
|
||||
s.NotEmpty(refreshToken)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Login_EmptyEmail() {
|
||||
err := apperrors.NewBusinessError(apperrors.UserNotFound, "user not found")
|
||||
s.userRepo.FindByEmailHashMock.Return(nil, err)
|
||||
|
||||
accessToken, refreshToken, loginErr := s.authService.Login(
|
||||
s.ctx,
|
||||
"",
|
||||
"password",
|
||||
"127.0.0.1",
|
||||
"test-agent",
|
||||
)
|
||||
|
||||
s.Error(loginErr)
|
||||
s.Empty(accessToken)
|
||||
s.Empty(refreshToken)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Login_SessionCreateError() {
|
||||
password := "testpassword"
|
||||
user := createTestUser(password)
|
||||
s.userRepo.FindByEmailHashMock.Return(user, nil)
|
||||
|
||||
dbErr := apperrors.NewInternalError(apperrors.DatabaseError, "failed to create session", nil)
|
||||
s.sessionRepo.CreateMock.Return(dbErr)
|
||||
|
||||
accessToken, refreshToken, err := s.authService.Login(
|
||||
s.ctx,
|
||||
"test@example.com",
|
||||
password,
|
||||
"127.0.0.1",
|
||||
"test-agent",
|
||||
)
|
||||
|
||||
s.Error(err)
|
||||
s.Empty(accessToken)
|
||||
s.Empty(refreshToken)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Login_EmptyIPAndUserAgent() {
|
||||
password := "testpassword"
|
||||
user := createTestUser(password)
|
||||
s.userRepo.FindByEmailHashMock.Return(user, nil)
|
||||
s.sessionRepo.CreateMock.Return(nil)
|
||||
|
||||
accessToken, refreshToken, err := s.authService.Login(
|
||||
s.ctx,
|
||||
"test@example.com",
|
||||
password,
|
||||
"",
|
||||
"",
|
||||
)
|
||||
|
||||
s.NoError(err)
|
||||
s.NotEmpty(accessToken)
|
||||
s.NotEmpty(refreshToken)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Refresh_Success() {
|
||||
session := createTestSession(1)
|
||||
s.sessionRepo.FindByRefreshTokenMock.Return(session, nil)
|
||||
s.sessionRepo.UpdateAccessTokenMock.Return(nil)
|
||||
|
||||
accessToken, err := s.authService.Refresh(s.ctx, "test-refresh-token")
|
||||
|
||||
s.NoError(err)
|
||||
s.NotEmpty(accessToken)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Refresh_RefreshInvalid() {
|
||||
err := apperrors.NewBusinessError(apperrors.RefreshInvalid, "refresh token is invalid or expired")
|
||||
s.sessionRepo.FindByRefreshTokenMock.Return(nil, err)
|
||||
|
||||
accessToken, refreshErr := s.authService.Refresh(s.ctx, "invalid-token")
|
||||
|
||||
s.Error(refreshErr)
|
||||
s.Empty(accessToken)
|
||||
|
||||
var appErr *apperrors.AppError
|
||||
s.True(errors.As(refreshErr, &appErr))
|
||||
s.Equal(apperrors.RefreshInvalid, appErr.Code)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Refresh_DatabaseError_OnFindSession() {
|
||||
dbErr := apperrors.NewInternalError(apperrors.DatabaseError, "failed to find session", nil)
|
||||
s.sessionRepo.FindByRefreshTokenMock.Return(nil, dbErr)
|
||||
|
||||
accessToken, err := s.authService.Refresh(s.ctx, "test-refresh-token")
|
||||
|
||||
s.Error(err)
|
||||
s.Empty(accessToken)
|
||||
|
||||
var appErr *apperrors.AppError
|
||||
s.True(errors.As(err, &appErr))
|
||||
s.Equal(apperrors.InternalErrorType, appErr.Type)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Refresh_EmptyToken() {
|
||||
err := apperrors.NewBusinessError(apperrors.RefreshInvalid, "refresh token is invalid or expired")
|
||||
s.sessionRepo.FindByRefreshTokenMock.Return(nil, err)
|
||||
|
||||
accessToken, refreshErr := s.authService.Refresh(s.ctx, "")
|
||||
|
||||
s.Error(refreshErr)
|
||||
s.Empty(accessToken)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Refresh_UpdateAccessTokenError() {
|
||||
session := createTestSession(1)
|
||||
s.sessionRepo.FindByRefreshTokenMock.Return(session, nil)
|
||||
|
||||
dbErr := apperrors.NewInternalError(apperrors.DatabaseError, "failed to update access token", nil)
|
||||
s.sessionRepo.UpdateAccessTokenMock.Return(dbErr)
|
||||
|
||||
accessToken, err := s.authService.Refresh(s.ctx, "test-refresh-token")
|
||||
|
||||
s.Error(err)
|
||||
s.Empty(accessToken)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Refresh_UserIDZero() {
|
||||
session := createTestSession(0)
|
||||
s.sessionRepo.FindByRefreshTokenMock.Return(session, nil)
|
||||
s.sessionRepo.UpdateAccessTokenMock.Return(nil)
|
||||
|
||||
accessToken, err := s.authService.Refresh(s.ctx, "test-refresh-token")
|
||||
|
||||
s.NoError(err)
|
||||
s.NotEmpty(accessToken)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Validate_Success() {
|
||||
s.T().Parallel()
|
||||
|
||||
userID := 1
|
||||
accessToken, err := jwt.GenerateAccessToken(userID)
|
||||
s.NoError(err)
|
||||
|
||||
validatedUserID, validateErr := s.authService.Validate(s.ctx, accessToken)
|
||||
|
||||
s.NoError(validateErr)
|
||||
s.Equal(userID, validatedUserID)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Validate_EmptyToken() {
|
||||
s.T().Parallel()
|
||||
|
||||
userID, err := s.authService.Validate(s.ctx, "")
|
||||
|
||||
s.Error(err)
|
||||
s.Equal(0, userID)
|
||||
|
||||
var appErr *apperrors.AppError
|
||||
s.True(errors.As(err, &appErr))
|
||||
s.Equal(apperrors.AuthInvalidToken, appErr.Code)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Validate_InvalidTokenFormat() {
|
||||
s.T().Parallel()
|
||||
|
||||
userID, err := s.authService.Validate(s.ctx, "invalid.token.format")
|
||||
|
||||
s.Error(err)
|
||||
s.Equal(0, userID)
|
||||
|
||||
var appErr *apperrors.AppError
|
||||
s.True(errors.As(err, &appErr))
|
||||
s.Equal(apperrors.AuthInvalidToken, appErr.Code)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Validate_RefreshTokenInsteadOfAccess() {
|
||||
s.T().Parallel()
|
||||
|
||||
userID := 1
|
||||
refreshToken, err := jwt.GenerateRefreshToken(userID)
|
||||
s.NoError(err)
|
||||
|
||||
validatedUserID, validateErr := s.authService.Validate(s.ctx, refreshToken)
|
||||
|
||||
s.Error(validateErr)
|
||||
s.Equal(0, validatedUserID)
|
||||
|
||||
var appErr *apperrors.AppError
|
||||
s.True(errors.As(validateErr, &appErr))
|
||||
s.Equal(apperrors.AuthInvalidToken, appErr.Code)
|
||||
s.Contains(appErr.Message, "not an access token")
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Validate_UserIDZero() {
|
||||
s.T().Parallel()
|
||||
|
||||
accessToken, err := jwt.GenerateAccessToken(0)
|
||||
s.NoError(err)
|
||||
|
||||
validatedUserID, validateErr := s.authService.Validate(s.ctx, accessToken)
|
||||
|
||||
s.NoError(validateErr)
|
||||
s.Equal(0, validatedUserID)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Validate_InvalidSignature() {
|
||||
s.T().Parallel()
|
||||
|
||||
invalidToken := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIiwidHlwZSI6ImFjY2VzcyIsImlhdCI6MTYwOTQ1NjgwMCwiZXhwIjoxNjA5NDY1ODAwfQ.invalid-signature"
|
||||
|
||||
userID, err := s.authService.Validate(s.ctx, invalidToken)
|
||||
|
||||
s.Error(err)
|
||||
s.Equal(0, userID)
|
||||
|
||||
var appErr *apperrors.AppError
|
||||
s.True(errors.As(err, &appErr))
|
||||
s.Equal(apperrors.AuthInvalidToken, appErr.Code)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Logout_Success() {
|
||||
s.sessionRepo.RevokeMock.Return(nil)
|
||||
|
||||
err := s.authService.Logout(s.ctx, "test-refresh-token")
|
||||
|
||||
s.NoError(err)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Logout_DatabaseError() {
|
||||
dbErr := apperrors.NewInternalError(apperrors.DatabaseError, "failed to revoke session", nil)
|
||||
s.sessionRepo.RevokeMock.Return(dbErr)
|
||||
|
||||
err := s.authService.Logout(s.ctx, "test-refresh-token")
|
||||
|
||||
s.Error(err)
|
||||
|
||||
var appErr *apperrors.AppError
|
||||
s.True(errors.As(err, &appErr))
|
||||
s.Equal(apperrors.InternalErrorType, appErr.Type)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Logout_EmptyToken() {
|
||||
s.sessionRepo.RevokeMock.Return(nil)
|
||||
|
||||
err := s.authService.Logout(s.ctx, "")
|
||||
|
||||
s.NoError(err)
|
||||
}
|
||||
|
||||
func (s *Suite) TestAuthService_Logout_NonExistentToken() {
|
||||
s.sessionRepo.RevokeMock.Return(nil)
|
||||
|
||||
err := s.authService.Logout(s.ctx, "non-existent-token")
|
||||
|
||||
s.NoError(err)
|
||||
}
|
||||
83
internal/service/user.go
Normal file
83
internal/service/user.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"smart-search-back/internal/repository"
|
||||
"smart-search-back/pkg/crypto"
|
||||
)
|
||||
|
||||
type userService struct {
|
||||
userRepo repository.UserRepository
|
||||
requestRepo repository.RequestRepository
|
||||
cryptoHelper *crypto.Crypto
|
||||
}
|
||||
|
||||
type UserInfo struct {
|
||||
Email string
|
||||
Name string
|
||||
Phone string
|
||||
CompanyName string
|
||||
PaymentStatus string
|
||||
}
|
||||
|
||||
type Statistics struct {
|
||||
RequestsCount int
|
||||
SuppliersCount int
|
||||
CreatedTZ int
|
||||
}
|
||||
|
||||
func NewUserService(userRepo repository.UserRepository, requestRepo repository.RequestRepository, cryptoSecret string) UserService {
|
||||
return &userService{
|
||||
userRepo: userRepo,
|
||||
requestRepo: requestRepo,
|
||||
cryptoHelper: crypto.NewCrypto(cryptoSecret),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *userService) GetInfo(ctx context.Context, userID int) (*UserInfo, error) {
|
||||
user, err := s.userRepo.FindByID(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
email, err := s.cryptoHelper.Decrypt(user.Email)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
phone, err := s.cryptoHelper.Decrypt(user.Phone)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
userName, err := s.cryptoHelper.Decrypt(user.UserName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &UserInfo{
|
||||
Email: email,
|
||||
Name: userName,
|
||||
Phone: phone,
|
||||
CompanyName: user.CompanyName,
|
||||
PaymentStatus: user.PaymentStatus,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *userService) GetBalance(ctx context.Context, userID int) (float64, error) {
|
||||
return s.userRepo.GetBalance(ctx, userID)
|
||||
}
|
||||
|
||||
func (s *userService) GetStatistics(ctx context.Context, userID int) (*Statistics, error) {
|
||||
requestsCount, suppliersCount, createdTZ, err := s.requestRepo.GetUserStatistics(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Statistics{
|
||||
RequestsCount: requestsCount,
|
||||
SuppliersCount: suppliersCount,
|
||||
CreatedTZ: createdTZ,
|
||||
}, nil
|
||||
}
|
||||
69
internal/worker/invite_cleaner.go
Normal file
69
internal/worker/invite_cleaner.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package worker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"smart-search-back/internal/repository"
|
||||
)
|
||||
|
||||
type InviteCleaner struct {
|
||||
inviteRepo repository.InviteRepository
|
||||
ctx context.Context
|
||||
ticker *time.Ticker
|
||||
done chan bool
|
||||
}
|
||||
|
||||
func NewInviteCleaner(ctx context.Context, inviteRepo repository.InviteRepository) *InviteCleaner {
|
||||
return &InviteCleaner{
|
||||
inviteRepo: inviteRepo,
|
||||
ctx: ctx,
|
||||
done: make(chan bool),
|
||||
}
|
||||
}
|
||||
|
||||
func (w *InviteCleaner) Start() {
|
||||
w.ticker = time.NewTicker(6 * time.Hour)
|
||||
|
||||
w.deactivateExpiredInvites()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-w.ticker.C:
|
||||
w.deactivateExpiredInvites()
|
||||
case <-w.done:
|
||||
return
|
||||
case <-w.ctx.Done():
|
||||
log.Println("Invite cleaner context cancelled, stopping worker")
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
log.Println("Invite cleaner worker started (runs every 6 hours)")
|
||||
}
|
||||
|
||||
func (w *InviteCleaner) Stop() {
|
||||
if w.ticker != nil {
|
||||
w.ticker.Stop()
|
||||
}
|
||||
select {
|
||||
case w.done <- true:
|
||||
default:
|
||||
}
|
||||
log.Println("Invite cleaner worker stopped")
|
||||
}
|
||||
|
||||
func (w *InviteCleaner) deactivateExpiredInvites() {
|
||||
count, err := w.inviteRepo.DeactivateExpired(w.ctx)
|
||||
if err != nil {
|
||||
log.Printf("Error deactivating expired invites: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
log.Printf("Deactivated %d expired invite codes", count)
|
||||
}
|
||||
}
|
||||
69
internal/worker/session_cleaner.go
Normal file
69
internal/worker/session_cleaner.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package worker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"smart-search-back/internal/repository"
|
||||
)
|
||||
|
||||
type SessionCleaner struct {
|
||||
sessionRepo repository.SessionRepository
|
||||
ctx context.Context
|
||||
ticker *time.Ticker
|
||||
done chan bool
|
||||
}
|
||||
|
||||
func NewSessionCleaner(ctx context.Context, sessionRepo repository.SessionRepository) *SessionCleaner {
|
||||
return &SessionCleaner{
|
||||
sessionRepo: sessionRepo,
|
||||
ctx: ctx,
|
||||
done: make(chan bool),
|
||||
}
|
||||
}
|
||||
|
||||
func (w *SessionCleaner) Start() {
|
||||
w.ticker = time.NewTicker(1 * time.Hour)
|
||||
|
||||
w.cleanExpiredSessions()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-w.ticker.C:
|
||||
w.cleanExpiredSessions()
|
||||
case <-w.done:
|
||||
return
|
||||
case <-w.ctx.Done():
|
||||
log.Println("Session cleaner context cancelled, stopping worker")
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
log.Println("Session cleaner worker started (runs every hour)")
|
||||
}
|
||||
|
||||
func (w *SessionCleaner) Stop() {
|
||||
if w.ticker != nil {
|
||||
w.ticker.Stop()
|
||||
}
|
||||
select {
|
||||
case w.done <- true:
|
||||
default:
|
||||
}
|
||||
log.Println("Session cleaner worker stopped")
|
||||
}
|
||||
|
||||
func (w *SessionCleaner) cleanExpiredSessions() {
|
||||
count, err := w.sessionRepo.DeleteExpired(w.ctx)
|
||||
if err != nil {
|
||||
log.Printf("Error cleaning expired sessions: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if count > 0 {
|
||||
log.Printf("Cleaned %d expired sessions", count)
|
||||
}
|
||||
}
|
||||
20
migrations/00001_create_users.sql
Normal file
20
migrations/00001_create_users.sql
Normal file
@@ -0,0 +1,20 @@
|
||||
-- +goose Up
|
||||
CREATE TABLE users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
email TEXT NOT NULL,
|
||||
email_hash TEXT NOT NULL UNIQUE,
|
||||
password_hash TEXT NOT NULL,
|
||||
phone TEXT,
|
||||
user_name TEXT,
|
||||
company_name TEXT,
|
||||
balance NUMERIC(10, 5) DEFAULT 0.0,
|
||||
payment_status TEXT DEFAULT 'unpaid',
|
||||
invites_issued INT DEFAULT 0,
|
||||
invites_limit INT DEFAULT 10,
|
||||
created_at TIMESTAMP DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_users_email_hash ON users(email_hash);
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE users;
|
||||
18
migrations/00002_create_sessions.sql
Normal file
18
migrations/00002_create_sessions.sql
Normal file
@@ -0,0 +1,18 @@
|
||||
-- +goose Up
|
||||
CREATE TABLE sessions (
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
access_token TEXT NOT NULL,
|
||||
refresh_token TEXT NOT NULL UNIQUE,
|
||||
ip TEXT,
|
||||
user_agent TEXT,
|
||||
created_at TIMESTAMP DEFAULT now(),
|
||||
expires_at TIMESTAMP NOT NULL,
|
||||
revoked_at TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX idx_sessions_refresh ON sessions(refresh_token);
|
||||
CREATE INDEX idx_sessions_user_id ON sessions(user_id);
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE sessions;
|
||||
17
migrations/00003_create_invite_codes.sql
Normal file
17
migrations/00003_create_invite_codes.sql
Normal file
@@ -0,0 +1,17 @@
|
||||
-- +goose Up
|
||||
CREATE TABLE invite_codes (
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
code BIGINT NOT NULL UNIQUE,
|
||||
can_be_used_count INT DEFAULT 10,
|
||||
used_count INT DEFAULT 0,
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
created_at TIMESTAMP DEFAULT now(),
|
||||
expires_at TIMESTAMP NOT NULL
|
||||
);
|
||||
|
||||
CREATE INDEX idx_invite_codes_code ON invite_codes(code);
|
||||
CREATE INDEX idx_invite_codes_user_id ON invite_codes(user_id);
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE invite_codes;
|
||||
14
migrations/00004_create_mailing_status.sql
Normal file
14
migrations/00004_create_mailing_status.sql
Normal file
@@ -0,0 +1,14 @@
|
||||
-- +goose Up
|
||||
CREATE TABLE mailing_status (
|
||||
id SERIAL PRIMARY KEY,
|
||||
status_name TEXT NOT NULL UNIQUE
|
||||
);
|
||||
|
||||
INSERT INTO mailing_status (status_name) VALUES
|
||||
('pending'),
|
||||
('in_progress'),
|
||||
('completed'),
|
||||
('failed');
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE mailing_status;
|
||||
18
migrations/00005_create_requests_for_suppliers.sql
Normal file
18
migrations/00005_create_requests_for_suppliers.sql
Normal file
@@ -0,0 +1,18 @@
|
||||
-- +goose Up
|
||||
CREATE TABLE requests_for_suppliers (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
request_txt TEXT,
|
||||
generated_tz BOOLEAN DEFAULT false,
|
||||
final_tz TEXT,
|
||||
generated_final_tz BOOLEAN DEFAULT false,
|
||||
final_update_tz TEXT,
|
||||
mailling_status_id INT REFERENCES mailing_status(id) DEFAULT 1,
|
||||
created_at TIMESTAMP DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_requests_user_id ON requests_for_suppliers(user_id);
|
||||
CREATE INDEX idx_requests_status ON requests_for_suppliers(mailling_status_id);
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE requests_for_suppliers;
|
||||
16
migrations/00006_create_suppliers.sql
Normal file
16
migrations/00006_create_suppliers.sql
Normal file
@@ -0,0 +1,16 @@
|
||||
-- +goose Up
|
||||
CREATE TABLE suppliers (
|
||||
id SERIAL PRIMARY KEY,
|
||||
request_id UUID NOT NULL REFERENCES requests_for_suppliers(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
email TEXT,
|
||||
phone TEXT,
|
||||
adress TEXT,
|
||||
url TEXT,
|
||||
created_at TIMESTAMP DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_suppliers_request_id ON suppliers(request_id);
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE suppliers;
|
||||
15
migrations/00007_create_request_token_usage.sql
Normal file
15
migrations/00007_create_request_token_usage.sql
Normal file
@@ -0,0 +1,15 @@
|
||||
-- +goose Up
|
||||
CREATE TABLE request_token_usage (
|
||||
id SERIAL PRIMARY KEY,
|
||||
request_id UUID NOT NULL REFERENCES requests_for_suppliers(id) ON DELETE CASCADE,
|
||||
request_token_count INT DEFAULT 0,
|
||||
response_token_count INT DEFAULT 0,
|
||||
token_cost NUMERIC(10, 5) DEFAULT 0.0,
|
||||
type TEXT NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_token_usage_request_id ON request_token_usage(request_id);
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE request_token_usage;
|
||||
125
pkg/crypto/crypto.go
Normal file
125
pkg/crypto/crypto.go
Normal file
@@ -0,0 +1,125 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Crypto struct {
|
||||
secret string
|
||||
}
|
||||
|
||||
func NewCrypto(secret string) *Crypto {
|
||||
return &Crypto{secret: secret}
|
||||
}
|
||||
|
||||
func (c *Crypto) EmailHash(email string) string {
|
||||
if email == "" {
|
||||
return email
|
||||
}
|
||||
normalized := strings.TrimSpace(strings.ToLower(email))
|
||||
h := hmac.New(sha256.New, []byte(c.secret))
|
||||
h.Write([]byte(normalized))
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
func PasswordHash(password string) string {
|
||||
h := sha512.New()
|
||||
h.Write([]byte(password))
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
func (c *Crypto) getKey() []byte {
|
||||
h := sha256.New()
|
||||
h.Write([]byte(c.secret))
|
||||
return h.Sum(nil)
|
||||
}
|
||||
|
||||
func (c *Crypto) Encrypt(plaintext string) (string, error) {
|
||||
if plaintext == "" {
|
||||
return plaintext, nil
|
||||
}
|
||||
|
||||
key := c.getKey()
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create cipher: %w", err)
|
||||
}
|
||||
|
||||
aesGCM, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create GCM: %w", err)
|
||||
}
|
||||
|
||||
iv := make([]byte, aesGCM.NonceSize())
|
||||
if _, err := rand.Read(iv); err != nil {
|
||||
return "", fmt.Errorf("failed to generate IV: %w", err)
|
||||
}
|
||||
|
||||
ciphertext := aesGCM.Seal(nil, iv, []byte(plaintext), nil)
|
||||
|
||||
tag := ciphertext[len(ciphertext)-aesGCM.Overhead():]
|
||||
cipherOnly := ciphertext[:len(ciphertext)-aesGCM.Overhead()]
|
||||
|
||||
return fmt.Sprintf("%s:%s:%s",
|
||||
hex.EncodeToString(iv),
|
||||
hex.EncodeToString(tag),
|
||||
hex.EncodeToString(cipherOnly),
|
||||
), nil
|
||||
}
|
||||
|
||||
func (c *Crypto) Decrypt(ciphertext string) (string, error) {
|
||||
if ciphertext == "" {
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
parts := strings.Split(ciphertext, ":")
|
||||
if len(parts) != 3 {
|
||||
return "", errors.New("invalid encrypted value format")
|
||||
}
|
||||
|
||||
ivHex, tagHex, cipherHex := parts[0], parts[1], parts[2]
|
||||
|
||||
iv, err := hex.DecodeString(ivHex)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to decode IV: %w", err)
|
||||
}
|
||||
|
||||
tag, err := hex.DecodeString(tagHex)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to decode tag: %w", err)
|
||||
}
|
||||
|
||||
cipherOnly, err := hex.DecodeString(cipherHex)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to decode ciphertext: %w", err)
|
||||
}
|
||||
|
||||
key := c.getKey()
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create cipher: %w", err)
|
||||
}
|
||||
|
||||
aesGCM, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create GCM: %w", err)
|
||||
}
|
||||
|
||||
ciphertextWithTag := append(cipherOnly, tag...)
|
||||
|
||||
plaintext, err := aesGCM.Open(nil, iv, ciphertextWithTag, nil)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to decrypt: %w", err)
|
||||
}
|
||||
|
||||
return string(plaintext), nil
|
||||
}
|
||||
17
pkg/errors/codes.go
Normal file
17
pkg/errors/codes.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package errors
|
||||
|
||||
const (
|
||||
AuthInvalidCredentials = "AUTH_INVALID_CREDENTIALS"
|
||||
AuthMissing = "AUTH_MISSING"
|
||||
AuthInvalidToken = "AUTH_INVALID_TOKEN"
|
||||
RefreshInvalid = "REFRESH_INVALID"
|
||||
InviteLimitReached = "INVITE_LIMIT_REACHED"
|
||||
InsufficientBalance = "INSUFFICIENT_BALANCE"
|
||||
UserNotFound = "USER_NOT_FOUND"
|
||||
RequestNotFound = "REQUEST_NOT_FOUND"
|
||||
|
||||
DatabaseError = "DATABASE_ERROR"
|
||||
EncryptionError = "ENCRYPTION_ERROR"
|
||||
AIAPIError = "AI_API_ERROR"
|
||||
InternalError = "INTERNAL_ERROR"
|
||||
)
|
||||
95
pkg/errors/errors.go
Normal file
95
pkg/errors/errors.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
type ErrorType int
|
||||
|
||||
const (
|
||||
BusinessError ErrorType = iota
|
||||
InternalErrorType
|
||||
)
|
||||
|
||||
type AppError struct {
|
||||
Code string
|
||||
Message string
|
||||
Type ErrorType
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *AppError) Error() string {
|
||||
if e.Err != nil {
|
||||
return fmt.Sprintf("%s: %s (%v)", e.Code, e.Message, e.Err)
|
||||
}
|
||||
return fmt.Sprintf("%s: %s", e.Code, e.Message)
|
||||
}
|
||||
|
||||
func (e *AppError) Unwrap() error {
|
||||
return e.Err
|
||||
}
|
||||
|
||||
func NewBusinessError(code, message string) *AppError {
|
||||
return &AppError{
|
||||
Code: code,
|
||||
Message: message,
|
||||
Type: BusinessError,
|
||||
}
|
||||
}
|
||||
|
||||
func NewInternalError(code, message string, err error) *AppError {
|
||||
return &AppError{
|
||||
Code: code,
|
||||
Message: message,
|
||||
Type: InternalErrorType,
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
func ToGRPCError(err error, zapLogger *zap.Logger, method string) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var appErr *AppError
|
||||
ok := errors.As(err, &appErr)
|
||||
if !ok {
|
||||
if zapLogger != nil {
|
||||
zapLogger.Error("gRPC handler error: unknown error type",
|
||||
zap.String("method", method),
|
||||
zap.Error(err),
|
||||
)
|
||||
}
|
||||
return status.Error(codes.Internal, "internal server error")
|
||||
}
|
||||
|
||||
if appErr.Type == InternalErrorType {
|
||||
if zapLogger != nil {
|
||||
zapLogger.Error("gRPC handler error: internal error",
|
||||
zap.String("method", method),
|
||||
zap.String("code", appErr.Code),
|
||||
zap.String("message", appErr.Message),
|
||||
zap.Error(appErr.Err),
|
||||
)
|
||||
}
|
||||
return status.Error(codes.Internal, "internal server error")
|
||||
}
|
||||
|
||||
switch appErr.Code {
|
||||
case AuthInvalidCredentials, AuthMissing, AuthInvalidToken, RefreshInvalid:
|
||||
return status.Error(codes.Unauthenticated, appErr.Message)
|
||||
case InviteLimitReached:
|
||||
return status.Error(codes.ResourceExhausted, appErr.Message)
|
||||
case InsufficientBalance:
|
||||
return status.Error(codes.FailedPrecondition, appErr.Message)
|
||||
case UserNotFound, RequestNotFound:
|
||||
return status.Error(codes.NotFound, appErr.Message)
|
||||
default:
|
||||
return status.Error(codes.Unknown, appErr.Message)
|
||||
}
|
||||
}
|
||||
79
pkg/jwt/jwt.go
Normal file
79
pkg/jwt/jwt.go
Normal file
@@ -0,0 +1,79 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
type Claims struct {
|
||||
Sub string `json:"sub"`
|
||||
Type string `json:"type"`
|
||||
jwt.RegisteredClaims
|
||||
}
|
||||
|
||||
func GenerateAccessToken(userID int, secret string) (string, error) {
|
||||
now := time.Now()
|
||||
claims := Claims{
|
||||
Sub: strconv.Itoa(userID),
|
||||
Type: "access",
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
IssuedAt: jwt.NewNumericDate(now),
|
||||
ExpiresAt: jwt.NewNumericDate(now.Add(15 * time.Minute)),
|
||||
},
|
||||
}
|
||||
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
return token.SignedString([]byte(secret))
|
||||
}
|
||||
|
||||
func GenerateRefreshToken(userID int, secret string) (string, error) {
|
||||
now := time.Now()
|
||||
claims := Claims{
|
||||
Sub: strconv.Itoa(userID),
|
||||
Type: "refresh",
|
||||
RegisteredClaims: jwt.RegisteredClaims{
|
||||
IssuedAt: jwt.NewNumericDate(now),
|
||||
ExpiresAt: jwt.NewNumericDate(now.Add(30 * 24 * time.Hour)),
|
||||
},
|
||||
}
|
||||
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
return token.SignedString([]byte(secret))
|
||||
}
|
||||
|
||||
func ValidateToken(tokenString, secret string) (*Claims, error) {
|
||||
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
|
||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
||||
}
|
||||
return []byte(secret), nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse token: %w", err)
|
||||
}
|
||||
|
||||
if claims, ok := token.Claims.(*Claims); ok && token.Valid {
|
||||
return claims, nil
|
||||
}
|
||||
|
||||
return nil, errors.New("invalid token")
|
||||
}
|
||||
|
||||
func GetUserIDFromToken(tokenString, secret string) (int, error) {
|
||||
claims, err := ValidateToken(tokenString, secret)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
userID, err := strconv.Atoi(claims.Sub)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("invalid user ID in token: %w", err)
|
||||
}
|
||||
|
||||
return userID, nil
|
||||
}
|
||||
538
pkg/pb/api/proto/auth/auth.pb.go
Normal file
538
pkg/pb/api/proto/auth/auth.pb.go
Normal file
@@ -0,0 +1,538 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.6
|
||||
// protoc v5.29.3
|
||||
// source: api/proto/auth/auth.proto
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type LoginRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Email string `protobuf:"bytes,1,opt,name=email,proto3" json:"email,omitempty"`
|
||||
Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
|
||||
Ip string `protobuf:"bytes,3,opt,name=ip,proto3" json:"ip,omitempty"`
|
||||
UserAgent string `protobuf:"bytes,4,opt,name=user_agent,json=userAgent,proto3" json:"user_agent,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *LoginRequest) Reset() {
|
||||
*x = LoginRequest{}
|
||||
mi := &file_api_proto_auth_auth_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *LoginRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*LoginRequest) ProtoMessage() {}
|
||||
|
||||
func (x *LoginRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_auth_auth_proto_msgTypes[0]
|
||||
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 LoginRequest.ProtoReflect.Descriptor instead.
|
||||
func (*LoginRequest) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_auth_auth_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *LoginRequest) GetEmail() string {
|
||||
if x != nil {
|
||||
return x.Email
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *LoginRequest) GetPassword() string {
|
||||
if x != nil {
|
||||
return x.Password
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *LoginRequest) GetIp() string {
|
||||
if x != nil {
|
||||
return x.Ip
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *LoginRequest) GetUserAgent() string {
|
||||
if x != nil {
|
||||
return x.UserAgent
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type LoginResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
AccessToken string `protobuf:"bytes,1,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"`
|
||||
RefreshToken string `protobuf:"bytes,2,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *LoginResponse) Reset() {
|
||||
*x = LoginResponse{}
|
||||
mi := &file_api_proto_auth_auth_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *LoginResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*LoginResponse) ProtoMessage() {}
|
||||
|
||||
func (x *LoginResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_auth_auth_proto_msgTypes[1]
|
||||
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 LoginResponse.ProtoReflect.Descriptor instead.
|
||||
func (*LoginResponse) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_auth_auth_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *LoginResponse) GetAccessToken() string {
|
||||
if x != nil {
|
||||
return x.AccessToken
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *LoginResponse) GetRefreshToken() string {
|
||||
if x != nil {
|
||||
return x.RefreshToken
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type RefreshRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
RefreshToken string `protobuf:"bytes,1,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"`
|
||||
Ip string `protobuf:"bytes,2,opt,name=ip,proto3" json:"ip,omitempty"`
|
||||
UserAgent string `protobuf:"bytes,3,opt,name=user_agent,json=userAgent,proto3" json:"user_agent,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *RefreshRequest) Reset() {
|
||||
*x = RefreshRequest{}
|
||||
mi := &file_api_proto_auth_auth_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *RefreshRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*RefreshRequest) ProtoMessage() {}
|
||||
|
||||
func (x *RefreshRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_auth_auth_proto_msgTypes[2]
|
||||
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 RefreshRequest.ProtoReflect.Descriptor instead.
|
||||
func (*RefreshRequest) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_auth_auth_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *RefreshRequest) GetRefreshToken() string {
|
||||
if x != nil {
|
||||
return x.RefreshToken
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *RefreshRequest) GetIp() string {
|
||||
if x != nil {
|
||||
return x.Ip
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *RefreshRequest) GetUserAgent() string {
|
||||
if x != nil {
|
||||
return x.UserAgent
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type RefreshResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
AccessToken string `protobuf:"bytes,1,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"`
|
||||
RefreshToken string `protobuf:"bytes,2,opt,name=refresh_token,json=refreshToken,proto3" json:"refresh_token,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *RefreshResponse) Reset() {
|
||||
*x = RefreshResponse{}
|
||||
mi := &file_api_proto_auth_auth_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *RefreshResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*RefreshResponse) ProtoMessage() {}
|
||||
|
||||
func (x *RefreshResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_auth_auth_proto_msgTypes[3]
|
||||
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 RefreshResponse.ProtoReflect.Descriptor instead.
|
||||
func (*RefreshResponse) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_auth_auth_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *RefreshResponse) GetAccessToken() string {
|
||||
if x != nil {
|
||||
return x.AccessToken
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *RefreshResponse) GetRefreshToken() string {
|
||||
if x != nil {
|
||||
return x.RefreshToken
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ValidateRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
AccessToken string `protobuf:"bytes,1,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ValidateRequest) Reset() {
|
||||
*x = ValidateRequest{}
|
||||
mi := &file_api_proto_auth_auth_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ValidateRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ValidateRequest) ProtoMessage() {}
|
||||
|
||||
func (x *ValidateRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_auth_auth_proto_msgTypes[4]
|
||||
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 ValidateRequest.ProtoReflect.Descriptor instead.
|
||||
func (*ValidateRequest) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_auth_auth_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *ValidateRequest) GetAccessToken() string {
|
||||
if x != nil {
|
||||
return x.AccessToken
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ValidateResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Valid bool `protobuf:"varint,1,opt,name=valid,proto3" json:"valid,omitempty"`
|
||||
UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ValidateResponse) Reset() {
|
||||
*x = ValidateResponse{}
|
||||
mi := &file_api_proto_auth_auth_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ValidateResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ValidateResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ValidateResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_auth_auth_proto_msgTypes[5]
|
||||
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 ValidateResponse.ProtoReflect.Descriptor instead.
|
||||
func (*ValidateResponse) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_auth_auth_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *ValidateResponse) GetValid() bool {
|
||||
if x != nil {
|
||||
return x.Valid
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *ValidateResponse) GetUserId() int64 {
|
||||
if x != nil {
|
||||
return x.UserId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type LogoutRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
AccessToken string `protobuf:"bytes,1,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *LogoutRequest) Reset() {
|
||||
*x = LogoutRequest{}
|
||||
mi := &file_api_proto_auth_auth_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *LogoutRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*LogoutRequest) ProtoMessage() {}
|
||||
|
||||
func (x *LogoutRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_auth_auth_proto_msgTypes[6]
|
||||
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 LogoutRequest.ProtoReflect.Descriptor instead.
|
||||
func (*LogoutRequest) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_auth_auth_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *LogoutRequest) GetAccessToken() string {
|
||||
if x != nil {
|
||||
return x.AccessToken
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type LogoutResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *LogoutResponse) Reset() {
|
||||
*x = LogoutResponse{}
|
||||
mi := &file_api_proto_auth_auth_proto_msgTypes[7]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *LogoutResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*LogoutResponse) ProtoMessage() {}
|
||||
|
||||
func (x *LogoutResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_auth_auth_proto_msgTypes[7]
|
||||
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 LogoutResponse.ProtoReflect.Descriptor instead.
|
||||
func (*LogoutResponse) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_auth_auth_proto_rawDescGZIP(), []int{7}
|
||||
}
|
||||
|
||||
func (x *LogoutResponse) GetSuccess() bool {
|
||||
if x != nil {
|
||||
return x.Success
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var File_api_proto_auth_auth_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_api_proto_auth_auth_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\x19api/proto/auth/auth.proto\x12\x04auth\"o\n" +
|
||||
"\fLoginRequest\x12\x14\n" +
|
||||
"\x05email\x18\x01 \x01(\tR\x05email\x12\x1a\n" +
|
||||
"\bpassword\x18\x02 \x01(\tR\bpassword\x12\x0e\n" +
|
||||
"\x02ip\x18\x03 \x01(\tR\x02ip\x12\x1d\n" +
|
||||
"\n" +
|
||||
"user_agent\x18\x04 \x01(\tR\tuserAgent\"W\n" +
|
||||
"\rLoginResponse\x12!\n" +
|
||||
"\faccess_token\x18\x01 \x01(\tR\vaccessToken\x12#\n" +
|
||||
"\rrefresh_token\x18\x02 \x01(\tR\frefreshToken\"d\n" +
|
||||
"\x0eRefreshRequest\x12#\n" +
|
||||
"\rrefresh_token\x18\x01 \x01(\tR\frefreshToken\x12\x0e\n" +
|
||||
"\x02ip\x18\x02 \x01(\tR\x02ip\x12\x1d\n" +
|
||||
"\n" +
|
||||
"user_agent\x18\x03 \x01(\tR\tuserAgent\"Y\n" +
|
||||
"\x0fRefreshResponse\x12!\n" +
|
||||
"\faccess_token\x18\x01 \x01(\tR\vaccessToken\x12#\n" +
|
||||
"\rrefresh_token\x18\x02 \x01(\tR\frefreshToken\"4\n" +
|
||||
"\x0fValidateRequest\x12!\n" +
|
||||
"\faccess_token\x18\x01 \x01(\tR\vaccessToken\"A\n" +
|
||||
"\x10ValidateResponse\x12\x14\n" +
|
||||
"\x05valid\x18\x01 \x01(\bR\x05valid\x12\x17\n" +
|
||||
"\auser_id\x18\x02 \x01(\x03R\x06userId\"2\n" +
|
||||
"\rLogoutRequest\x12!\n" +
|
||||
"\faccess_token\x18\x01 \x01(\tR\vaccessToken\"*\n" +
|
||||
"\x0eLogoutResponse\x12\x18\n" +
|
||||
"\asuccess\x18\x01 \x01(\bR\asuccess2\xe7\x01\n" +
|
||||
"\vAuthService\x120\n" +
|
||||
"\x05Login\x12\x12.auth.LoginRequest\x1a\x13.auth.LoginResponse\x126\n" +
|
||||
"\aRefresh\x12\x14.auth.RefreshRequest\x1a\x15.auth.RefreshResponse\x129\n" +
|
||||
"\bValidate\x12\x15.auth.ValidateRequest\x1a\x16.auth.ValidateResponse\x123\n" +
|
||||
"\x06Logout\x12\x13.auth.LogoutRequest\x1a\x14.auth.LogoutResponseB5Z3github.com/smart-search-gateway/api/proto/auth/authb\x06proto3"
|
||||
|
||||
var (
|
||||
file_api_proto_auth_auth_proto_rawDescOnce sync.Once
|
||||
file_api_proto_auth_auth_proto_rawDescData []byte
|
||||
)
|
||||
|
||||
func file_api_proto_auth_auth_proto_rawDescGZIP() []byte {
|
||||
file_api_proto_auth_auth_proto_rawDescOnce.Do(func() {
|
||||
file_api_proto_auth_auth_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_api_proto_auth_auth_proto_rawDesc), len(file_api_proto_auth_auth_proto_rawDesc)))
|
||||
})
|
||||
return file_api_proto_auth_auth_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_api_proto_auth_auth_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
|
||||
var file_api_proto_auth_auth_proto_goTypes = []any{
|
||||
(*LoginRequest)(nil), // 0: auth.LoginRequest
|
||||
(*LoginResponse)(nil), // 1: auth.LoginResponse
|
||||
(*RefreshRequest)(nil), // 2: auth.RefreshRequest
|
||||
(*RefreshResponse)(nil), // 3: auth.RefreshResponse
|
||||
(*ValidateRequest)(nil), // 4: auth.ValidateRequest
|
||||
(*ValidateResponse)(nil), // 5: auth.ValidateResponse
|
||||
(*LogoutRequest)(nil), // 6: auth.LogoutRequest
|
||||
(*LogoutResponse)(nil), // 7: auth.LogoutResponse
|
||||
}
|
||||
var file_api_proto_auth_auth_proto_depIdxs = []int32{
|
||||
0, // 0: auth.AuthService.Login:input_type -> auth.LoginRequest
|
||||
2, // 1: auth.AuthService.Refresh:input_type -> auth.RefreshRequest
|
||||
4, // 2: auth.AuthService.Validate:input_type -> auth.ValidateRequest
|
||||
6, // 3: auth.AuthService.Logout:input_type -> auth.LogoutRequest
|
||||
1, // 4: auth.AuthService.Login:output_type -> auth.LoginResponse
|
||||
3, // 5: auth.AuthService.Refresh:output_type -> auth.RefreshResponse
|
||||
5, // 6: auth.AuthService.Validate:output_type -> auth.ValidateResponse
|
||||
7, // 7: auth.AuthService.Logout:output_type -> auth.LogoutResponse
|
||||
4, // [4:8] is the sub-list for method output_type
|
||||
0, // [0:4] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_api_proto_auth_auth_proto_init() }
|
||||
func file_api_proto_auth_auth_proto_init() {
|
||||
if File_api_proto_auth_auth_proto != nil {
|
||||
return
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_proto_auth_auth_proto_rawDesc), len(file_api_proto_auth_auth_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 8,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_api_proto_auth_auth_proto_goTypes,
|
||||
DependencyIndexes: file_api_proto_auth_auth_proto_depIdxs,
|
||||
MessageInfos: file_api_proto_auth_auth_proto_msgTypes,
|
||||
}.Build()
|
||||
File_api_proto_auth_auth_proto = out.File
|
||||
file_api_proto_auth_auth_proto_goTypes = nil
|
||||
file_api_proto_auth_auth_proto_depIdxs = nil
|
||||
}
|
||||
235
pkg/pb/api/proto/auth/auth_grpc.pb.go
Normal file
235
pkg/pb/api/proto/auth/auth_grpc.pb.go
Normal file
@@ -0,0 +1,235 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc v5.29.3
|
||||
// source: api/proto/auth/auth.proto
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
AuthService_Login_FullMethodName = "/auth.AuthService/Login"
|
||||
AuthService_Refresh_FullMethodName = "/auth.AuthService/Refresh"
|
||||
AuthService_Validate_FullMethodName = "/auth.AuthService/Validate"
|
||||
AuthService_Logout_FullMethodName = "/auth.AuthService/Logout"
|
||||
)
|
||||
|
||||
// AuthServiceClient is the client API for AuthService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type AuthServiceClient interface {
|
||||
Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error)
|
||||
Refresh(ctx context.Context, in *RefreshRequest, opts ...grpc.CallOption) (*RefreshResponse, error)
|
||||
Validate(ctx context.Context, in *ValidateRequest, opts ...grpc.CallOption) (*ValidateResponse, error)
|
||||
Logout(ctx context.Context, in *LogoutRequest, opts ...grpc.CallOption) (*LogoutResponse, error)
|
||||
}
|
||||
|
||||
type authServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewAuthServiceClient(cc grpc.ClientConnInterface) AuthServiceClient {
|
||||
return &authServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *authServiceClient) Login(ctx context.Context, in *LoginRequest, opts ...grpc.CallOption) (*LoginResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(LoginResponse)
|
||||
err := c.cc.Invoke(ctx, AuthService_Login_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *authServiceClient) Refresh(ctx context.Context, in *RefreshRequest, opts ...grpc.CallOption) (*RefreshResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(RefreshResponse)
|
||||
err := c.cc.Invoke(ctx, AuthService_Refresh_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *authServiceClient) Validate(ctx context.Context, in *ValidateRequest, opts ...grpc.CallOption) (*ValidateResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ValidateResponse)
|
||||
err := c.cc.Invoke(ctx, AuthService_Validate_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *authServiceClient) Logout(ctx context.Context, in *LogoutRequest, opts ...grpc.CallOption) (*LogoutResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(LogoutResponse)
|
||||
err := c.cc.Invoke(ctx, AuthService_Logout_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// AuthServiceServer is the server API for AuthService service.
|
||||
// All implementations must embed UnimplementedAuthServiceServer
|
||||
// for forward compatibility.
|
||||
type AuthServiceServer interface {
|
||||
Login(context.Context, *LoginRequest) (*LoginResponse, error)
|
||||
Refresh(context.Context, *RefreshRequest) (*RefreshResponse, error)
|
||||
Validate(context.Context, *ValidateRequest) (*ValidateResponse, error)
|
||||
Logout(context.Context, *LogoutRequest) (*LogoutResponse, error)
|
||||
mustEmbedUnimplementedAuthServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedAuthServiceServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedAuthServiceServer struct{}
|
||||
|
||||
func (UnimplementedAuthServiceServer) Login(context.Context, *LoginRequest) (*LoginResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Login not implemented")
|
||||
}
|
||||
func (UnimplementedAuthServiceServer) Refresh(context.Context, *RefreshRequest) (*RefreshResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Refresh not implemented")
|
||||
}
|
||||
func (UnimplementedAuthServiceServer) Validate(context.Context, *ValidateRequest) (*ValidateResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Validate not implemented")
|
||||
}
|
||||
func (UnimplementedAuthServiceServer) Logout(context.Context, *LogoutRequest) (*LogoutResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Logout not implemented")
|
||||
}
|
||||
func (UnimplementedAuthServiceServer) mustEmbedUnimplementedAuthServiceServer() {}
|
||||
func (UnimplementedAuthServiceServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeAuthServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to AuthServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeAuthServiceServer interface {
|
||||
mustEmbedUnimplementedAuthServiceServer()
|
||||
}
|
||||
|
||||
func RegisterAuthServiceServer(s grpc.ServiceRegistrar, srv AuthServiceServer) {
|
||||
// If the following call pancis, it indicates UnimplementedAuthServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&AuthService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _AuthService_Login_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(LoginRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AuthServiceServer).Login(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: AuthService_Login_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AuthServiceServer).Login(ctx, req.(*LoginRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _AuthService_Refresh_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(RefreshRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AuthServiceServer).Refresh(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: AuthService_Refresh_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AuthServiceServer).Refresh(ctx, req.(*RefreshRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _AuthService_Validate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ValidateRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AuthServiceServer).Validate(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: AuthService_Validate_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AuthServiceServer).Validate(ctx, req.(*ValidateRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _AuthService_Logout_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(LogoutRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AuthServiceServer).Logout(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: AuthService_Logout_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AuthServiceServer).Logout(ctx, req.(*LogoutRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// AuthService_ServiceDesc is the grpc.ServiceDesc for AuthService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var AuthService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "auth.AuthService",
|
||||
HandlerType: (*AuthServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Login",
|
||||
Handler: _AuthService_Login_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Refresh",
|
||||
Handler: _AuthService_Refresh_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Validate",
|
||||
Handler: _AuthService_Validate_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Logout",
|
||||
Handler: _AuthService_Logout_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "api/proto/auth/auth.proto",
|
||||
}
|
||||
369
pkg/pb/api/proto/invite/invite.pb.go
Normal file
369
pkg/pb/api/proto/invite/invite.pb.go
Normal file
@@ -0,0 +1,369 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.6
|
||||
// protoc v5.29.3
|
||||
// source: api/proto/invite/invite.proto
|
||||
|
||||
package invite
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type GenerateRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
TtlDays int32 `protobuf:"varint,2,opt,name=ttl_days,json=ttlDays,proto3" json:"ttl_days,omitempty"`
|
||||
MaxUses int32 `protobuf:"varint,3,opt,name=max_uses,json=maxUses,proto3" json:"max_uses,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GenerateRequest) Reset() {
|
||||
*x = GenerateRequest{}
|
||||
mi := &file_api_proto_invite_invite_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GenerateRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GenerateRequest) ProtoMessage() {}
|
||||
|
||||
func (x *GenerateRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_invite_invite_proto_msgTypes[0]
|
||||
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 GenerateRequest.ProtoReflect.Descriptor instead.
|
||||
func (*GenerateRequest) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_invite_invite_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *GenerateRequest) GetUserId() int64 {
|
||||
if x != nil {
|
||||
return x.UserId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *GenerateRequest) GetTtlDays() int32 {
|
||||
if x != nil {
|
||||
return x.TtlDays
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *GenerateRequest) GetMaxUses() int32 {
|
||||
if x != nil {
|
||||
return x.MaxUses
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type GenerateResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"`
|
||||
MaxUses int32 `protobuf:"varint,2,opt,name=max_uses,json=maxUses,proto3" json:"max_uses,omitempty"`
|
||||
ExpiresAt *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=expires_at,json=expiresAt,proto3" json:"expires_at,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GenerateResponse) Reset() {
|
||||
*x = GenerateResponse{}
|
||||
mi := &file_api_proto_invite_invite_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GenerateResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GenerateResponse) ProtoMessage() {}
|
||||
|
||||
func (x *GenerateResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_invite_invite_proto_msgTypes[1]
|
||||
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 GenerateResponse.ProtoReflect.Descriptor instead.
|
||||
func (*GenerateResponse) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_invite_invite_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *GenerateResponse) GetCode() string {
|
||||
if x != nil {
|
||||
return x.Code
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *GenerateResponse) GetMaxUses() int32 {
|
||||
if x != nil {
|
||||
return x.MaxUses
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *GenerateResponse) GetExpiresAt() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.ExpiresAt
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type GetInfoRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetInfoRequest) Reset() {
|
||||
*x = GetInfoRequest{}
|
||||
mi := &file_api_proto_invite_invite_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetInfoRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetInfoRequest) ProtoMessage() {}
|
||||
|
||||
func (x *GetInfoRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_invite_invite_proto_msgTypes[2]
|
||||
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 GetInfoRequest.ProtoReflect.Descriptor instead.
|
||||
func (*GetInfoRequest) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_invite_invite_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *GetInfoRequest) GetCode() string {
|
||||
if x != nil {
|
||||
return x.Code
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type GetInfoResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"`
|
||||
UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
CanBeUsedCount int32 `protobuf:"varint,3,opt,name=can_be_used_count,json=canBeUsedCount,proto3" json:"can_be_used_count,omitempty"`
|
||||
UsedCount int32 `protobuf:"varint,4,opt,name=used_count,json=usedCount,proto3" json:"used_count,omitempty"`
|
||||
ExpiresAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=expires_at,json=expiresAt,proto3" json:"expires_at,omitempty"`
|
||||
IsActive bool `protobuf:"varint,6,opt,name=is_active,json=isActive,proto3" json:"is_active,omitempty"`
|
||||
CreatedAt *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetInfoResponse) Reset() {
|
||||
*x = GetInfoResponse{}
|
||||
mi := &file_api_proto_invite_invite_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetInfoResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetInfoResponse) ProtoMessage() {}
|
||||
|
||||
func (x *GetInfoResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_invite_invite_proto_msgTypes[3]
|
||||
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 GetInfoResponse.ProtoReflect.Descriptor instead.
|
||||
func (*GetInfoResponse) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_invite_invite_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *GetInfoResponse) GetCode() string {
|
||||
if x != nil {
|
||||
return x.Code
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *GetInfoResponse) GetUserId() int64 {
|
||||
if x != nil {
|
||||
return x.UserId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *GetInfoResponse) GetCanBeUsedCount() int32 {
|
||||
if x != nil {
|
||||
return x.CanBeUsedCount
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *GetInfoResponse) GetUsedCount() int32 {
|
||||
if x != nil {
|
||||
return x.UsedCount
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *GetInfoResponse) GetExpiresAt() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.ExpiresAt
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *GetInfoResponse) GetIsActive() bool {
|
||||
if x != nil {
|
||||
return x.IsActive
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *GetInfoResponse) GetCreatedAt() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.CreatedAt
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_api_proto_invite_invite_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_api_proto_invite_invite_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\x1dapi/proto/invite/invite.proto\x12\x06invite\x1a\x1fgoogle/protobuf/timestamp.proto\"`\n" +
|
||||
"\x0fGenerateRequest\x12\x17\n" +
|
||||
"\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x19\n" +
|
||||
"\bttl_days\x18\x02 \x01(\x05R\attlDays\x12\x19\n" +
|
||||
"\bmax_uses\x18\x03 \x01(\x05R\amaxUses\"|\n" +
|
||||
"\x10GenerateResponse\x12\x12\n" +
|
||||
"\x04code\x18\x01 \x01(\tR\x04code\x12\x19\n" +
|
||||
"\bmax_uses\x18\x02 \x01(\x05R\amaxUses\x129\n" +
|
||||
"\n" +
|
||||
"expires_at\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampR\texpiresAt\"$\n" +
|
||||
"\x0eGetInfoRequest\x12\x12\n" +
|
||||
"\x04code\x18\x01 \x01(\tR\x04code\"\x9b\x02\n" +
|
||||
"\x0fGetInfoResponse\x12\x12\n" +
|
||||
"\x04code\x18\x01 \x01(\tR\x04code\x12\x17\n" +
|
||||
"\auser_id\x18\x02 \x01(\x03R\x06userId\x12)\n" +
|
||||
"\x11can_be_used_count\x18\x03 \x01(\x05R\x0ecanBeUsedCount\x12\x1d\n" +
|
||||
"\n" +
|
||||
"used_count\x18\x04 \x01(\x05R\tusedCount\x129\n" +
|
||||
"\n" +
|
||||
"expires_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\texpiresAt\x12\x1b\n" +
|
||||
"\tis_active\x18\x06 \x01(\bR\bisActive\x129\n" +
|
||||
"\n" +
|
||||
"created_at\x18\a \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt2\x8a\x01\n" +
|
||||
"\rInviteService\x12=\n" +
|
||||
"\bGenerate\x12\x17.invite.GenerateRequest\x1a\x18.invite.GenerateResponse\x12:\n" +
|
||||
"\aGetInfo\x12\x16.invite.GetInfoRequest\x1a\x17.invite.GetInfoResponseB9Z7github.com/smart-search-gateway/api/proto/invite/inviteb\x06proto3"
|
||||
|
||||
var (
|
||||
file_api_proto_invite_invite_proto_rawDescOnce sync.Once
|
||||
file_api_proto_invite_invite_proto_rawDescData []byte
|
||||
)
|
||||
|
||||
func file_api_proto_invite_invite_proto_rawDescGZIP() []byte {
|
||||
file_api_proto_invite_invite_proto_rawDescOnce.Do(func() {
|
||||
file_api_proto_invite_invite_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_api_proto_invite_invite_proto_rawDesc), len(file_api_proto_invite_invite_proto_rawDesc)))
|
||||
})
|
||||
return file_api_proto_invite_invite_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_api_proto_invite_invite_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
|
||||
var file_api_proto_invite_invite_proto_goTypes = []any{
|
||||
(*GenerateRequest)(nil), // 0: invite.GenerateRequest
|
||||
(*GenerateResponse)(nil), // 1: invite.GenerateResponse
|
||||
(*GetInfoRequest)(nil), // 2: invite.GetInfoRequest
|
||||
(*GetInfoResponse)(nil), // 3: invite.GetInfoResponse
|
||||
(*timestamppb.Timestamp)(nil), // 4: google.protobuf.Timestamp
|
||||
}
|
||||
var file_api_proto_invite_invite_proto_depIdxs = []int32{
|
||||
4, // 0: invite.GenerateResponse.expires_at:type_name -> google.protobuf.Timestamp
|
||||
4, // 1: invite.GetInfoResponse.expires_at:type_name -> google.protobuf.Timestamp
|
||||
4, // 2: invite.GetInfoResponse.created_at:type_name -> google.protobuf.Timestamp
|
||||
0, // 3: invite.InviteService.Generate:input_type -> invite.GenerateRequest
|
||||
2, // 4: invite.InviteService.GetInfo:input_type -> invite.GetInfoRequest
|
||||
1, // 5: invite.InviteService.Generate:output_type -> invite.GenerateResponse
|
||||
3, // 6: invite.InviteService.GetInfo:output_type -> invite.GetInfoResponse
|
||||
5, // [5:7] is the sub-list for method output_type
|
||||
3, // [3:5] is the sub-list for method input_type
|
||||
3, // [3:3] is the sub-list for extension type_name
|
||||
3, // [3:3] is the sub-list for extension extendee
|
||||
0, // [0:3] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_api_proto_invite_invite_proto_init() }
|
||||
func file_api_proto_invite_invite_proto_init() {
|
||||
if File_api_proto_invite_invite_proto != nil {
|
||||
return
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_proto_invite_invite_proto_rawDesc), len(file_api_proto_invite_invite_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 4,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_api_proto_invite_invite_proto_goTypes,
|
||||
DependencyIndexes: file_api_proto_invite_invite_proto_depIdxs,
|
||||
MessageInfos: file_api_proto_invite_invite_proto_msgTypes,
|
||||
}.Build()
|
||||
File_api_proto_invite_invite_proto = out.File
|
||||
file_api_proto_invite_invite_proto_goTypes = nil
|
||||
file_api_proto_invite_invite_proto_depIdxs = nil
|
||||
}
|
||||
159
pkg/pb/api/proto/invite/invite_grpc.pb.go
Normal file
159
pkg/pb/api/proto/invite/invite_grpc.pb.go
Normal file
@@ -0,0 +1,159 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc v5.29.3
|
||||
// source: api/proto/invite/invite.proto
|
||||
|
||||
package invite
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
InviteService_Generate_FullMethodName = "/invite.InviteService/Generate"
|
||||
InviteService_GetInfo_FullMethodName = "/invite.InviteService/GetInfo"
|
||||
)
|
||||
|
||||
// InviteServiceClient is the client API for InviteService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type InviteServiceClient interface {
|
||||
Generate(ctx context.Context, in *GenerateRequest, opts ...grpc.CallOption) (*GenerateResponse, error)
|
||||
GetInfo(ctx context.Context, in *GetInfoRequest, opts ...grpc.CallOption) (*GetInfoResponse, error)
|
||||
}
|
||||
|
||||
type inviteServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewInviteServiceClient(cc grpc.ClientConnInterface) InviteServiceClient {
|
||||
return &inviteServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *inviteServiceClient) Generate(ctx context.Context, in *GenerateRequest, opts ...grpc.CallOption) (*GenerateResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GenerateResponse)
|
||||
err := c.cc.Invoke(ctx, InviteService_Generate_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *inviteServiceClient) GetInfo(ctx context.Context, in *GetInfoRequest, opts ...grpc.CallOption) (*GetInfoResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetInfoResponse)
|
||||
err := c.cc.Invoke(ctx, InviteService_GetInfo_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// InviteServiceServer is the server API for InviteService service.
|
||||
// All implementations must embed UnimplementedInviteServiceServer
|
||||
// for forward compatibility.
|
||||
type InviteServiceServer interface {
|
||||
Generate(context.Context, *GenerateRequest) (*GenerateResponse, error)
|
||||
GetInfo(context.Context, *GetInfoRequest) (*GetInfoResponse, error)
|
||||
mustEmbedUnimplementedInviteServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedInviteServiceServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedInviteServiceServer struct{}
|
||||
|
||||
func (UnimplementedInviteServiceServer) Generate(context.Context, *GenerateRequest) (*GenerateResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Generate not implemented")
|
||||
}
|
||||
func (UnimplementedInviteServiceServer) GetInfo(context.Context, *GetInfoRequest) (*GetInfoResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetInfo not implemented")
|
||||
}
|
||||
func (UnimplementedInviteServiceServer) mustEmbedUnimplementedInviteServiceServer() {}
|
||||
func (UnimplementedInviteServiceServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeInviteServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to InviteServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeInviteServiceServer interface {
|
||||
mustEmbedUnimplementedInviteServiceServer()
|
||||
}
|
||||
|
||||
func RegisterInviteServiceServer(s grpc.ServiceRegistrar, srv InviteServiceServer) {
|
||||
// If the following call pancis, it indicates UnimplementedInviteServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&InviteService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _InviteService_Generate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GenerateRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(InviteServiceServer).Generate(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: InviteService_Generate_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(InviteServiceServer).Generate(ctx, req.(*GenerateRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _InviteService_GetInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetInfoRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(InviteServiceServer).GetInfo(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: InviteService_GetInfo_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(InviteServiceServer).GetInfo(ctx, req.(*GetInfoRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// InviteService_ServiceDesc is the grpc.ServiceDesc for InviteService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var InviteService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "invite.InviteService",
|
||||
HandlerType: (*InviteServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "Generate",
|
||||
Handler: _InviteService_Generate_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetInfo",
|
||||
Handler: _InviteService_GetInfo_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "api/proto/invite/invite.proto",
|
||||
}
|
||||
640
pkg/pb/api/proto/request/request.pb.go
Normal file
640
pkg/pb/api/proto/request/request.pb.go
Normal file
@@ -0,0 +1,640 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.6
|
||||
// protoc v5.29.3
|
||||
// source: api/proto/request/request.proto
|
||||
|
||||
package request
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type CreateTZRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
RequestTxt string `protobuf:"bytes,2,opt,name=request_txt,json=requestTxt,proto3" json:"request_txt,omitempty"`
|
||||
FileData []byte `protobuf:"bytes,3,opt,name=file_data,json=fileData,proto3" json:"file_data,omitempty"`
|
||||
FileName string `protobuf:"bytes,4,opt,name=file_name,json=fileName,proto3" json:"file_name,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *CreateTZRequest) Reset() {
|
||||
*x = CreateTZRequest{}
|
||||
mi := &file_api_proto_request_request_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *CreateTZRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*CreateTZRequest) ProtoMessage() {}
|
||||
|
||||
func (x *CreateTZRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_request_request_proto_msgTypes[0]
|
||||
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 CreateTZRequest.ProtoReflect.Descriptor instead.
|
||||
func (*CreateTZRequest) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_request_request_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *CreateTZRequest) GetUserId() int64 {
|
||||
if x != nil {
|
||||
return x.UserId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *CreateTZRequest) GetRequestTxt() string {
|
||||
if x != nil {
|
||||
return x.RequestTxt
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *CreateTZRequest) GetFileData() []byte {
|
||||
if x != nil {
|
||||
return x.FileData
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *CreateTZRequest) GetFileName() string {
|
||||
if x != nil {
|
||||
return x.FileName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type CreateTZResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"`
|
||||
TzText string `protobuf:"bytes,2,opt,name=tz_text,json=tzText,proto3" json:"tz_text,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *CreateTZResponse) Reset() {
|
||||
*x = CreateTZResponse{}
|
||||
mi := &file_api_proto_request_request_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *CreateTZResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*CreateTZResponse) ProtoMessage() {}
|
||||
|
||||
func (x *CreateTZResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_request_request_proto_msgTypes[1]
|
||||
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 CreateTZResponse.ProtoReflect.Descriptor instead.
|
||||
func (*CreateTZResponse) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_request_request_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *CreateTZResponse) GetRequestId() string {
|
||||
if x != nil {
|
||||
return x.RequestId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *CreateTZResponse) GetTzText() string {
|
||||
if x != nil {
|
||||
return x.TzText
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ApproveTZRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"`
|
||||
FinalTz string `protobuf:"bytes,2,opt,name=final_tz,json=finalTz,proto3" json:"final_tz,omitempty"`
|
||||
UserId int64 `protobuf:"varint,3,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ApproveTZRequest) Reset() {
|
||||
*x = ApproveTZRequest{}
|
||||
mi := &file_api_proto_request_request_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ApproveTZRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ApproveTZRequest) ProtoMessage() {}
|
||||
|
||||
func (x *ApproveTZRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_request_request_proto_msgTypes[2]
|
||||
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 ApproveTZRequest.ProtoReflect.Descriptor instead.
|
||||
func (*ApproveTZRequest) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_request_request_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *ApproveTZRequest) GetRequestId() string {
|
||||
if x != nil {
|
||||
return x.RequestId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ApproveTZRequest) GetFinalTz() string {
|
||||
if x != nil {
|
||||
return x.FinalTz
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ApproveTZRequest) GetUserId() int64 {
|
||||
if x != nil {
|
||||
return x.UserId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type ApproveTZResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"`
|
||||
MailingStatus string `protobuf:"bytes,2,opt,name=mailing_status,json=mailingStatus,proto3" json:"mailing_status,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ApproveTZResponse) Reset() {
|
||||
*x = ApproveTZResponse{}
|
||||
mi := &file_api_proto_request_request_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ApproveTZResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ApproveTZResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ApproveTZResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_request_request_proto_msgTypes[3]
|
||||
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 ApproveTZResponse.ProtoReflect.Descriptor instead.
|
||||
func (*ApproveTZResponse) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_request_request_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *ApproveTZResponse) GetSuccess() bool {
|
||||
if x != nil {
|
||||
return x.Success
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *ApproveTZResponse) GetMailingStatus() string {
|
||||
if x != nil {
|
||||
return x.MailingStatus
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type GetMailingListRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetMailingListRequest) Reset() {
|
||||
*x = GetMailingListRequest{}
|
||||
mi := &file_api_proto_request_request_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetMailingListRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetMailingListRequest) ProtoMessage() {}
|
||||
|
||||
func (x *GetMailingListRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_request_request_proto_msgTypes[4]
|
||||
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 GetMailingListRequest.ProtoReflect.Descriptor instead.
|
||||
func (*GetMailingListRequest) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_request_request_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *GetMailingListRequest) GetUserId() int64 {
|
||||
if x != nil {
|
||||
return x.UserId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type GetMailingListResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Items []*MailingItem `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetMailingListResponse) Reset() {
|
||||
*x = GetMailingListResponse{}
|
||||
mi := &file_api_proto_request_request_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetMailingListResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetMailingListResponse) ProtoMessage() {}
|
||||
|
||||
func (x *GetMailingListResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_request_request_proto_msgTypes[5]
|
||||
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 GetMailingListResponse.ProtoReflect.Descriptor instead.
|
||||
func (*GetMailingListResponse) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_request_request_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *GetMailingListResponse) GetItems() []*MailingItem {
|
||||
if x != nil {
|
||||
return x.Items
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type GetMailingListByIDRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"`
|
||||
UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetMailingListByIDRequest) Reset() {
|
||||
*x = GetMailingListByIDRequest{}
|
||||
mi := &file_api_proto_request_request_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetMailingListByIDRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetMailingListByIDRequest) ProtoMessage() {}
|
||||
|
||||
func (x *GetMailingListByIDRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_request_request_proto_msgTypes[6]
|
||||
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 GetMailingListByIDRequest.ProtoReflect.Descriptor instead.
|
||||
func (*GetMailingListByIDRequest) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_request_request_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *GetMailingListByIDRequest) GetRequestId() string {
|
||||
if x != nil {
|
||||
return x.RequestId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *GetMailingListByIDRequest) GetUserId() int64 {
|
||||
if x != nil {
|
||||
return x.UserId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type GetMailingListByIDResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Item *MailingItem `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetMailingListByIDResponse) Reset() {
|
||||
*x = GetMailingListByIDResponse{}
|
||||
mi := &file_api_proto_request_request_proto_msgTypes[7]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetMailingListByIDResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetMailingListByIDResponse) ProtoMessage() {}
|
||||
|
||||
func (x *GetMailingListByIDResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_request_request_proto_msgTypes[7]
|
||||
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 GetMailingListByIDResponse.ProtoReflect.Descriptor instead.
|
||||
func (*GetMailingListByIDResponse) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_request_request_proto_rawDescGZIP(), []int{7}
|
||||
}
|
||||
|
||||
func (x *GetMailingListByIDResponse) GetItem() *MailingItem {
|
||||
if x != nil {
|
||||
return x.Item
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type MailingItem struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"`
|
||||
RequestTxt string `protobuf:"bytes,2,opt,name=request_txt,json=requestTxt,proto3" json:"request_txt,omitempty"`
|
||||
FinalTz string `protobuf:"bytes,3,opt,name=final_tz,json=finalTz,proto3" json:"final_tz,omitempty"`
|
||||
MailingStatus string `protobuf:"bytes,4,opt,name=mailing_status,json=mailingStatus,proto3" json:"mailing_status,omitempty"`
|
||||
CreatedAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
|
||||
SuppliersFound int32 `protobuf:"varint,6,opt,name=suppliers_found,json=suppliersFound,proto3" json:"suppliers_found,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *MailingItem) Reset() {
|
||||
*x = MailingItem{}
|
||||
mi := &file_api_proto_request_request_proto_msgTypes[8]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *MailingItem) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*MailingItem) ProtoMessage() {}
|
||||
|
||||
func (x *MailingItem) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_request_request_proto_msgTypes[8]
|
||||
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 MailingItem.ProtoReflect.Descriptor instead.
|
||||
func (*MailingItem) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_request_request_proto_rawDescGZIP(), []int{8}
|
||||
}
|
||||
|
||||
func (x *MailingItem) GetRequestId() string {
|
||||
if x != nil {
|
||||
return x.RequestId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *MailingItem) GetRequestTxt() string {
|
||||
if x != nil {
|
||||
return x.RequestTxt
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *MailingItem) GetFinalTz() string {
|
||||
if x != nil {
|
||||
return x.FinalTz
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *MailingItem) GetMailingStatus() string {
|
||||
if x != nil {
|
||||
return x.MailingStatus
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *MailingItem) GetCreatedAt() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.CreatedAt
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *MailingItem) GetSuppliersFound() int32 {
|
||||
if x != nil {
|
||||
return x.SuppliersFound
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var File_api_proto_request_request_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_api_proto_request_request_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\x1fapi/proto/request/request.proto\x12\arequest\x1a\x1fgoogle/protobuf/timestamp.proto\"\x85\x01\n" +
|
||||
"\x0fCreateTZRequest\x12\x17\n" +
|
||||
"\auser_id\x18\x01 \x01(\x03R\x06userId\x12\x1f\n" +
|
||||
"\vrequest_txt\x18\x02 \x01(\tR\n" +
|
||||
"requestTxt\x12\x1b\n" +
|
||||
"\tfile_data\x18\x03 \x01(\fR\bfileData\x12\x1b\n" +
|
||||
"\tfile_name\x18\x04 \x01(\tR\bfileName\"J\n" +
|
||||
"\x10CreateTZResponse\x12\x1d\n" +
|
||||
"\n" +
|
||||
"request_id\x18\x01 \x01(\tR\trequestId\x12\x17\n" +
|
||||
"\atz_text\x18\x02 \x01(\tR\x06tzText\"e\n" +
|
||||
"\x10ApproveTZRequest\x12\x1d\n" +
|
||||
"\n" +
|
||||
"request_id\x18\x01 \x01(\tR\trequestId\x12\x19\n" +
|
||||
"\bfinal_tz\x18\x02 \x01(\tR\afinalTz\x12\x17\n" +
|
||||
"\auser_id\x18\x03 \x01(\x03R\x06userId\"T\n" +
|
||||
"\x11ApproveTZResponse\x12\x18\n" +
|
||||
"\asuccess\x18\x01 \x01(\bR\asuccess\x12%\n" +
|
||||
"\x0emailing_status\x18\x02 \x01(\tR\rmailingStatus\"0\n" +
|
||||
"\x15GetMailingListRequest\x12\x17\n" +
|
||||
"\auser_id\x18\x01 \x01(\x03R\x06userId\"D\n" +
|
||||
"\x16GetMailingListResponse\x12*\n" +
|
||||
"\x05items\x18\x01 \x03(\v2\x14.request.MailingItemR\x05items\"S\n" +
|
||||
"\x19GetMailingListByIDRequest\x12\x1d\n" +
|
||||
"\n" +
|
||||
"request_id\x18\x01 \x01(\tR\trequestId\x12\x17\n" +
|
||||
"\auser_id\x18\x02 \x01(\x03R\x06userId\"F\n" +
|
||||
"\x1aGetMailingListByIDResponse\x12(\n" +
|
||||
"\x04item\x18\x01 \x01(\v2\x14.request.MailingItemR\x04item\"\xf3\x01\n" +
|
||||
"\vMailingItem\x12\x1d\n" +
|
||||
"\n" +
|
||||
"request_id\x18\x01 \x01(\tR\trequestId\x12\x1f\n" +
|
||||
"\vrequest_txt\x18\x02 \x01(\tR\n" +
|
||||
"requestTxt\x12\x19\n" +
|
||||
"\bfinal_tz\x18\x03 \x01(\tR\afinalTz\x12%\n" +
|
||||
"\x0emailing_status\x18\x04 \x01(\tR\rmailingStatus\x129\n" +
|
||||
"\n" +
|
||||
"created_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\tcreatedAt\x12'\n" +
|
||||
"\x0fsuppliers_found\x18\x06 \x01(\x05R\x0esuppliersFound2\xc7\x02\n" +
|
||||
"\x0eRequestService\x12?\n" +
|
||||
"\bCreateTZ\x12\x18.request.CreateTZRequest\x1a\x19.request.CreateTZResponse\x12B\n" +
|
||||
"\tApproveTZ\x12\x19.request.ApproveTZRequest\x1a\x1a.request.ApproveTZResponse\x12Q\n" +
|
||||
"\x0eGetMailingList\x12\x1e.request.GetMailingListRequest\x1a\x1f.request.GetMailingListResponse\x12]\n" +
|
||||
"\x12GetMailingListByID\x12\".request.GetMailingListByIDRequest\x1a#.request.GetMailingListByIDResponseB;Z9github.com/smart-search-gateway/api/proto/request/requestb\x06proto3"
|
||||
|
||||
var (
|
||||
file_api_proto_request_request_proto_rawDescOnce sync.Once
|
||||
file_api_proto_request_request_proto_rawDescData []byte
|
||||
)
|
||||
|
||||
func file_api_proto_request_request_proto_rawDescGZIP() []byte {
|
||||
file_api_proto_request_request_proto_rawDescOnce.Do(func() {
|
||||
file_api_proto_request_request_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_api_proto_request_request_proto_rawDesc), len(file_api_proto_request_request_proto_rawDesc)))
|
||||
})
|
||||
return file_api_proto_request_request_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_api_proto_request_request_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
|
||||
var file_api_proto_request_request_proto_goTypes = []any{
|
||||
(*CreateTZRequest)(nil), // 0: request.CreateTZRequest
|
||||
(*CreateTZResponse)(nil), // 1: request.CreateTZResponse
|
||||
(*ApproveTZRequest)(nil), // 2: request.ApproveTZRequest
|
||||
(*ApproveTZResponse)(nil), // 3: request.ApproveTZResponse
|
||||
(*GetMailingListRequest)(nil), // 4: request.GetMailingListRequest
|
||||
(*GetMailingListResponse)(nil), // 5: request.GetMailingListResponse
|
||||
(*GetMailingListByIDRequest)(nil), // 6: request.GetMailingListByIDRequest
|
||||
(*GetMailingListByIDResponse)(nil), // 7: request.GetMailingListByIDResponse
|
||||
(*MailingItem)(nil), // 8: request.MailingItem
|
||||
(*timestamppb.Timestamp)(nil), // 9: google.protobuf.Timestamp
|
||||
}
|
||||
var file_api_proto_request_request_proto_depIdxs = []int32{
|
||||
8, // 0: request.GetMailingListResponse.items:type_name -> request.MailingItem
|
||||
8, // 1: request.GetMailingListByIDResponse.item:type_name -> request.MailingItem
|
||||
9, // 2: request.MailingItem.created_at:type_name -> google.protobuf.Timestamp
|
||||
0, // 3: request.RequestService.CreateTZ:input_type -> request.CreateTZRequest
|
||||
2, // 4: request.RequestService.ApproveTZ:input_type -> request.ApproveTZRequest
|
||||
4, // 5: request.RequestService.GetMailingList:input_type -> request.GetMailingListRequest
|
||||
6, // 6: request.RequestService.GetMailingListByID:input_type -> request.GetMailingListByIDRequest
|
||||
1, // 7: request.RequestService.CreateTZ:output_type -> request.CreateTZResponse
|
||||
3, // 8: request.RequestService.ApproveTZ:output_type -> request.ApproveTZResponse
|
||||
5, // 9: request.RequestService.GetMailingList:output_type -> request.GetMailingListResponse
|
||||
7, // 10: request.RequestService.GetMailingListByID:output_type -> request.GetMailingListByIDResponse
|
||||
7, // [7:11] is the sub-list for method output_type
|
||||
3, // [3:7] is the sub-list for method input_type
|
||||
3, // [3:3] is the sub-list for extension type_name
|
||||
3, // [3:3] is the sub-list for extension extendee
|
||||
0, // [0:3] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_api_proto_request_request_proto_init() }
|
||||
func file_api_proto_request_request_proto_init() {
|
||||
if File_api_proto_request_request_proto != nil {
|
||||
return
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_proto_request_request_proto_rawDesc), len(file_api_proto_request_request_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 9,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_api_proto_request_request_proto_goTypes,
|
||||
DependencyIndexes: file_api_proto_request_request_proto_depIdxs,
|
||||
MessageInfos: file_api_proto_request_request_proto_msgTypes,
|
||||
}.Build()
|
||||
File_api_proto_request_request_proto = out.File
|
||||
file_api_proto_request_request_proto_goTypes = nil
|
||||
file_api_proto_request_request_proto_depIdxs = nil
|
||||
}
|
||||
235
pkg/pb/api/proto/request/request_grpc.pb.go
Normal file
235
pkg/pb/api/proto/request/request_grpc.pb.go
Normal file
@@ -0,0 +1,235 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc v5.29.3
|
||||
// source: api/proto/request/request.proto
|
||||
|
||||
package request
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
RequestService_CreateTZ_FullMethodName = "/request.RequestService/CreateTZ"
|
||||
RequestService_ApproveTZ_FullMethodName = "/request.RequestService/ApproveTZ"
|
||||
RequestService_GetMailingList_FullMethodName = "/request.RequestService/GetMailingList"
|
||||
RequestService_GetMailingListByID_FullMethodName = "/request.RequestService/GetMailingListByID"
|
||||
)
|
||||
|
||||
// RequestServiceClient is the client API for RequestService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type RequestServiceClient interface {
|
||||
CreateTZ(ctx context.Context, in *CreateTZRequest, opts ...grpc.CallOption) (*CreateTZResponse, error)
|
||||
ApproveTZ(ctx context.Context, in *ApproveTZRequest, opts ...grpc.CallOption) (*ApproveTZResponse, error)
|
||||
GetMailingList(ctx context.Context, in *GetMailingListRequest, opts ...grpc.CallOption) (*GetMailingListResponse, error)
|
||||
GetMailingListByID(ctx context.Context, in *GetMailingListByIDRequest, opts ...grpc.CallOption) (*GetMailingListByIDResponse, error)
|
||||
}
|
||||
|
||||
type requestServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewRequestServiceClient(cc grpc.ClientConnInterface) RequestServiceClient {
|
||||
return &requestServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *requestServiceClient) CreateTZ(ctx context.Context, in *CreateTZRequest, opts ...grpc.CallOption) (*CreateTZResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(CreateTZResponse)
|
||||
err := c.cc.Invoke(ctx, RequestService_CreateTZ_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *requestServiceClient) ApproveTZ(ctx context.Context, in *ApproveTZRequest, opts ...grpc.CallOption) (*ApproveTZResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ApproveTZResponse)
|
||||
err := c.cc.Invoke(ctx, RequestService_ApproveTZ_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *requestServiceClient) GetMailingList(ctx context.Context, in *GetMailingListRequest, opts ...grpc.CallOption) (*GetMailingListResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetMailingListResponse)
|
||||
err := c.cc.Invoke(ctx, RequestService_GetMailingList_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *requestServiceClient) GetMailingListByID(ctx context.Context, in *GetMailingListByIDRequest, opts ...grpc.CallOption) (*GetMailingListByIDResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetMailingListByIDResponse)
|
||||
err := c.cc.Invoke(ctx, RequestService_GetMailingListByID_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// RequestServiceServer is the server API for RequestService service.
|
||||
// All implementations must embed UnimplementedRequestServiceServer
|
||||
// for forward compatibility.
|
||||
type RequestServiceServer interface {
|
||||
CreateTZ(context.Context, *CreateTZRequest) (*CreateTZResponse, error)
|
||||
ApproveTZ(context.Context, *ApproveTZRequest) (*ApproveTZResponse, error)
|
||||
GetMailingList(context.Context, *GetMailingListRequest) (*GetMailingListResponse, error)
|
||||
GetMailingListByID(context.Context, *GetMailingListByIDRequest) (*GetMailingListByIDResponse, error)
|
||||
mustEmbedUnimplementedRequestServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedRequestServiceServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedRequestServiceServer struct{}
|
||||
|
||||
func (UnimplementedRequestServiceServer) CreateTZ(context.Context, *CreateTZRequest) (*CreateTZResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateTZ not implemented")
|
||||
}
|
||||
func (UnimplementedRequestServiceServer) ApproveTZ(context.Context, *ApproveTZRequest) (*ApproveTZResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ApproveTZ not implemented")
|
||||
}
|
||||
func (UnimplementedRequestServiceServer) GetMailingList(context.Context, *GetMailingListRequest) (*GetMailingListResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetMailingList not implemented")
|
||||
}
|
||||
func (UnimplementedRequestServiceServer) GetMailingListByID(context.Context, *GetMailingListByIDRequest) (*GetMailingListByIDResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetMailingListByID not implemented")
|
||||
}
|
||||
func (UnimplementedRequestServiceServer) mustEmbedUnimplementedRequestServiceServer() {}
|
||||
func (UnimplementedRequestServiceServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeRequestServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to RequestServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeRequestServiceServer interface {
|
||||
mustEmbedUnimplementedRequestServiceServer()
|
||||
}
|
||||
|
||||
func RegisterRequestServiceServer(s grpc.ServiceRegistrar, srv RequestServiceServer) {
|
||||
// If the following call pancis, it indicates UnimplementedRequestServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&RequestService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _RequestService_CreateTZ_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(CreateTZRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(RequestServiceServer).CreateTZ(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: RequestService_CreateTZ_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(RequestServiceServer).CreateTZ(ctx, req.(*CreateTZRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _RequestService_ApproveTZ_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ApproveTZRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(RequestServiceServer).ApproveTZ(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: RequestService_ApproveTZ_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(RequestServiceServer).ApproveTZ(ctx, req.(*ApproveTZRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _RequestService_GetMailingList_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetMailingListRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(RequestServiceServer).GetMailingList(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: RequestService_GetMailingList_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(RequestServiceServer).GetMailingList(ctx, req.(*GetMailingListRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _RequestService_GetMailingListByID_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetMailingListByIDRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(RequestServiceServer).GetMailingListByID(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: RequestService_GetMailingListByID_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(RequestServiceServer).GetMailingListByID(ctx, req.(*GetMailingListByIDRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// RequestService_ServiceDesc is the grpc.ServiceDesc for RequestService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var RequestService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "request.RequestService",
|
||||
HandlerType: (*RequestServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "CreateTZ",
|
||||
Handler: _RequestService_CreateTZ_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ApproveTZ",
|
||||
Handler: _RequestService_ApproveTZ_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetMailingList",
|
||||
Handler: _RequestService_GetMailingList_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetMailingListByID",
|
||||
Handler: _RequestService_GetMailingListByID_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "api/proto/request/request.proto",
|
||||
}
|
||||
201
pkg/pb/api/proto/supplier/supplier.pb.go
Normal file
201
pkg/pb/api/proto/supplier/supplier.pb.go
Normal file
@@ -0,0 +1,201 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.6
|
||||
// protoc v5.29.3
|
||||
// source: api/proto/supplier/supplier.proto
|
||||
|
||||
package supplier
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type ExportExcelRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"`
|
||||
UserId int64 `protobuf:"varint,2,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ExportExcelRequest) Reset() {
|
||||
*x = ExportExcelRequest{}
|
||||
mi := &file_api_proto_supplier_supplier_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ExportExcelRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ExportExcelRequest) ProtoMessage() {}
|
||||
|
||||
func (x *ExportExcelRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_supplier_supplier_proto_msgTypes[0]
|
||||
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 ExportExcelRequest.ProtoReflect.Descriptor instead.
|
||||
func (*ExportExcelRequest) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_supplier_supplier_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *ExportExcelRequest) GetRequestId() string {
|
||||
if x != nil {
|
||||
return x.RequestId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ExportExcelRequest) GetUserId() int64 {
|
||||
if x != nil {
|
||||
return x.UserId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type ExportExcelResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
FileData []byte `protobuf:"bytes,1,opt,name=file_data,json=fileData,proto3" json:"file_data,omitempty"`
|
||||
FileName string `protobuf:"bytes,2,opt,name=file_name,json=fileName,proto3" json:"file_name,omitempty"`
|
||||
MimeType string `protobuf:"bytes,3,opt,name=mime_type,json=mimeType,proto3" json:"mime_type,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ExportExcelResponse) Reset() {
|
||||
*x = ExportExcelResponse{}
|
||||
mi := &file_api_proto_supplier_supplier_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ExportExcelResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ExportExcelResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ExportExcelResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_supplier_supplier_proto_msgTypes[1]
|
||||
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 ExportExcelResponse.ProtoReflect.Descriptor instead.
|
||||
func (*ExportExcelResponse) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_supplier_supplier_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *ExportExcelResponse) GetFileData() []byte {
|
||||
if x != nil {
|
||||
return x.FileData
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ExportExcelResponse) GetFileName() string {
|
||||
if x != nil {
|
||||
return x.FileName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *ExportExcelResponse) GetMimeType() string {
|
||||
if x != nil {
|
||||
return x.MimeType
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_api_proto_supplier_supplier_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_api_proto_supplier_supplier_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"!api/proto/supplier/supplier.proto\x12\bsupplier\"L\n" +
|
||||
"\x12ExportExcelRequest\x12\x1d\n" +
|
||||
"\n" +
|
||||
"request_id\x18\x01 \x01(\tR\trequestId\x12\x17\n" +
|
||||
"\auser_id\x18\x02 \x01(\x03R\x06userId\"l\n" +
|
||||
"\x13ExportExcelResponse\x12\x1b\n" +
|
||||
"\tfile_data\x18\x01 \x01(\fR\bfileData\x12\x1b\n" +
|
||||
"\tfile_name\x18\x02 \x01(\tR\bfileName\x12\x1b\n" +
|
||||
"\tmime_type\x18\x03 \x01(\tR\bmimeType2]\n" +
|
||||
"\x0fSupplierService\x12J\n" +
|
||||
"\vExportExcel\x12\x1c.supplier.ExportExcelRequest\x1a\x1d.supplier.ExportExcelResponseB=Z;github.com/smart-search-gateway/api/proto/supplier/supplierb\x06proto3"
|
||||
|
||||
var (
|
||||
file_api_proto_supplier_supplier_proto_rawDescOnce sync.Once
|
||||
file_api_proto_supplier_supplier_proto_rawDescData []byte
|
||||
)
|
||||
|
||||
func file_api_proto_supplier_supplier_proto_rawDescGZIP() []byte {
|
||||
file_api_proto_supplier_supplier_proto_rawDescOnce.Do(func() {
|
||||
file_api_proto_supplier_supplier_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_api_proto_supplier_supplier_proto_rawDesc), len(file_api_proto_supplier_supplier_proto_rawDesc)))
|
||||
})
|
||||
return file_api_proto_supplier_supplier_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_api_proto_supplier_supplier_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_api_proto_supplier_supplier_proto_goTypes = []any{
|
||||
(*ExportExcelRequest)(nil), // 0: supplier.ExportExcelRequest
|
||||
(*ExportExcelResponse)(nil), // 1: supplier.ExportExcelResponse
|
||||
}
|
||||
var file_api_proto_supplier_supplier_proto_depIdxs = []int32{
|
||||
0, // 0: supplier.SupplierService.ExportExcel:input_type -> supplier.ExportExcelRequest
|
||||
1, // 1: supplier.SupplierService.ExportExcel:output_type -> supplier.ExportExcelResponse
|
||||
1, // [1:2] is the sub-list for method output_type
|
||||
0, // [0:1] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_api_proto_supplier_supplier_proto_init() }
|
||||
func file_api_proto_supplier_supplier_proto_init() {
|
||||
if File_api_proto_supplier_supplier_proto != nil {
|
||||
return
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_proto_supplier_supplier_proto_rawDesc), len(file_api_proto_supplier_supplier_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 2,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_api_proto_supplier_supplier_proto_goTypes,
|
||||
DependencyIndexes: file_api_proto_supplier_supplier_proto_depIdxs,
|
||||
MessageInfos: file_api_proto_supplier_supplier_proto_msgTypes,
|
||||
}.Build()
|
||||
File_api_proto_supplier_supplier_proto = out.File
|
||||
file_api_proto_supplier_supplier_proto_goTypes = nil
|
||||
file_api_proto_supplier_supplier_proto_depIdxs = nil
|
||||
}
|
||||
121
pkg/pb/api/proto/supplier/supplier_grpc.pb.go
Normal file
121
pkg/pb/api/proto/supplier/supplier_grpc.pb.go
Normal file
@@ -0,0 +1,121 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc v5.29.3
|
||||
// source: api/proto/supplier/supplier.proto
|
||||
|
||||
package supplier
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
SupplierService_ExportExcel_FullMethodName = "/supplier.SupplierService/ExportExcel"
|
||||
)
|
||||
|
||||
// SupplierServiceClient is the client API for SupplierService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type SupplierServiceClient interface {
|
||||
ExportExcel(ctx context.Context, in *ExportExcelRequest, opts ...grpc.CallOption) (*ExportExcelResponse, error)
|
||||
}
|
||||
|
||||
type supplierServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewSupplierServiceClient(cc grpc.ClientConnInterface) SupplierServiceClient {
|
||||
return &supplierServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *supplierServiceClient) ExportExcel(ctx context.Context, in *ExportExcelRequest, opts ...grpc.CallOption) (*ExportExcelResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ExportExcelResponse)
|
||||
err := c.cc.Invoke(ctx, SupplierService_ExportExcel_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// SupplierServiceServer is the server API for SupplierService service.
|
||||
// All implementations must embed UnimplementedSupplierServiceServer
|
||||
// for forward compatibility.
|
||||
type SupplierServiceServer interface {
|
||||
ExportExcel(context.Context, *ExportExcelRequest) (*ExportExcelResponse, error)
|
||||
mustEmbedUnimplementedSupplierServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedSupplierServiceServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedSupplierServiceServer struct{}
|
||||
|
||||
func (UnimplementedSupplierServiceServer) ExportExcel(context.Context, *ExportExcelRequest) (*ExportExcelResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ExportExcel not implemented")
|
||||
}
|
||||
func (UnimplementedSupplierServiceServer) mustEmbedUnimplementedSupplierServiceServer() {}
|
||||
func (UnimplementedSupplierServiceServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeSupplierServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to SupplierServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeSupplierServiceServer interface {
|
||||
mustEmbedUnimplementedSupplierServiceServer()
|
||||
}
|
||||
|
||||
func RegisterSupplierServiceServer(s grpc.ServiceRegistrar, srv SupplierServiceServer) {
|
||||
// If the following call pancis, it indicates UnimplementedSupplierServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&SupplierService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _SupplierService_ExportExcel_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ExportExcelRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(SupplierServiceServer).ExportExcel(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: SupplierService_ExportExcel_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(SupplierServiceServer).ExportExcel(ctx, req.(*ExportExcelRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// SupplierService_ServiceDesc is the grpc.ServiceDesc for SupplierService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var SupplierService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "supplier.SupplierService",
|
||||
HandlerType: (*SupplierServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "ExportExcel",
|
||||
Handler: _SupplierService_ExportExcel_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "api/proto/supplier/supplier.proto",
|
||||
}
|
||||
548
pkg/pb/api/proto/user/user.pb.go
Normal file
548
pkg/pb/api/proto/user/user.pb.go
Normal file
@@ -0,0 +1,548 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.6
|
||||
// protoc v5.29.3
|
||||
// source: api/proto/user/user.proto
|
||||
|
||||
package user
|
||||
|
||||
import (
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type GetInfoRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetInfoRequest) Reset() {
|
||||
*x = GetInfoRequest{}
|
||||
mi := &file_api_proto_user_user_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetInfoRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetInfoRequest) ProtoMessage() {}
|
||||
|
||||
func (x *GetInfoRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_user_user_proto_msgTypes[0]
|
||||
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 GetInfoRequest.ProtoReflect.Descriptor instead.
|
||||
func (*GetInfoRequest) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_user_user_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *GetInfoRequest) GetUserId() int64 {
|
||||
if x != nil {
|
||||
return x.UserId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type GetInfoResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Email string `protobuf:"bytes,1,opt,name=email,proto3" json:"email,omitempty"`
|
||||
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Phone string `protobuf:"bytes,3,opt,name=phone,proto3" json:"phone,omitempty"`
|
||||
CompanyName string `protobuf:"bytes,4,opt,name=company_name,json=companyName,proto3" json:"company_name,omitempty"`
|
||||
PaymentStatus string `protobuf:"bytes,5,opt,name=payment_status,json=paymentStatus,proto3" json:"payment_status,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetInfoResponse) Reset() {
|
||||
*x = GetInfoResponse{}
|
||||
mi := &file_api_proto_user_user_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetInfoResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetInfoResponse) ProtoMessage() {}
|
||||
|
||||
func (x *GetInfoResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_user_user_proto_msgTypes[1]
|
||||
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 GetInfoResponse.ProtoReflect.Descriptor instead.
|
||||
func (*GetInfoResponse) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_user_user_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *GetInfoResponse) GetEmail() string {
|
||||
if x != nil {
|
||||
return x.Email
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *GetInfoResponse) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *GetInfoResponse) GetPhone() string {
|
||||
if x != nil {
|
||||
return x.Phone
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *GetInfoResponse) GetCompanyName() string {
|
||||
if x != nil {
|
||||
return x.CompanyName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *GetInfoResponse) GetPaymentStatus() string {
|
||||
if x != nil {
|
||||
return x.PaymentStatus
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type GetBalanceRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetBalanceRequest) Reset() {
|
||||
*x = GetBalanceRequest{}
|
||||
mi := &file_api_proto_user_user_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetBalanceRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetBalanceRequest) ProtoMessage() {}
|
||||
|
||||
func (x *GetBalanceRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_user_user_proto_msgTypes[2]
|
||||
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 GetBalanceRequest.ProtoReflect.Descriptor instead.
|
||||
func (*GetBalanceRequest) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_user_user_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *GetBalanceRequest) GetUserId() int64 {
|
||||
if x != nil {
|
||||
return x.UserId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type GetBalanceResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Balance float64 `protobuf:"fixed64,1,opt,name=balance,proto3" json:"balance,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetBalanceResponse) Reset() {
|
||||
*x = GetBalanceResponse{}
|
||||
mi := &file_api_proto_user_user_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetBalanceResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetBalanceResponse) ProtoMessage() {}
|
||||
|
||||
func (x *GetBalanceResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_user_user_proto_msgTypes[3]
|
||||
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 GetBalanceResponse.ProtoReflect.Descriptor instead.
|
||||
func (*GetBalanceResponse) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_user_user_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *GetBalanceResponse) GetBalance() float64 {
|
||||
if x != nil {
|
||||
return x.Balance
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type GetStatisticsRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetStatisticsRequest) Reset() {
|
||||
*x = GetStatisticsRequest{}
|
||||
mi := &file_api_proto_user_user_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetStatisticsRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetStatisticsRequest) ProtoMessage() {}
|
||||
|
||||
func (x *GetStatisticsRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_user_user_proto_msgTypes[4]
|
||||
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 GetStatisticsRequest.ProtoReflect.Descriptor instead.
|
||||
func (*GetStatisticsRequest) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_user_user_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *GetStatisticsRequest) GetUserId() int64 {
|
||||
if x != nil {
|
||||
return x.UserId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type GetStatisticsResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
TotalRequests int32 `protobuf:"varint,1,opt,name=total_requests,json=totalRequests,proto3" json:"total_requests,omitempty"`
|
||||
SuccessfulRequests int32 `protobuf:"varint,2,opt,name=successful_requests,json=successfulRequests,proto3" json:"successful_requests,omitempty"`
|
||||
FailedRequests int32 `protobuf:"varint,3,opt,name=failed_requests,json=failedRequests,proto3" json:"failed_requests,omitempty"`
|
||||
TotalSpent float64 `protobuf:"fixed64,4,opt,name=total_spent,json=totalSpent,proto3" json:"total_spent,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetStatisticsResponse) Reset() {
|
||||
*x = GetStatisticsResponse{}
|
||||
mi := &file_api_proto_user_user_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetStatisticsResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetStatisticsResponse) ProtoMessage() {}
|
||||
|
||||
func (x *GetStatisticsResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_user_user_proto_msgTypes[5]
|
||||
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 GetStatisticsResponse.ProtoReflect.Descriptor instead.
|
||||
func (*GetStatisticsResponse) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_user_user_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *GetStatisticsResponse) GetTotalRequests() int32 {
|
||||
if x != nil {
|
||||
return x.TotalRequests
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *GetStatisticsResponse) GetSuccessfulRequests() int32 {
|
||||
if x != nil {
|
||||
return x.SuccessfulRequests
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *GetStatisticsResponse) GetFailedRequests() int32 {
|
||||
if x != nil {
|
||||
return x.FailedRequests
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *GetStatisticsResponse) GetTotalSpent() float64 {
|
||||
if x != nil {
|
||||
return x.TotalSpent
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type GetBalanceStatisticsRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
UserId int64 `protobuf:"varint,1,opt,name=user_id,json=userId,proto3" json:"user_id,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetBalanceStatisticsRequest) Reset() {
|
||||
*x = GetBalanceStatisticsRequest{}
|
||||
mi := &file_api_proto_user_user_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetBalanceStatisticsRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetBalanceStatisticsRequest) ProtoMessage() {}
|
||||
|
||||
func (x *GetBalanceStatisticsRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_user_user_proto_msgTypes[6]
|
||||
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 GetBalanceStatisticsRequest.ProtoReflect.Descriptor instead.
|
||||
func (*GetBalanceStatisticsRequest) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_user_user_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *GetBalanceStatisticsRequest) GetUserId() int64 {
|
||||
if x != nil {
|
||||
return x.UserId
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type GetBalanceStatisticsResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Balance float64 `protobuf:"fixed64,1,opt,name=balance,proto3" json:"balance,omitempty"`
|
||||
TotalRequests int32 `protobuf:"varint,2,opt,name=total_requests,json=totalRequests,proto3" json:"total_requests,omitempty"`
|
||||
TotalSpent float64 `protobuf:"fixed64,3,opt,name=total_spent,json=totalSpent,proto3" json:"total_spent,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetBalanceStatisticsResponse) Reset() {
|
||||
*x = GetBalanceStatisticsResponse{}
|
||||
mi := &file_api_proto_user_user_proto_msgTypes[7]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetBalanceStatisticsResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetBalanceStatisticsResponse) ProtoMessage() {}
|
||||
|
||||
func (x *GetBalanceStatisticsResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_proto_user_user_proto_msgTypes[7]
|
||||
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 GetBalanceStatisticsResponse.ProtoReflect.Descriptor instead.
|
||||
func (*GetBalanceStatisticsResponse) Descriptor() ([]byte, []int) {
|
||||
return file_api_proto_user_user_proto_rawDescGZIP(), []int{7}
|
||||
}
|
||||
|
||||
func (x *GetBalanceStatisticsResponse) GetBalance() float64 {
|
||||
if x != nil {
|
||||
return x.Balance
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *GetBalanceStatisticsResponse) GetTotalRequests() int32 {
|
||||
if x != nil {
|
||||
return x.TotalRequests
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *GetBalanceStatisticsResponse) GetTotalSpent() float64 {
|
||||
if x != nil {
|
||||
return x.TotalSpent
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
var File_api_proto_user_user_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_api_proto_user_user_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\x19api/proto/user/user.proto\x12\x04user\")\n" +
|
||||
"\x0eGetInfoRequest\x12\x17\n" +
|
||||
"\auser_id\x18\x01 \x01(\x03R\x06userId\"\x9b\x01\n" +
|
||||
"\x0fGetInfoResponse\x12\x14\n" +
|
||||
"\x05email\x18\x01 \x01(\tR\x05email\x12\x12\n" +
|
||||
"\x04name\x18\x02 \x01(\tR\x04name\x12\x14\n" +
|
||||
"\x05phone\x18\x03 \x01(\tR\x05phone\x12!\n" +
|
||||
"\fcompany_name\x18\x04 \x01(\tR\vcompanyName\x12%\n" +
|
||||
"\x0epayment_status\x18\x05 \x01(\tR\rpaymentStatus\",\n" +
|
||||
"\x11GetBalanceRequest\x12\x17\n" +
|
||||
"\auser_id\x18\x01 \x01(\x03R\x06userId\".\n" +
|
||||
"\x12GetBalanceResponse\x12\x18\n" +
|
||||
"\abalance\x18\x01 \x01(\x01R\abalance\"/\n" +
|
||||
"\x14GetStatisticsRequest\x12\x17\n" +
|
||||
"\auser_id\x18\x01 \x01(\x03R\x06userId\"\xb9\x01\n" +
|
||||
"\x15GetStatisticsResponse\x12%\n" +
|
||||
"\x0etotal_requests\x18\x01 \x01(\x05R\rtotalRequests\x12/\n" +
|
||||
"\x13successful_requests\x18\x02 \x01(\x05R\x12successfulRequests\x12'\n" +
|
||||
"\x0ffailed_requests\x18\x03 \x01(\x05R\x0efailedRequests\x12\x1f\n" +
|
||||
"\vtotal_spent\x18\x04 \x01(\x01R\n" +
|
||||
"totalSpent\"6\n" +
|
||||
"\x1bGetBalanceStatisticsRequest\x12\x17\n" +
|
||||
"\auser_id\x18\x01 \x01(\x03R\x06userId\"\x80\x01\n" +
|
||||
"\x1cGetBalanceStatisticsResponse\x12\x18\n" +
|
||||
"\abalance\x18\x01 \x01(\x01R\abalance\x12%\n" +
|
||||
"\x0etotal_requests\x18\x02 \x01(\x05R\rtotalRequests\x12\x1f\n" +
|
||||
"\vtotal_spent\x18\x03 \x01(\x01R\n" +
|
||||
"totalSpent2\xaf\x02\n" +
|
||||
"\vUserService\x126\n" +
|
||||
"\aGetInfo\x12\x14.user.GetInfoRequest\x1a\x15.user.GetInfoResponse\x12?\n" +
|
||||
"\n" +
|
||||
"GetBalance\x12\x17.user.GetBalanceRequest\x1a\x18.user.GetBalanceResponse\x12H\n" +
|
||||
"\rGetStatistics\x12\x1a.user.GetStatisticsRequest\x1a\x1b.user.GetStatisticsResponse\x12]\n" +
|
||||
"\x14GetBalanceStatistics\x12!.user.GetBalanceStatisticsRequest\x1a\".user.GetBalanceStatisticsResponseB5Z3github.com/smart-search-gateway/api/proto/user/userb\x06proto3"
|
||||
|
||||
var (
|
||||
file_api_proto_user_user_proto_rawDescOnce sync.Once
|
||||
file_api_proto_user_user_proto_rawDescData []byte
|
||||
)
|
||||
|
||||
func file_api_proto_user_user_proto_rawDescGZIP() []byte {
|
||||
file_api_proto_user_user_proto_rawDescOnce.Do(func() {
|
||||
file_api_proto_user_user_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_api_proto_user_user_proto_rawDesc), len(file_api_proto_user_user_proto_rawDesc)))
|
||||
})
|
||||
return file_api_proto_user_user_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_api_proto_user_user_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
|
||||
var file_api_proto_user_user_proto_goTypes = []any{
|
||||
(*GetInfoRequest)(nil), // 0: user.GetInfoRequest
|
||||
(*GetInfoResponse)(nil), // 1: user.GetInfoResponse
|
||||
(*GetBalanceRequest)(nil), // 2: user.GetBalanceRequest
|
||||
(*GetBalanceResponse)(nil), // 3: user.GetBalanceResponse
|
||||
(*GetStatisticsRequest)(nil), // 4: user.GetStatisticsRequest
|
||||
(*GetStatisticsResponse)(nil), // 5: user.GetStatisticsResponse
|
||||
(*GetBalanceStatisticsRequest)(nil), // 6: user.GetBalanceStatisticsRequest
|
||||
(*GetBalanceStatisticsResponse)(nil), // 7: user.GetBalanceStatisticsResponse
|
||||
}
|
||||
var file_api_proto_user_user_proto_depIdxs = []int32{
|
||||
0, // 0: user.UserService.GetInfo:input_type -> user.GetInfoRequest
|
||||
2, // 1: user.UserService.GetBalance:input_type -> user.GetBalanceRequest
|
||||
4, // 2: user.UserService.GetStatistics:input_type -> user.GetStatisticsRequest
|
||||
6, // 3: user.UserService.GetBalanceStatistics:input_type -> user.GetBalanceStatisticsRequest
|
||||
1, // 4: user.UserService.GetInfo:output_type -> user.GetInfoResponse
|
||||
3, // 5: user.UserService.GetBalance:output_type -> user.GetBalanceResponse
|
||||
5, // 6: user.UserService.GetStatistics:output_type -> user.GetStatisticsResponse
|
||||
7, // 7: user.UserService.GetBalanceStatistics:output_type -> user.GetBalanceStatisticsResponse
|
||||
4, // [4:8] is the sub-list for method output_type
|
||||
0, // [0:4] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_api_proto_user_user_proto_init() }
|
||||
func file_api_proto_user_user_proto_init() {
|
||||
if File_api_proto_user_user_proto != nil {
|
||||
return
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_proto_user_user_proto_rawDesc), len(file_api_proto_user_user_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 8,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
GoTypes: file_api_proto_user_user_proto_goTypes,
|
||||
DependencyIndexes: file_api_proto_user_user_proto_depIdxs,
|
||||
MessageInfos: file_api_proto_user_user_proto_msgTypes,
|
||||
}.Build()
|
||||
File_api_proto_user_user_proto = out.File
|
||||
file_api_proto_user_user_proto_goTypes = nil
|
||||
file_api_proto_user_user_proto_depIdxs = nil
|
||||
}
|
||||
235
pkg/pb/api/proto/user/user_grpc.pb.go
Normal file
235
pkg/pb/api/proto/user/user_grpc.pb.go
Normal file
@@ -0,0 +1,235 @@
|
||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||
// versions:
|
||||
// - protoc-gen-go-grpc v1.5.1
|
||||
// - protoc v5.29.3
|
||||
// source: api/proto/user/user.proto
|
||||
|
||||
package user
|
||||
|
||||
import (
|
||||
context "context"
|
||||
grpc "google.golang.org/grpc"
|
||||
codes "google.golang.org/grpc/codes"
|
||||
status "google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
// Requires gRPC-Go v1.64.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
UserService_GetInfo_FullMethodName = "/user.UserService/GetInfo"
|
||||
UserService_GetBalance_FullMethodName = "/user.UserService/GetBalance"
|
||||
UserService_GetStatistics_FullMethodName = "/user.UserService/GetStatistics"
|
||||
UserService_GetBalanceStatistics_FullMethodName = "/user.UserService/GetBalanceStatistics"
|
||||
)
|
||||
|
||||
// UserServiceClient is the client API for UserService service.
|
||||
//
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type UserServiceClient interface {
|
||||
GetInfo(ctx context.Context, in *GetInfoRequest, opts ...grpc.CallOption) (*GetInfoResponse, error)
|
||||
GetBalance(ctx context.Context, in *GetBalanceRequest, opts ...grpc.CallOption) (*GetBalanceResponse, error)
|
||||
GetStatistics(ctx context.Context, in *GetStatisticsRequest, opts ...grpc.CallOption) (*GetStatisticsResponse, error)
|
||||
GetBalanceStatistics(ctx context.Context, in *GetBalanceStatisticsRequest, opts ...grpc.CallOption) (*GetBalanceStatisticsResponse, error)
|
||||
}
|
||||
|
||||
type userServiceClient struct {
|
||||
cc grpc.ClientConnInterface
|
||||
}
|
||||
|
||||
func NewUserServiceClient(cc grpc.ClientConnInterface) UserServiceClient {
|
||||
return &userServiceClient{cc}
|
||||
}
|
||||
|
||||
func (c *userServiceClient) GetInfo(ctx context.Context, in *GetInfoRequest, opts ...grpc.CallOption) (*GetInfoResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetInfoResponse)
|
||||
err := c.cc.Invoke(ctx, UserService_GetInfo_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *userServiceClient) GetBalance(ctx context.Context, in *GetBalanceRequest, opts ...grpc.CallOption) (*GetBalanceResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetBalanceResponse)
|
||||
err := c.cc.Invoke(ctx, UserService_GetBalance_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *userServiceClient) GetStatistics(ctx context.Context, in *GetStatisticsRequest, opts ...grpc.CallOption) (*GetStatisticsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetStatisticsResponse)
|
||||
err := c.cc.Invoke(ctx, UserService_GetStatistics_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *userServiceClient) GetBalanceStatistics(ctx context.Context, in *GetBalanceStatisticsRequest, opts ...grpc.CallOption) (*GetBalanceStatisticsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(GetBalanceStatisticsResponse)
|
||||
err := c.cc.Invoke(ctx, UserService_GetBalanceStatistics_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// UserServiceServer is the server API for UserService service.
|
||||
// All implementations must embed UnimplementedUserServiceServer
|
||||
// for forward compatibility.
|
||||
type UserServiceServer interface {
|
||||
GetInfo(context.Context, *GetInfoRequest) (*GetInfoResponse, error)
|
||||
GetBalance(context.Context, *GetBalanceRequest) (*GetBalanceResponse, error)
|
||||
GetStatistics(context.Context, *GetStatisticsRequest) (*GetStatisticsResponse, error)
|
||||
GetBalanceStatistics(context.Context, *GetBalanceStatisticsRequest) (*GetBalanceStatisticsResponse, error)
|
||||
mustEmbedUnimplementedUserServiceServer()
|
||||
}
|
||||
|
||||
// UnimplementedUserServiceServer must be embedded to have
|
||||
// forward compatible implementations.
|
||||
//
|
||||
// NOTE: this should be embedded by value instead of pointer to avoid a nil
|
||||
// pointer dereference when methods are called.
|
||||
type UnimplementedUserServiceServer struct{}
|
||||
|
||||
func (UnimplementedUserServiceServer) GetInfo(context.Context, *GetInfoRequest) (*GetInfoResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetInfo not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) GetBalance(context.Context, *GetBalanceRequest) (*GetBalanceResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetBalance not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) GetStatistics(context.Context, *GetStatisticsRequest) (*GetStatisticsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetStatistics not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) GetBalanceStatistics(context.Context, *GetBalanceStatisticsRequest) (*GetBalanceStatisticsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method GetBalanceStatistics not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) mustEmbedUnimplementedUserServiceServer() {}
|
||||
func (UnimplementedUserServiceServer) testEmbeddedByValue() {}
|
||||
|
||||
// UnsafeUserServiceServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to UserServiceServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeUserServiceServer interface {
|
||||
mustEmbedUnimplementedUserServiceServer()
|
||||
}
|
||||
|
||||
func RegisterUserServiceServer(s grpc.ServiceRegistrar, srv UserServiceServer) {
|
||||
// If the following call pancis, it indicates UnimplementedUserServiceServer was
|
||||
// embedded by pointer and is nil. This will cause panics if an
|
||||
// unimplemented method is ever invoked, so we test this at initialization
|
||||
// time to prevent it from happening at runtime later due to I/O.
|
||||
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
|
||||
t.testEmbeddedByValue()
|
||||
}
|
||||
s.RegisterService(&UserService_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _UserService_GetInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetInfoRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(UserServiceServer).GetInfo(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: UserService_GetInfo_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(UserServiceServer).GetInfo(ctx, req.(*GetInfoRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _UserService_GetBalance_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetBalanceRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(UserServiceServer).GetBalance(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: UserService_GetBalance_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(UserServiceServer).GetBalance(ctx, req.(*GetBalanceRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _UserService_GetStatistics_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetStatisticsRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(UserServiceServer).GetStatistics(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: UserService_GetStatistics_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(UserServiceServer).GetStatistics(ctx, req.(*GetStatisticsRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _UserService_GetBalanceStatistics_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(GetBalanceStatisticsRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(UserServiceServer).GetBalanceStatistics(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: UserService_GetBalanceStatistics_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(UserServiceServer).GetBalanceStatistics(ctx, req.(*GetBalanceStatisticsRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// UserService_ServiceDesc is the grpc.ServiceDesc for UserService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var UserService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "user.UserService",
|
||||
HandlerType: (*UserServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "GetInfo",
|
||||
Handler: _UserService_GetInfo_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetBalance",
|
||||
Handler: _UserService_GetBalance_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetStatistics",
|
||||
Handler: _UserService_GetStatistics_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "GetBalanceStatistics",
|
||||
Handler: _UserService_GetBalanceStatistics_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "api/proto/user/user.proto",
|
||||
}
|
||||
Reference in New Issue
Block a user