From 3974f0e5df267d5ed3f4dab32ab51e50bef1c269 Mon Sep 17 00:00:00 2001 From: Wer1d <98684652+Wer1d@users.noreply.github.com> Date: Mon, 25 Dec 2023 01:07:26 +0700 Subject: [PATCH 1/4] feat: document swagger parent 3afc3f0466b38aea60c6aa141e0aafac631cfc7a author Wer1d <98684652+Wer1d@users.noreply.github.com> 1703441246 +0700 committer Wer1d <98684652+Wer1d@users.noreply.github.com> 1703441246 +0700 refactor: delete godotenv feat : add swagger fix: change BasicAuth to Bearer fix: delete import godotenv docs: auth docs docs: add user-not-found feat: config cors (#15) feat: Register + Login OIDC (#4) * feat: Register + Login OIDC * fix: fix user model * fix: combine login ®ister, add apperror, normalize database, getUser by header * fix: add atlas migrate, move logic from handler to service, use dto, add logic update * fix: repository, typo, ip/op type * fix: update init sql * refactor: remove migrate.md * fix:typo, config linters * refactor: run lint-fix * fix: normalize round, department, section * fix: model dep and section * refactor:linter-fix * refactor: lint-fix * fix: add fk in init sql, remove update in register, move convert to util file * fix: init sql , remove endpoint, change id to composit key * refactor: auth handler feat: document swagger fix: change BasicAuth to Bearer docs: auth docs docs: all refactor: go mod tidy --- .env.example | 2 +- cfgldr/cfgldr.go | 35 + cmd/main.go | 15 +- docs/docs.go | 876 ++++++++++++++++++ docs/swagger.json | 854 +++++++++++++++++ docs/swagger.yaml | 573 ++++++++++++ go.mod | 17 +- go.sum | 41 +- internal/auth/auth.dto.go | 103 ++ internal/auth/auth.handler.go | 45 + internal/auth/auth.model.go | 3 - internal/auth/auth.repository.go | 2 +- internal/auth/auth.util.go | 2 +- internal/event/event.dto.go | 68 ++ internal/event/event.handler.go | 23 + internal/feature_flag/feature_flag.dto.go | 17 + internal/feature_flag/feature_flag.handler.go | 11 + internal/health_check/health_check.handler.go | 9 + 18 files changed, 2682 insertions(+), 14 deletions(-) create mode 100644 docs/docs.go create mode 100644 docs/swagger.json create mode 100644 docs/swagger.yaml create mode 100644 internal/event/event.dto.go create mode 100644 internal/feature_flag/feature_flag.dto.go diff --git a/.env.example b/.env.example index 5d632a1..53971c0 100644 --- a/.env.example +++ b/.env.example @@ -12,4 +12,4 @@ OAUTH2_CLIENT_SECRET=123456 OAUTH2_REDIRECT_URL=http://localhost:3000/auth/callback OAUTH2_SCOPES=openid,email -CORS_ORIGINS=https://openhouse.chula.ac.th,https://isd-sgcu.in.th,https://openhouse.isd-sgcu.in.th \ No newline at end of file +CORS_ORIGINS=https://openhouse.chula.ac.th,https://isd-sgcu.in.th,https://openhouse.isd-sgcu.in.th diff --git a/cfgldr/cfgldr.go b/cfgldr/cfgldr.go index 42f62dd..156ec80 100644 --- a/cfgldr/cfgldr.go +++ b/cfgldr/cfgldr.go @@ -10,6 +10,8 @@ type Config struct { RedisConfig RedisConfig OAuth2Config OAuth2Config CorsConfig CorsConfig + OAuth2Config OAuth2Config + CorsConfig CorsConfig } type DatabaseConfig struct { @@ -38,6 +40,19 @@ type CorsConfig struct { AllowOrigins string `mapstructure:"ORIGINS"` } +type OAuth2Config struct { + RedirectURL string `mapstructure:"REDIRECT_URL"` + ClientID string `mapstructure:"CLIENT_ID"` + ClientSecret string `mapstructure:"CLIENT_SECRET"` + Scopes []string `mapstructure:"SCOPES"` + AllowOrigins string `mapstructure:"ORIGINS"` + Endpoint string `mapstructure:"ENDPOINT"` +} + +type CorsConfig struct { + AllowOrigins string `mapstructure:"ORIGINS"` +} + func LoadConfig() (*Config, error) { dbCfgLdr := viper.New() dbCfgLdr.SetEnvPrefix("DB") @@ -84,12 +99,32 @@ func LoadConfig() (*Config, error) { return nil, err } + oauth2CfgLdr := viper.New() + oauth2CfgLdr.SetEnvPrefix("OAUTH2") + oauth2CfgLdr.AutomaticEnv() + oauth2CfgLdr.AllowEmptyEnv(false) + oauth2Config := OAuth2Config{} + if err := oauth2CfgLdr.Unmarshal(&oauth2Config); err != nil { + return nil, err + } + + corsConfigLdr := viper.New() + corsConfigLdr.SetEnvPrefix("CORS") + corsConfigLdr.AutomaticEnv() + dbCfgLdr.AllowEmptyEnv(false) + corsConfig := CorsConfig{} + if err := corsConfigLdr.Unmarshal(&corsConfig); err != nil { + return nil, err + } + return &Config{ DatabaseConfig: dbConfig, AppConfig: appConfig, RedisConfig: redisConfig, OAuth2Config: oauth2Config, CorsConfig: corsConfig, + OAuth2Config: oauth2Config, + CorsConfig: corsConfig, }, nil } diff --git a/cmd/main.go b/cmd/main.go index 7f683d1..752b469 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -5,8 +5,19 @@ import ( "github.com/gin-gonic/gin" "github.com/isd-sgcu/oph66-backend/di" + _ "github.com/isd-sgcu/oph66-backend/docs" + swaggerFiles "github.com/swaggo/files" + ginSwagger "github.com/swaggo/gin-swagger" ) +// @title OPH-66 Backend API +// @version 1.0 +// @description Documentation outlines the specifications and endpoints for the OPH-66 Backend API. +// @Schemes http https +// @securityDefinitions.apikey Bearer +// @in header +// @name Authorization +// @description Type "Bearer" followed by a space and JWT token. func main() { container, err := di.Init() if err != nil { @@ -20,7 +31,6 @@ func main() { r := gin.Default() r.Use(gin.HandlerFunc(container.CorsHandler)) - r.GET("/_hc", container.HcHandler.HealthCheck) r.GET("/live", container.FeatureflagHandler.GetLivestreamInfo) r.GET("/events", container.EventHandler.GetAllEvents) @@ -30,6 +40,9 @@ func main() { r.GET("/auth/login", container.AuthHandler.GoogleLogin) r.GET("/auth/callback", container.AuthHandler.GoogleCallback) + if container.Config.AppConfig.Env == "development" { + r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) + } if err := r.Run(fmt.Sprintf(":%v", container.Config.AppConfig.Port)); err != nil { container.Logger.Fatal("unable to start server") } diff --git a/docs/docs.go b/docs/docs.go new file mode 100644 index 0000000..176f69d --- /dev/null +++ b/docs/docs.go @@ -0,0 +1,876 @@ +// Package docs Code generated by swaggo/swag. DO NOT EDIT +package docs + +import "github.com/swaggo/swag" + +const docTemplate = `{ + "schemes": {{ marshal .Schemes }}, + "swagger": "2.0", + "info": { + "description": "{{escape .Description}}", + "title": "{{.Title}}", + "contact": {}, + "version": "{{.Version}}" + }, + "host": "{{.Host}}", + "basePath": "{{.BasePath}}", + "paths": { + "/_hc": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Health Check for the service", + "produces": [ + "text/plain" + ], + "tags": [ + "healthcheck" + ], + "summary": "Health Check", + "operationId": "HealthCheck", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/auth/callback": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "After successfully logging in with a @chula account, you'll receive a token. If you attempt to log in using a different domain, Google will not allow the login", + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "receive a token after successfully login with Google", + "operationId": "GoogleCallback", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/auth.CallbackResponse" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/auth.CallbackInvalidResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/auth.CallbackErrorResponse" + } + } + } + } + }, + "/auth/login": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Redirect to Google login page", + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Redirect to Google login page", + "operationId": "GoogleLogin", + "responses": {} + } + }, + "/auth/me": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Get Profile of current user", + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Get Profile of current user", + "operationId": "GetProfile", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/auth.MockGetProfileResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/auth.GetProfileUnauthorized" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/auth.GetProfileUserNotFound" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/auth.GetProfileErrorResponse" + } + } + } + } + }, + "/auth/register": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Register new account with @chula email", + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Register", + "operationId": "Register", + "parameters": [ + { + "description": "User", + "name": "user", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/auth.MockUser" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/auth.MockRegisterResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/auth.RegisterUnauthorized" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/auth.RegisterInvalidResponse" + } + }, + "498": { + "description": "", + "schema": { + "$ref": "#/definitions/auth.RegisterInvalidToken" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/auth.RegisterErrorResponse" + } + } + } + } + }, + "/events": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Get all events as array of events", + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "Get all events", + "operationId": "GetAllEvents", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/event.Event" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/event.EventInvalidResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/event.EventAllErrorResponse" + } + } + } + } + }, + "/events/{eventId}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Get event by id", + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "get event by id", + "operationId": "GetEventById", + "parameters": [ + { + "type": "string", + "description": "event id", + "name": "eventId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/event.EventDTO" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/event.EventInvalidResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/event.EventErrorResponse" + } + } + } + } + }, + "/live": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Get livestream flag", + "produces": [ + "application/json" + ], + "tags": [ + "FeatureFlag" + ], + "summary": "Get livestream flag", + "operationId": "GetLivestreamInfo", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/featureflag.response" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/featureflag.invalidResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/featureflag.errorResponse" + } + } + } + } + } + }, + "definitions": { + "auth.CallbackErrorResponse": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/auth/callback" + }, + "title": { + "type": "string", + "example": "internal-server-error" + } + } + }, + "auth.CallbackInvalidResponse": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/auth/callback" + }, + "title": { + "type": "string", + "example": "bad-request" + } + } + }, + "auth.CallbackResponse": { + "type": "object", + "properties": { + "token": { + "type": "string", + "example": "gbxnZjiHVzb_4mDQTQNiJdrZFOCactWXkZvZOxS2_qZsy7vAQY7uA2RFIHe2JABoEjhT0Y3KlOJuOEvE2YJMLrJDagwhpAITGex" + } + } + }, + "auth.GetProfileErrorResponse": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/auth/me" + }, + "title": { + "type": "string", + "example": "internal-server-error" + } + } + }, + "auth.GetProfileUnauthorized": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/auth/me" + }, + "title": { + "type": "string", + "example": "unauthorized" + } + } + }, + "auth.GetProfileUserNotFound": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/auth/me" + }, + "title": { + "type": "string", + "example": "user-not-found" + } + } + }, + "auth.MockDesiredRound": { + "type": "object", + "properties": { + "code": { + "type": "string", + "example": "1" + }, + "order": { + "type": "integer", + "example": 1 + } + } + }, + "auth.MockGetProfileResponse": { + "type": "object", + "properties": { + "user": { + "$ref": "#/definitions/auth.MockUser" + } + } + }, + "auth.MockInterestedFaculty": { + "type": "object", + "properties": { + "code": { + "type": "string", + "example": "1" + }, + "order": { + "type": "integer", + "example": 1 + } + } + }, + "auth.MockRegisterResponse": { + "type": "object", + "properties": { + "user": { + "$ref": "#/definitions/auth.MockUser" + } + } + }, + "auth.MockUser": { + "type": "object", + "properties": { + "address": { + "type": "string", + "example": "Bangkok" + }, + "allergy": { + "type": "string", + "example": "None" + }, + "birth_date": { + "type": "string", + "example": "1990-01-01" + }, + "desired_rounds": { + "type": "array", + "items": { + "$ref": "#/definitions/auth.MockDesiredRound" + } + }, + "first_name": { + "type": "string", + "example": "John" + }, + "from_abroad": { + "type": "string", + "example": "no" + }, + "gender": { + "type": "string", + "example": "male" + }, + "grade": { + "type": "string", + "example": "undergraduate" + }, + "interested_faculties": { + "type": "array", + "items": { + "$ref": "#/definitions/auth.MockInterestedFaculty" + } + }, + "join_cu_reason": { + "type": "string", + "example": "Interested in the programs offered" + }, + "last_name": { + "type": "string", + "example": "Doe" + }, + "medical_condition": { + "type": "string", + "example": "None" + }, + "news_source": { + "type": "string", + "example": "Facebook" + }, + "school": { + "type": "string", + "example": "CU" + }, + "status": { + "type": "string", + "example": "student" + } + } + }, + "auth.RegisterErrorResponse": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/auth/register" + }, + "title": { + "type": "string", + "example": "internal-server-error" + } + } + }, + "auth.RegisterInvalidResponse": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/auth/register" + }, + "title": { + "type": "string", + "example": "bad-request" + } + } + }, + "auth.RegisterInvalidToken": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/auth/register" + }, + "title": { + "type": "string", + "example": "invalid-token" + } + } + }, + "auth.RegisterUnauthorized": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/auth/register" + }, + "title": { + "type": "string", + "example": "unauthorized" + } + } + }, + "bilingual_field.Bilingual": { + "type": "object", + "properties": { + "en": { + "type": "string" + }, + "th": { + "type": "string" + } + } + }, + "event.DepartmentBilingual": { + "type": "object", + "properties": { + "en": { + "type": "string", + "example": "Computer Engineering" + }, + "th": { + "type": "string", + "example": "ภาควิชาคอมพิวเตอร์" + } + } + }, + "event.DescriptionBilingual": { + "type": "object", + "properties": { + "en": { + "type": "string", + "example": "This is the first event." + }, + "th": { + "type": "string", + "example": "รายละเอียดอีเวนท์แรก" + } + } + }, + "event.Event": { + "type": "object", + "properties": { + "department": { + "$ref": "#/definitions/bilingual_field.Bilingual" + }, + "description": { + "$ref": "#/definitions/bilingual_field.Bilingual" + }, + "faculty": { + "$ref": "#/definitions/faculty.Faculty" + }, + "id": { + "type": "string" + }, + "location": { + "$ref": "#/definitions/bilingual_field.Bilingual" + }, + "max_capacity": { + "type": "integer" + }, + "name": { + "$ref": "#/definitions/bilingual_field.Bilingual" + }, + "require_registration": { + "type": "boolean" + }, + "schedules": { + "type": "array", + "items": { + "$ref": "#/definitions/schedule.Schedule" + } + } + } + }, + "event.EventAllErrorResponse": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/events" + }, + "title": { + "type": "string", + "example": "internal-server-error" + } + } + }, + "event.EventDTO": { + "type": "object", + "properties": { + "department": { + "$ref": "#/definitions/event.DepartmentBilingual" + }, + "description": { + "$ref": "#/definitions/event.DescriptionBilingual" + }, + "faculty": { + "$ref": "#/definitions/event.Faculty" + }, + "id": { + "type": "string", + "example": "first-event" + }, + "location": { + "$ref": "#/definitions/event.LocationBilingual" + }, + "max_capacity": { + "type": "integer", + "example": 100 + }, + "name": { + "$ref": "#/definitions/event.NameEventBilingual" + }, + "require_registration": { + "type": "boolean", + "example": true + }, + "schedules": { + "type": "array", + "items": { + "$ref": "#/definitions/event.Schedule" + } + } + } + }, + "event.EventErrorResponse": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/events/:eventId" + }, + "title": { + "type": "string", + "example": "internal-server-error" + } + } + }, + "event.EventInvalidResponse": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/events/:eventId" + }, + "title": { + "type": "string", + "example": "invalid-event-id" + } + } + }, + "event.Faculty": { + "type": "object", + "properties": { + "code": { + "type": "string", + "example": "21" + }, + "name": { + "$ref": "#/definitions/event.NameFacultyBilingual" + } + } + }, + "event.LocationBilingual": { + "type": "object", + "properties": { + "en": { + "type": "string", + "example": "SIT Building" + }, + "th": { + "type": "string", + "example": "อาคาร SIT" + } + } + }, + "event.NameEventBilingual": { + "type": "object", + "properties": { + "en": { + "type": "string", + "example": "First Event" + }, + "th": { + "type": "string", + "example": "อีเวนท์แรก" + } + } + }, + "event.NameFacultyBilingual": { + "type": "object", + "properties": { + "en": { + "type": "string", + "example": "Faculty of Engineering" + }, + "th": { + "type": "string", + "example": "คณะวิศวกรรมศาสตร์" + } + } + }, + "event.Schedule": { + "type": "object", + "properties": { + "ends_at": { + "type": "string", + "example": "2021-08-01T00:00:00+07:00" + }, + "starts_at": { + "type": "string", + "example": "2021-08-01T00:00:00+07:00" + } + } + }, + "faculty.Faculty": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "name": { + "$ref": "#/definitions/bilingual_field.Bilingual" + } + } + }, + "featureflag.errorResponse": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/featureflag/live" + }, + "title": { + "type": "string", + "example": "internal-server-error" + } + } + }, + "featureflag.invalidResponse": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/featureflag/live" + }, + "title": { + "type": "string", + "example": "invalid-feature-flag-key" + } + } + }, + "featureflag.response": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "example": true + }, + "extra_info": { + "type": "string", + "example": "https://www.youtube.com/watch?v=6n3pFFPSlW4" + }, + "key": { + "type": "string", + "example": "livestream" + } + } + }, + "schedule.Schedule": { + "type": "object", + "properties": { + "ends_at": { + "type": "string" + }, + "starts_at": { + "type": "string" + } + } + } + }, + "securityDefinitions": { + "Bearer": { + "description": "Type \"Bearer\" followed by a space and JWT token.", + "type": "apiKey", + "name": "Authorization", + "in": "header" + } + } +}` + +// SwaggerInfo holds exported Swagger Info so clients can modify it +var SwaggerInfo = &swag.Spec{ + Version: "1.0", + Host: "", + BasePath: "", + Schemes: []string{"http", "https"}, + Title: "OPH-66 Backend API", + Description: "Documentation outlines the specifications and endpoints for the OPH-66 Backend API.", + InfoInstanceName: "swagger", + SwaggerTemplate: docTemplate, + LeftDelim: "{{", + RightDelim: "}}", +} + +func init() { + swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo) +} diff --git a/docs/swagger.json b/docs/swagger.json new file mode 100644 index 0000000..0ab73e1 --- /dev/null +++ b/docs/swagger.json @@ -0,0 +1,854 @@ +{ + "schemes": [ + "http", + "https" + ], + "swagger": "2.0", + "info": { + "description": "Documentation outlines the specifications and endpoints for the OPH-66 Backend API.", + "title": "OPH-66 Backend API", + "contact": {}, + "version": "1.0" + }, + "paths": { + "/_hc": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Health Check for the service", + "produces": [ + "text/plain" + ], + "tags": [ + "healthcheck" + ], + "summary": "Health Check", + "operationId": "HealthCheck", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "string" + } + } + } + } + }, + "/auth/callback": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "After successfully logging in with a @chula account, you'll receive a token. If you attempt to log in using a different domain, Google will not allow the login", + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "receive a token after successfully login with Google", + "operationId": "GoogleCallback", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/auth.CallbackResponse" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/auth.CallbackInvalidResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/auth.CallbackErrorResponse" + } + } + } + } + }, + "/auth/login": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Redirect to Google login page", + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Redirect to Google login page", + "operationId": "GoogleLogin", + "responses": {} + } + }, + "/auth/me": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Get Profile of current user", + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Get Profile of current user", + "operationId": "GetProfile", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/auth.MockGetProfileResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/auth.GetProfileUnauthorized" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/auth.GetProfileUserNotFound" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/auth.GetProfileErrorResponse" + } + } + } + } + }, + "/auth/register": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Register new account with @chula email", + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Register", + "operationId": "Register", + "parameters": [ + { + "description": "User", + "name": "user", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/auth.MockUser" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/auth.MockRegisterResponse" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/auth.RegisterUnauthorized" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/auth.RegisterInvalidResponse" + } + }, + "498": { + "description": "", + "schema": { + "$ref": "#/definitions/auth.RegisterInvalidToken" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/auth.RegisterErrorResponse" + } + } + } + } + }, + "/events": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Get all events as array of events", + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "Get all events", + "operationId": "GetAllEvents", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/event.Event" + } + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/event.EventInvalidResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/event.EventAllErrorResponse" + } + } + } + } + }, + "/events/{eventId}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Get event by id", + "produces": [ + "application/json" + ], + "tags": [ + "event" + ], + "summary": "get event by id", + "operationId": "GetEventById", + "parameters": [ + { + "type": "string", + "description": "event id", + "name": "eventId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/event.EventDTO" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/event.EventInvalidResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/event.EventErrorResponse" + } + } + } + } + }, + "/live": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "Get livestream flag", + "produces": [ + "application/json" + ], + "tags": [ + "FeatureFlag" + ], + "summary": "Get livestream flag", + "operationId": "GetLivestreamInfo", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/featureflag.response" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/featureflag.invalidResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/featureflag.errorResponse" + } + } + } + } + } + }, + "definitions": { + "auth.CallbackErrorResponse": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/auth/callback" + }, + "title": { + "type": "string", + "example": "internal-server-error" + } + } + }, + "auth.CallbackInvalidResponse": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/auth/callback" + }, + "title": { + "type": "string", + "example": "bad-request" + } + } + }, + "auth.CallbackResponse": { + "type": "object", + "properties": { + "token": { + "type": "string", + "example": "gbxnZjiHVzb_4mDQTQNiJdrZFOCactWXkZvZOxS2_qZsy7vAQY7uA2RFIHe2JABoEjhT0Y3KlOJuOEvE2YJMLrJDagwhpAITGex" + } + } + }, + "auth.GetProfileErrorResponse": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/auth/me" + }, + "title": { + "type": "string", + "example": "internal-server-error" + } + } + }, + "auth.GetProfileUnauthorized": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/auth/me" + }, + "title": { + "type": "string", + "example": "unauthorized" + } + } + }, + "auth.GetProfileUserNotFound": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/auth/me" + }, + "title": { + "type": "string", + "example": "user-not-found" + } + } + }, + "auth.MockDesiredRound": { + "type": "object", + "properties": { + "code": { + "type": "string", + "example": "1" + }, + "order": { + "type": "integer", + "example": 1 + } + } + }, + "auth.MockGetProfileResponse": { + "type": "object", + "properties": { + "user": { + "$ref": "#/definitions/auth.MockUser" + } + } + }, + "auth.MockInterestedFaculty": { + "type": "object", + "properties": { + "code": { + "type": "string", + "example": "1" + }, + "order": { + "type": "integer", + "example": 1 + } + } + }, + "auth.MockRegisterResponse": { + "type": "object", + "properties": { + "user": { + "$ref": "#/definitions/auth.MockUser" + } + } + }, + "auth.MockUser": { + "type": "object", + "properties": { + "address": { + "type": "string", + "example": "Bangkok" + }, + "allergy": { + "type": "string", + "example": "None" + }, + "birth_date": { + "type": "string", + "example": "1990-01-01" + }, + "desired_rounds": { + "type": "array", + "items": { + "$ref": "#/definitions/auth.MockDesiredRound" + } + }, + "first_name": { + "type": "string", + "example": "John" + }, + "from_abroad": { + "type": "string", + "example": "no" + }, + "gender": { + "type": "string", + "example": "male" + }, + "grade": { + "type": "string", + "example": "undergraduate" + }, + "interested_faculties": { + "type": "array", + "items": { + "$ref": "#/definitions/auth.MockInterestedFaculty" + } + }, + "join_cu_reason": { + "type": "string", + "example": "Interested in the programs offered" + }, + "last_name": { + "type": "string", + "example": "Doe" + }, + "medical_condition": { + "type": "string", + "example": "None" + }, + "news_source": { + "type": "string", + "example": "Facebook" + }, + "school": { + "type": "string", + "example": "CU" + }, + "status": { + "type": "string", + "example": "student" + } + } + }, + "auth.RegisterErrorResponse": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/auth/register" + }, + "title": { + "type": "string", + "example": "internal-server-error" + } + } + }, + "auth.RegisterInvalidResponse": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/auth/register" + }, + "title": { + "type": "string", + "example": "bad-request" + } + } + }, + "auth.RegisterInvalidToken": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/auth/register" + }, + "title": { + "type": "string", + "example": "invalid-token" + } + } + }, + "auth.RegisterUnauthorized": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/auth/register" + }, + "title": { + "type": "string", + "example": "unauthorized" + } + } + }, + "bilingual_field.Bilingual": { + "type": "object", + "properties": { + "en": { + "type": "string" + }, + "th": { + "type": "string" + } + } + }, + "event.DepartmentBilingual": { + "type": "object", + "properties": { + "en": { + "type": "string", + "example": "Computer Engineering" + }, + "th": { + "type": "string", + "example": "ภาควิชาคอมพิวเตอร์" + } + } + }, + "event.DescriptionBilingual": { + "type": "object", + "properties": { + "en": { + "type": "string", + "example": "This is the first event." + }, + "th": { + "type": "string", + "example": "รายละเอียดอีเวนท์แรก" + } + } + }, + "event.Event": { + "type": "object", + "properties": { + "department": { + "$ref": "#/definitions/bilingual_field.Bilingual" + }, + "description": { + "$ref": "#/definitions/bilingual_field.Bilingual" + }, + "faculty": { + "$ref": "#/definitions/faculty.Faculty" + }, + "id": { + "type": "string" + }, + "location": { + "$ref": "#/definitions/bilingual_field.Bilingual" + }, + "max_capacity": { + "type": "integer" + }, + "name": { + "$ref": "#/definitions/bilingual_field.Bilingual" + }, + "require_registration": { + "type": "boolean" + }, + "schedules": { + "type": "array", + "items": { + "$ref": "#/definitions/schedule.Schedule" + } + } + } + }, + "event.EventAllErrorResponse": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/events" + }, + "title": { + "type": "string", + "example": "internal-server-error" + } + } + }, + "event.EventDTO": { + "type": "object", + "properties": { + "department": { + "$ref": "#/definitions/event.DepartmentBilingual" + }, + "description": { + "$ref": "#/definitions/event.DescriptionBilingual" + }, + "faculty": { + "$ref": "#/definitions/event.Faculty" + }, + "id": { + "type": "string", + "example": "first-event" + }, + "location": { + "$ref": "#/definitions/event.LocationBilingual" + }, + "max_capacity": { + "type": "integer", + "example": 100 + }, + "name": { + "$ref": "#/definitions/event.NameEventBilingual" + }, + "require_registration": { + "type": "boolean", + "example": true + }, + "schedules": { + "type": "array", + "items": { + "$ref": "#/definitions/event.Schedule" + } + } + } + }, + "event.EventErrorResponse": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/events/:eventId" + }, + "title": { + "type": "string", + "example": "internal-server-error" + } + } + }, + "event.EventInvalidResponse": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/events/:eventId" + }, + "title": { + "type": "string", + "example": "invalid-event-id" + } + } + }, + "event.Faculty": { + "type": "object", + "properties": { + "code": { + "type": "string", + "example": "21" + }, + "name": { + "$ref": "#/definitions/event.NameFacultyBilingual" + } + } + }, + "event.LocationBilingual": { + "type": "object", + "properties": { + "en": { + "type": "string", + "example": "SIT Building" + }, + "th": { + "type": "string", + "example": "อาคาร SIT" + } + } + }, + "event.NameEventBilingual": { + "type": "object", + "properties": { + "en": { + "type": "string", + "example": "First Event" + }, + "th": { + "type": "string", + "example": "อีเวนท์แรก" + } + } + }, + "event.NameFacultyBilingual": { + "type": "object", + "properties": { + "en": { + "type": "string", + "example": "Faculty of Engineering" + }, + "th": { + "type": "string", + "example": "คณะวิศวกรรมศาสตร์" + } + } + }, + "event.Schedule": { + "type": "object", + "properties": { + "ends_at": { + "type": "string", + "example": "2021-08-01T00:00:00+07:00" + }, + "starts_at": { + "type": "string", + "example": "2021-08-01T00:00:00+07:00" + } + } + }, + "faculty.Faculty": { + "type": "object", + "properties": { + "code": { + "type": "string" + }, + "name": { + "$ref": "#/definitions/bilingual_field.Bilingual" + } + } + }, + "featureflag.errorResponse": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/featureflag/live" + }, + "title": { + "type": "string", + "example": "internal-server-error" + } + } + }, + "featureflag.invalidResponse": { + "type": "object", + "properties": { + "instance": { + "type": "string", + "example": "/featureflag/live" + }, + "title": { + "type": "string", + "example": "invalid-feature-flag-key" + } + } + }, + "featureflag.response": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "example": true + }, + "extra_info": { + "type": "string", + "example": "https://www.youtube.com/watch?v=6n3pFFPSlW4" + }, + "key": { + "type": "string", + "example": "livestream" + } + } + }, + "schedule.Schedule": { + "type": "object", + "properties": { + "ends_at": { + "type": "string" + }, + "starts_at": { + "type": "string" + } + } + } + }, + "securityDefinitions": { + "Bearer": { + "description": "Type \"Bearer\" followed by a space and JWT token.", + "type": "apiKey", + "name": "Authorization", + "in": "header" + } + } +} \ No newline at end of file diff --git a/docs/swagger.yaml b/docs/swagger.yaml new file mode 100644 index 0000000..8381202 --- /dev/null +++ b/docs/swagger.yaml @@ -0,0 +1,573 @@ +definitions: + auth.CallbackErrorResponse: + properties: + instance: + example: /auth/callback + type: string + title: + example: internal-server-error + type: string + type: object + auth.CallbackInvalidResponse: + properties: + instance: + example: /auth/callback + type: string + title: + example: bad-request + type: string + type: object + auth.CallbackResponse: + properties: + token: + example: gbxnZjiHVzb_4mDQTQNiJdrZFOCactWXkZvZOxS2_qZsy7vAQY7uA2RFIHe2JABoEjhT0Y3KlOJuOEvE2YJMLrJDagwhpAITGex + type: string + type: object + auth.GetProfileErrorResponse: + properties: + instance: + example: /auth/me + type: string + title: + example: internal-server-error + type: string + type: object + auth.GetProfileUnauthorized: + properties: + instance: + example: /auth/me + type: string + title: + example: unauthorized + type: string + type: object + auth.GetProfileUserNotFound: + properties: + instance: + example: /auth/me + type: string + title: + example: user-not-found + type: string + type: object + auth.MockDesiredRound: + properties: + code: + example: "1" + type: string + order: + example: 1 + type: integer + type: object + auth.MockGetProfileResponse: + properties: + user: + $ref: '#/definitions/auth.MockUser' + type: object + auth.MockInterestedFaculty: + properties: + code: + example: "1" + type: string + order: + example: 1 + type: integer + type: object + auth.MockRegisterResponse: + properties: + user: + $ref: '#/definitions/auth.MockUser' + type: object + auth.MockUser: + properties: + address: + example: Bangkok + type: string + allergy: + example: None + type: string + birth_date: + example: "1990-01-01" + type: string + desired_rounds: + items: + $ref: '#/definitions/auth.MockDesiredRound' + type: array + first_name: + example: John + type: string + from_abroad: + example: "no" + type: string + gender: + example: male + type: string + grade: + example: undergraduate + type: string + interested_faculties: + items: + $ref: '#/definitions/auth.MockInterestedFaculty' + type: array + join_cu_reason: + example: Interested in the programs offered + type: string + last_name: + example: Doe + type: string + medical_condition: + example: None + type: string + news_source: + example: Facebook + type: string + school: + example: CU + type: string + status: + example: student + type: string + type: object + auth.RegisterErrorResponse: + properties: + instance: + example: /auth/register + type: string + title: + example: internal-server-error + type: string + type: object + auth.RegisterInvalidResponse: + properties: + instance: + example: /auth/register + type: string + title: + example: bad-request + type: string + type: object + auth.RegisterInvalidToken: + properties: + instance: + example: /auth/register + type: string + title: + example: invalid-token + type: string + type: object + auth.RegisterUnauthorized: + properties: + instance: + example: /auth/register + type: string + title: + example: unauthorized + type: string + type: object + bilingual_field.Bilingual: + properties: + en: + type: string + th: + type: string + type: object + event.DepartmentBilingual: + properties: + en: + example: Computer Engineering + type: string + th: + example: ภาควิชาคอมพิวเตอร์ + type: string + type: object + event.DescriptionBilingual: + properties: + en: + example: This is the first event. + type: string + th: + example: รายละเอียดอีเวนท์แรก + type: string + type: object + event.Event: + properties: + department: + $ref: '#/definitions/bilingual_field.Bilingual' + description: + $ref: '#/definitions/bilingual_field.Bilingual' + faculty: + $ref: '#/definitions/faculty.Faculty' + id: + type: string + location: + $ref: '#/definitions/bilingual_field.Bilingual' + max_capacity: + type: integer + name: + $ref: '#/definitions/bilingual_field.Bilingual' + require_registration: + type: boolean + schedules: + items: + $ref: '#/definitions/schedule.Schedule' + type: array + type: object + event.EventAllErrorResponse: + properties: + instance: + example: /events + type: string + title: + example: internal-server-error + type: string + type: object + event.EventDTO: + properties: + department: + $ref: '#/definitions/event.DepartmentBilingual' + description: + $ref: '#/definitions/event.DescriptionBilingual' + faculty: + $ref: '#/definitions/event.Faculty' + id: + example: first-event + type: string + location: + $ref: '#/definitions/event.LocationBilingual' + max_capacity: + example: 100 + type: integer + name: + $ref: '#/definitions/event.NameEventBilingual' + require_registration: + example: true + type: boolean + schedules: + items: + $ref: '#/definitions/event.Schedule' + type: array + type: object + event.EventErrorResponse: + properties: + instance: + example: /events/:eventId + type: string + title: + example: internal-server-error + type: string + type: object + event.EventInvalidResponse: + properties: + instance: + example: /events/:eventId + type: string + title: + example: invalid-event-id + type: string + type: object + event.Faculty: + properties: + code: + example: "21" + type: string + name: + $ref: '#/definitions/event.NameFacultyBilingual' + type: object + event.LocationBilingual: + properties: + en: + example: SIT Building + type: string + th: + example: อาคาร SIT + type: string + type: object + event.NameEventBilingual: + properties: + en: + example: First Event + type: string + th: + example: อีเวนท์แรก + type: string + type: object + event.NameFacultyBilingual: + properties: + en: + example: Faculty of Engineering + type: string + th: + example: คณะวิศวกรรมศาสตร์ + type: string + type: object + event.Schedule: + properties: + ends_at: + example: "2021-08-01T00:00:00+07:00" + type: string + starts_at: + example: "2021-08-01T00:00:00+07:00" + type: string + type: object + faculty.Faculty: + properties: + code: + type: string + name: + $ref: '#/definitions/bilingual_field.Bilingual' + type: object + featureflag.errorResponse: + properties: + instance: + example: /featureflag/live + type: string + title: + example: internal-server-error + type: string + type: object + featureflag.invalidResponse: + properties: + instance: + example: /featureflag/live + type: string + title: + example: invalid-feature-flag-key + type: string + type: object + featureflag.response: + properties: + enabled: + example: true + type: boolean + extra_info: + example: https://www.youtube.com/watch?v=6n3pFFPSlW4 + type: string + key: + example: livestream + type: string + type: object + schedule.Schedule: + properties: + ends_at: + type: string + starts_at: + type: string + type: object +info: + contact: {} + description: Documentation outlines the specifications and endpoints for the OPH-66 + Backend API. + title: OPH-66 Backend API + version: "1.0" +paths: + /_hc: + get: + description: Health Check for the service + operationId: HealthCheck + produces: + - text/plain + responses: + "200": + description: OK + schema: + type: string + security: + - Bearer: [] + summary: Health Check + tags: + - healthcheck + /auth/callback: + get: + description: After successfully logging in with a @chula account, you'll receive + a token. If you attempt to log in using a different domain, Google will not + allow the login + operationId: GoogleCallback + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/auth.CallbackResponse' + "404": + description: Not Found + schema: + $ref: '#/definitions/auth.CallbackInvalidResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/auth.CallbackErrorResponse' + security: + - Bearer: [] + summary: receive a token after successfully login with Google + tags: + - auth + /auth/login: + get: + description: Redirect to Google login page + operationId: GoogleLogin + produces: + - application/json + responses: {} + security: + - Bearer: [] + summary: Redirect to Google login page + tags: + - auth + /auth/me: + get: + description: Get Profile of current user + operationId: GetProfile + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/auth.MockGetProfileResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/auth.GetProfileUnauthorized' + "404": + description: Not Found + schema: + $ref: '#/definitions/auth.GetProfileUserNotFound' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/auth.GetProfileErrorResponse' + security: + - Bearer: [] + summary: Get Profile of current user + tags: + - auth + /auth/register: + post: + description: Register new account with @chula email + operationId: Register + parameters: + - description: User + in: body + name: user + required: true + schema: + $ref: '#/definitions/auth.MockUser' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/auth.MockRegisterResponse' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/auth.RegisterUnauthorized' + "404": + description: Not Found + schema: + $ref: '#/definitions/auth.RegisterInvalidResponse' + "498": + description: "" + schema: + $ref: '#/definitions/auth.RegisterInvalidToken' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/auth.RegisterErrorResponse' + security: + - Bearer: [] + summary: Register + tags: + - auth + /events: + get: + description: Get all events as array of events + operationId: GetAllEvents + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/event.Event' + type: array + "404": + description: Not Found + schema: + $ref: '#/definitions/event.EventInvalidResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/event.EventAllErrorResponse' + security: + - Bearer: [] + summary: Get all events + tags: + - event + /events/{eventId}: + get: + description: Get event by id + operationId: GetEventById + parameters: + - description: event id + in: path + name: eventId + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/event.EventDTO' + "404": + description: Not Found + schema: + $ref: '#/definitions/event.EventInvalidResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/event.EventErrorResponse' + security: + - Bearer: [] + summary: get event by id + tags: + - event + /live: + get: + description: Get livestream flag + operationId: GetLivestreamInfo + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/featureflag.response' + "404": + description: Not Found + schema: + $ref: '#/definitions/featureflag.invalidResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/featureflag.errorResponse' + security: + - Bearer: [] + summary: Get livestream flag + tags: + - FeatureFlag +schemes: +- http +- https +securityDefinitions: + Bearer: + description: Type "Bearer" followed by a space and JWT token. + in: header + name: Authorization + type: apiKey +swagger: "2.0" diff --git a/go.mod b/go.mod index 8a9954e..5da443b 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,9 @@ require ( github.com/google/wire v0.5.0 github.com/redis/go-redis/v9 v9.3.0 github.com/spf13/viper v1.18.1 + github.com/swaggo/files v1.0.1 + github.com/swaggo/gin-swagger v1.6.0 + github.com/swaggo/swag v1.16.2 go.uber.org/zap v1.26.0 golang.org/x/oauth2 v0.15.0 google.golang.org/api v0.153.0 @@ -23,6 +26,7 @@ require ( ) require ( + github.com/KyleBanks/depth v1.2.1 // indirect github.com/bytedance/sonic v1.10.2 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect @@ -31,6 +35,10 @@ require ( github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-openapi/jsonpointer v0.20.2 // indirect + github.com/go-openapi/jsonreference v0.20.4 // indirect + github.com/go-openapi/spec v0.20.13 // indirect + github.com/go-openapi/swag v0.22.6 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.16.0 // indirect @@ -44,10 +52,12 @@ require ( github.com/jackc/pgx/v5 v5.4.3 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect + github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.2.6 // indirect github.com/leodido/go-urn v1.2.4 // indirect github.com/magiconair/properties v1.8.7 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -65,14 +75,19 @@ require ( go.opencensus.io v0.24.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/arch v0.6.0 // indirect - golang.org/x/crypto v0.16.0 // indirect + golang.org/x/crypto v0.17.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect golang.org/x/net v0.19.0 // indirect golang.org/x/sys v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect + golang.org/x/tools v0.13.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect google.golang.org/grpc v1.59.0 // indirect google.golang.org/protobuf v1.31.0 // indirect + golang.org/x/tools v0.16.1 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect + google.golang.org/grpc v1.59.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index fa01150..654a74f 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzc cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= +github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= @@ -42,10 +44,20 @@ github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uq github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gin-contrib/cors v1.5.0 h1:DgGKV7DDoOn36DFkNtbHrjoRiT5ExCe+PC9/xp7aKvk= github.com/gin-contrib/cors v1.5.0/go.mod h1:TvU7MAZ3EwrPLI2ztzTt3tqgvBCq+wn8WpZmfADjupI= +github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= +github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk= 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.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= +github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= +github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU= +github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4= +github.com/go-openapi/spec v0.20.13 h1:XJDIN+dLH6vqXgafnl5SUIMnzaChQ6QTo0/UPMbkIaE= +github.com/go-openapi/spec v0.20.13/go.mod h1:8EOhTpBoFiask8rrgwbLC3zmJfz4zsCUueRuPM6GNkw= +github.com/go-openapi/swag v0.22.6 h1:dnqg1XfHXL9aBxSbktBqFR5CxVyVI+7fYWhAf1JOeTw= +github.com/go-openapi/swag v0.22.6/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmridBTsDy8A0= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -108,6 +120,8 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= 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/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= @@ -122,6 +136,8 @@ github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -139,8 +155,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/redis/go-redis/v9 v9.3.0 h1:RiVDjmig62jIWp7Kk4XVLs0hzV6pI3PyTnnL0cnn0u0= github.com/redis/go-redis/v9 v9.3.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= @@ -168,6 +184,12 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE= +github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg= +github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+zy8M= +github.com/swaggo/gin-swagger v1.6.0/go.mod h1:BG00cCEy294xtVpyIAHG6+e2Qzj/xKlRdOqDkvq0uzo= +github.com/swaggo/swag v1.16.2 h1:28Pp+8DkQoV+HLzLx8RGJZXNGKbFqnuvSbAAtoxiY04= +github.com/swaggo/swag v1.16.2/go.mod h1:6YzXnDcpr0767iOejs318CwYkCQqyGer6BizOg03f+E= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= @@ -187,8 +209,8 @@ golang.org/x/arch v0.6.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= @@ -196,6 +218,8 @@ golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTk golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -205,6 +229,7 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -230,10 +255,12 @@ golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= @@ -246,6 +273,8 @@ golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.153.0 h1:N1AwGhielyKFaUqH07/ZSIQR3uNPcV7NVw0vj+j4iR4= @@ -277,8 +306,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= -google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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= diff --git a/internal/auth/auth.dto.go b/internal/auth/auth.dto.go index 95a0903..f7502e9 100644 --- a/internal/auth/auth.dto.go +++ b/internal/auth/auth.dto.go @@ -41,3 +41,106 @@ type RegisterResponse struct { type GetProfileResponse struct { User *User `json:"user"` } + +type RegisterDTO struct { + Gender string `json:"gender"` + FirstName string `json:"first_name"` + LastName string `json:"last_name"` + School string `json:"school"` + BirthDate string `json:"birth_date"` + Address string `json:"address"` + FromAbroad string `json:"from_abroad"` + Allergy string `json:"allergy"` + MedicalCondition string `json:"medical_condition"` + JoinCUReason string `json:"join_cu_reason"` + NewsSource string `json:"news_source"` + Status string `json:"status"` + Grade string `json:"grade"` + DesiredRounds []DesiredRound `json:"desired_rounds"` + InterestedFaculties []InterestedFaculty `json:"interested_faculties"` +} + +type MockUser struct { + Gender string `json:"gender" example:"male"` + FirstName string `json:"first_name" example:"John"` + LastName string `json:"last_name" example:"Doe"` + School string `json:"school" example:"CU"` + BirthDate string `json:"birth_date" example:"1990-01-01"` + Address string `json:"address" example:"Bangkok"` + FromAbroad string `json:"from_abroad" example:"no"` + Allergy string `json:"allergy" example:"None"` + MedicalCondition string `json:"medical_condition" example:"None"` + JoinCUReason string `json:"join_cu_reason" example:"Interested in the programs offered"` + NewsSource string `json:"news_source" example:"Facebook"` + Status string `json:"status" example:"student"` + Grade string `json:"grade" example:"undergraduate"` + DesiredRounds []MockDesiredRound `json:"desired_rounds"` + InterestedFaculties []MockInterestedFaculty `json:"interested_faculties"` +} + +type MockDesiredRound struct { + Order uint `json:"order" example:"1"` + Code string `json:"code" example:"1"` +} + +type MockInterestedFaculty struct { + Order uint `json:"order" example:"1"` + Code string `json:"code" example:"1"` +} + +type CallbackResponse struct { + Token string `json:"token" example:"gbxnZjiHVzb_4mDQTQNiJdrZFOCactWXkZvZOxS2_qZsy7vAQY7uA2RFIHe2JABoEjhT0Y3KlOJuOEvE2YJMLrJDagwhpAITGex"` +} + +type CallbackErrorResponse struct { + Instance string `json:"instance" example:"/auth/callback"` + Title string `json:"title" example:"internal-server-error"` +} + +type CallbackInvalidResponse struct { + Instance string `json:"instance" example:"/auth/callback"` + Title string `json:"title" example:"bad-request"` +} + +type MockRegisterResponse struct { + MockUser MockUser `json:"user"` +} + +type RegisterErrorResponse struct { + Instance string `json:"instance" example:"/auth/register"` + Title string `json:"title" example:"internal-server-error"` +} + +type RegisterInvalidResponse struct { + Instance string `json:"instance" example:"/auth/register"` + Title string `json:"title" example:"bad-request"` +} + +type RegisterUnauthorized struct { + Instance string `json:"instance" example:"/auth/register"` + Title string `json:"title" example:"unauthorized"` +} + +type RegisterInvalidToken struct { + Instance string `json:"instance" example:"/auth/register"` + Title string `json:"title" example:"invalid-token"` +} + +type MockGetProfileResponse struct { + MockUser MockUser `json:"user"` +} + +type GetProfileErrorResponse struct { + Instance string `json:"instance" example:"/auth/me"` + Title string `json:"title" example:"internal-server-error"` +} + +type GetProfileUnauthorized struct { + Instance string `json:"instance" example:"/auth/me"` + Title string `json:"title" example:"unauthorized"` +} + +type GetProfileUserNotFound struct { + Instance string `json:"instance" example:"/auth/me"` + Title string `json:"title" example:"user-not-found"` +} diff --git a/internal/auth/auth.handler.go b/internal/auth/auth.handler.go index 65848b9..99e7295 100644 --- a/internal/auth/auth.handler.go +++ b/internal/auth/auth.handler.go @@ -29,11 +29,30 @@ func NewHandler(svc Service, logger *zap.Logger) Handler { } } +// GoogleLogin godoc +// @summary Redirect to Google login page +// @description Redirect to Google login page +// @id GoogleLogin +// @produce json +// @tags auth +// @Security Bearer +// @router /auth/login [get] func (h *handlerImpl) GoogleLogin(c *gin.Context) { url := h.svc.GoogleLogin() c.Redirect(http.StatusTemporaryRedirect, url) } +// GoogleCallback godoc +// @summary receive a token after successfully login with Google +// @description After successfully logging in with a @chula account, you'll receive a token. If you attempt to log in using a different domain, Google will not allow the login +// @id GoogleCallback +// @produce json +// @tags auth +// @Security Bearer +// @router /auth/callback [get] +// @success 200 {object} auth.CallbackResponse +// @Failure 500 {object} auth.CallbackErrorResponse +// @Failure 404 {object} auth.CallbackInvalidResponse func (h *handlerImpl) GoogleCallback(c *gin.Context) { code := c.Query("code") token, apperr := h.svc.GoogleCallback(c, code) @@ -47,6 +66,20 @@ func (h *handlerImpl) GoogleCallback(c *gin.Context) { c.JSON(http.StatusOK, response) } +// Register godoc +// @summary Register +// @description Register new account with @chula email +// @id Register +// @produce json +// @tags auth +// @Security Bearer +// @router /auth/register [post] +// @param user body auth.MockUser true "User" +// @success 200 {object} auth.MockRegisterResponse +// @Failure 500 {object} auth.RegisterErrorResponse +// @Failure 404 {object} auth.RegisterInvalidResponse +// @Failure 401 {object} auth.RegisterUnauthorized +// @Failure 498 {object} auth.RegisterInvalidToken func (h *handlerImpl) Register(c *gin.Context) { var data RegisterRequestDTO var user User @@ -78,6 +111,18 @@ func (h *handlerImpl) Register(c *gin.Context) { c.JSON(http.StatusOK, response) } +// GetProfile godoc +// @summary Get Profile of current user +// @description Get Profile of current user +// @id GetProfile +// @produce json +// @tags auth +// @Security Bearer +// @router /auth/me [get] +// @success 200 {object} auth.MockGetProfileResponse +// @Failure 500 {object} auth.GetProfileErrorResponse +// @Failure 401 {object} auth.GetProfileUnauthorized +// @Failure 404 {object} auth.GetProfileUserNotFound func (h *handlerImpl) GetProfile(c *gin.Context) { var user User authHeader := c.GetHeader("Authorization") diff --git a/internal/auth/auth.model.go b/internal/auth/auth.model.go index 1df427c..32d00ae 100644 --- a/internal/auth/auth.model.go +++ b/internal/auth/auth.model.go @@ -10,9 +10,6 @@ type User struct { FirstName string `json:"first_name"` LastName string `json:"last_name"` Email string `gorm:"index" json:"email"` - School string `json:"school"` - BirthDate string `json:"birth_date"` - Address string `json:"address"` FromAbroad string `json:"from_abroad"` Allergy string `json:"allergy"` MedicalCondition string `json:"medical_condition"` diff --git a/internal/auth/auth.repository.go b/internal/auth/auth.repository.go index 276ec02..7660a45 100644 --- a/internal/auth/auth.repository.go +++ b/internal/auth/auth.repository.go @@ -25,4 +25,4 @@ func (r *repositoryImpl) CreateUser(user *User) error { func (r *repositoryImpl) GetUserByEmail(user *User, email string) error { return r.db.Preload("DesiredRounds").Preload("DesiredRounds.Round").Preload("InterestedFaculties").Preload("InterestedFaculties.Faculty").Preload("InterestedFaculties.Department").Preload("InterestedFaculties.Section").Where("email = ?", email).First(&user).Error -} +} \ No newline at end of file diff --git a/internal/auth/auth.util.go b/internal/auth/auth.util.go index 84d4b3b..5330ab8 100644 --- a/internal/auth/auth.util.go +++ b/internal/auth/auth.util.go @@ -40,4 +40,4 @@ func ConvertFacultyInfoToInterestedFaculty(dto *FacultyInfo, user *User, interes interestedFaculty.FacultyCode = dto.FacultyCode interestedFaculty.DepartmentCode = dto.DepartmentCode interestedFaculty.SectionCode = dto.SectionCode -} +} \ No newline at end of file diff --git a/internal/event/event.dto.go b/internal/event/event.dto.go new file mode 100644 index 0000000..82ad372 --- /dev/null +++ b/internal/event/event.dto.go @@ -0,0 +1,68 @@ +package event + +import "time" + +type EventAll []Event + +type EventInvalidResponse struct { + Instance string `json:"instance" example:"/events/:eventId"` + Title string `json:"title" example:"invalid-event-id"` +} + +type EventErrorResponse struct { + Instance string `json:"instance" example:"/events/:eventId"` + Title string `json:"title" example:"internal-server-error"` +} + +type EventAllErrorResponse struct { + Instance string `json:"instance" example:"/events"` + Title string `json:"title" example:"internal-server-error"` +} + +type EventDTO struct { + Id string `json:"id" example:"first-event"` + Name NameEventBilingual `json:"name"` + FacultyCode int `json:"-"` + Faculty Faculty `json:"faculty"` + Department DepartmentBilingual `json:"department"` + RequireRegistration bool `json:"require_registration" example:"true"` + MaxCapacity int `json:"max_capacity" example:"100"` + Schedules []Schedule `json:"schedules"` + Location LocationBilingual `json:"location"` + Description DescriptionBilingual `json:"description,omitempty"` +} + +type NameEventBilingual struct { + En string `json:"en" example:"First Event"` + Th string `json:"th" example:"อีเวนท์แรก"` +} + +type DepartmentBilingual struct { + En string `json:"en" example:"Computer Engineering"` + Th string `json:"th" example:"ภาควิชาคอมพิวเตอร์"` +} + +type Faculty struct { + Code string `json:"code" example:"21"` + Name NameFacultyBilingual `json:"name"` +} + +type NameFacultyBilingual struct { + En string `json:"en" example:"Faculty of Engineering"` + Th string `json:"th" example:"คณะวิศวกรรมศาสตร์"` +} + +type LocationBilingual struct { + En string `json:"en" example:"SIT Building"` + Th string `json:"th" example:"อาคาร SIT"` +} + +type DescriptionBilingual struct { + En string `json:"en" example:"This is the first event."` + Th string `json:"th" example:"รายละเอียดอีเวนท์แรก"` +} + +type Schedule struct { + StartsAt time.Time `json:"ends_at" example:"2021-08-01T00:00:00+07:00"` + EndsAt time.Time `json:"starts_at" example:"2021-08-01T00:00:00+07:00"` +} diff --git a/internal/event/event.handler.go b/internal/event/event.handler.go index 408e7c9..0e1a1ff 100644 --- a/internal/event/event.handler.go +++ b/internal/event/event.handler.go @@ -31,6 +31,17 @@ type handlerImpl struct { logger *zap.Logger } +// GetAllEvents godoc +// @summary Get all events +// @description Get all events as array of events +// @id GetAllEvents +// @produce json +// @tags event +// @Security Bearer +// @router /events [get] +// @success 200 {object} event.EventAll +// @Failure 500 {object} event.EventAllErrorResponse +// @Failure 404 {object} event.EventInvalidResponse func (h *handlerImpl) GetAllEvents(c *gin.Context) { hit, result, apperr := h.cache.Get(c.Request.Context(), "get_all_events") if apperr != nil { @@ -65,6 +76,18 @@ func (h *handlerImpl) GetAllEvents(c *gin.Context) { c.String(http.StatusOK, string(eventsJson)) } +// GetEvent godoc +// @summary get event by id +// @description Get event by id +// @id GetEventById +// @produce json +// @tags event +// @Security Bearer +// @param eventId path string true "event id" +// @router /events/{eventId} [get] +// @success 200 {object} event.EventDTO +// @Failure 500 {object} event.EventErrorResponse +// @Failure 404 {object} event.EventInvalidResponse func (h *handlerImpl) GetEventById(c *gin.Context) { eventId := c.Param("eventId") diff --git a/internal/feature_flag/feature_flag.dto.go b/internal/feature_flag/feature_flag.dto.go new file mode 100644 index 0000000..e5af27a --- /dev/null +++ b/internal/feature_flag/feature_flag.dto.go @@ -0,0 +1,17 @@ +package featureflag + +type response struct { + Key string `json:"key" example:"livestream"` + Enabled bool `json:"enabled" example:"true"` + ExtraInfo string `json:"extra_info" example:"https://www.youtube.com/watch?v=6n3pFFPSlW4"` +} + +type errorResponse struct { + Instance string `json:"instance" example:"/featureflag/live"` + Title string `json:"title" example:"internal-server-error"` +} + +type invalidResponse struct { + Instance string `json:"instance" example:"/featureflag/live"` + Title string `json:"title" example:"invalid-feature-flag-key"` +} \ No newline at end of file diff --git a/internal/feature_flag/feature_flag.handler.go b/internal/feature_flag/feature_flag.handler.go index 648b308..d19c634 100644 --- a/internal/feature_flag/feature_flag.handler.go +++ b/internal/feature_flag/feature_flag.handler.go @@ -26,6 +26,17 @@ type handlerImpl struct { cache Cache } +// GetLivestreamInfo godoc +// @summary Get livestream flag +// @description Get livestream flag +// @id GetLivestreamInfo +// @produce json +// @tags FeatureFlag +// @Security Bearer +// @router /live [get] +// @success 200 {object} featureflag.response +// @Failure 500 {object} featureflag.errorResponse +// @Failure 404 {object} featureflag.invalidResponse func (h *handlerImpl) GetLivestreamInfo(c *gin.Context) { cacheKey := "livestream" diff --git a/internal/health_check/health_check.handler.go b/internal/health_check/health_check.handler.go index a0f8386..6aa26a3 100644 --- a/internal/health_check/health_check.handler.go +++ b/internal/health_check/health_check.handler.go @@ -17,6 +17,15 @@ func NewHandler() Handler { type handlerImpl struct { } +// HealthCheck godoc +// @summary Health Check +// @description Health Check for the service +// @id HealthCheck +// @produce plain +// @tags healthcheck +// @Security Bearer +// @router /_hc [get] +// @Success 200 {string} string "OK" func (h *handlerImpl) HealthCheck(c *gin.Context) { c.String(http.StatusOK, "OK") } From 9d6032b6316dfba76718d02a8bac4144c0496e16 Mon Sep 17 00:00:00 2001 From: ImSoZRious <30285202+ImSoZRious@users.noreply.github.com> Date: Thu, 28 Dec 2023 01:14:18 +0700 Subject: [PATCH 2/4] fix: lint --- cfgldr/cfgldr.go | 35 ----------- go.mod | 29 +++++---- go.sum | 41 +++++++++++-- internal/auth/auth.dto.go | 72 +++++++++++------------ internal/auth/auth.model.go | 3 + internal/auth/auth.repository.go | 2 +- internal/auth/auth.util.go | 2 +- internal/event/event.dto.go | 44 +++++++------- internal/feature_flag/feature_flag.dto.go | 16 ++--- 9 files changed, 125 insertions(+), 119 deletions(-) diff --git a/cfgldr/cfgldr.go b/cfgldr/cfgldr.go index 156ec80..42f62dd 100644 --- a/cfgldr/cfgldr.go +++ b/cfgldr/cfgldr.go @@ -10,8 +10,6 @@ type Config struct { RedisConfig RedisConfig OAuth2Config OAuth2Config CorsConfig CorsConfig - OAuth2Config OAuth2Config - CorsConfig CorsConfig } type DatabaseConfig struct { @@ -40,19 +38,6 @@ type CorsConfig struct { AllowOrigins string `mapstructure:"ORIGINS"` } -type OAuth2Config struct { - RedirectURL string `mapstructure:"REDIRECT_URL"` - ClientID string `mapstructure:"CLIENT_ID"` - ClientSecret string `mapstructure:"CLIENT_SECRET"` - Scopes []string `mapstructure:"SCOPES"` - AllowOrigins string `mapstructure:"ORIGINS"` - Endpoint string `mapstructure:"ENDPOINT"` -} - -type CorsConfig struct { - AllowOrigins string `mapstructure:"ORIGINS"` -} - func LoadConfig() (*Config, error) { dbCfgLdr := viper.New() dbCfgLdr.SetEnvPrefix("DB") @@ -99,32 +84,12 @@ func LoadConfig() (*Config, error) { return nil, err } - oauth2CfgLdr := viper.New() - oauth2CfgLdr.SetEnvPrefix("OAUTH2") - oauth2CfgLdr.AutomaticEnv() - oauth2CfgLdr.AllowEmptyEnv(false) - oauth2Config := OAuth2Config{} - if err := oauth2CfgLdr.Unmarshal(&oauth2Config); err != nil { - return nil, err - } - - corsConfigLdr := viper.New() - corsConfigLdr.SetEnvPrefix("CORS") - corsConfigLdr.AutomaticEnv() - dbCfgLdr.AllowEmptyEnv(false) - corsConfig := CorsConfig{} - if err := corsConfigLdr.Unmarshal(&corsConfig); err != nil { - return nil, err - } - return &Config{ DatabaseConfig: dbConfig, AppConfig: appConfig, RedisConfig: redisConfig, OAuth2Config: oauth2Config, CorsConfig: corsConfig, - OAuth2Config: oauth2Config, - CorsConfig: corsConfig, }, nil } diff --git a/go.mod b/go.mod index 5da443b..805a24f 100644 --- a/go.mod +++ b/go.mod @@ -6,14 +6,14 @@ require ( github.com/gin-contrib/cors v1.5.0 github.com/gin-gonic/gin v1.9.1 github.com/google/wire v0.5.0 - github.com/redis/go-redis/v9 v9.3.0 - github.com/spf13/viper v1.18.1 + github.com/redis/go-redis/v9 v9.3.1 + github.com/spf13/viper v1.18.2 github.com/swaggo/files v1.0.1 github.com/swaggo/gin-swagger v1.6.0 github.com/swaggo/swag v1.16.2 go.uber.org/zap v1.26.0 golang.org/x/oauth2 v0.15.0 - google.golang.org/api v0.153.0 + google.golang.org/api v0.154.0 gorm.io/driver/postgres v1.5.4 gorm.io/gorm v1.25.5 ) @@ -32,9 +32,12 @@ require ( github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/chenzhuoyu/iasm v0.9.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.20.2 // indirect github.com/go-openapi/jsonreference v0.20.4 // indirect github.com/go-openapi/spec v0.20.13 // indirect @@ -48,8 +51,9 @@ require ( github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect - github.com/jackc/pgx/v5 v5.4.3 // indirect + github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect + github.com/jackc/pgx/v5 v5.5.1 // indirect + github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/josharian/intern v1.0.0 // indirect @@ -73,20 +77,21 @@ require ( github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect + go.opentelemetry.io/otel v1.21.0 // indirect + go.opentelemetry.io/otel/metric v1.21.0 // indirect + go.opentelemetry.io/otel/trace v1.21.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/arch v0.6.0 // indirect golang.org/x/crypto v0.17.0 // indirect - golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/exp v0.0.0-20231226003508-02704c960a9b // indirect golang.org/x/net v0.19.0 // indirect + golang.org/x/sync v0.5.0 // indirect golang.org/x/sys v0.15.0 // indirect golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.13.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect - google.golang.org/grpc v1.59.0 // indirect - google.golang.org/protobuf v1.31.0 // indirect golang.org/x/tools v0.16.1 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect - google.golang.org/grpc v1.59.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 // indirect + google.golang.org/grpc v1.60.1 // indirect google.golang.org/protobuf v1.32.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 654a74f..9919ba8 100644 --- a/go.sum +++ b/go.sum @@ -36,6 +36,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF 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/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= 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.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= @@ -50,6 +52,11 @@ 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.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/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-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU= @@ -114,8 +121,14 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA= +github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY= github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= +github.com/jackc/pgx/v5 v5.5.1 h1:5I9etrGkLrN+2XPCsi6XLlV5DITbSL/xBZdmAxFcXPI= +github.com/jackc/pgx/v5 v5.5.1/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= +github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= +github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= @@ -155,6 +168,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/redis/go-redis/v9 v9.3.0 h1:RiVDjmig62jIWp7Kk4XVLs0hzV6pI3PyTnnL0cnn0u0= github.com/redis/go-redis/v9 v9.3.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= +github.com/redis/go-redis/v9 v9.3.1 h1:KqdY8U+3X6z+iACvumCNxnoluToB+9Me+TvyFa21Mds= +github.com/redis/go-redis/v9 v9.3.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= @@ -171,6 +186,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.18.1 h1:rmuU42rScKWlhhJDyXZRKJQHXFX02chSVW1IvkPGiVM= github.com/spf13/viper v1.18.1/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= +github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= +github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -197,6 +214,14 @@ github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= +go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= +go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= +go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= +go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= +go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= +go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -214,12 +239,14 @@ golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/exp v0.0.0-20231226003508-02704c960a9b h1:kLiC65FbiHWFAOu+lxwNPujcsl8VYyTYYEZnsOO1WK4= +golang.org/x/exp v0.0.0-20231226003508-02704c960a9b/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= 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-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -273,12 +300,14 @@ golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= +golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.153.0 h1:N1AwGhielyKFaUqH07/ZSIQR3uNPcV7NVw0vj+j4iR4= google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= +google.golang.org/api v0.154.0 h1:X7QkVKZBskztmpPKWQXgjJRPA2dJYrL6r+sYPRLj050= +google.golang.org/api v0.154.0/go.mod h1:qhSMkM85hgqiokIYsrRyKxrjfBeIhgl4Z2JmeRkYylc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= @@ -288,6 +317,8 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I= google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 h1:/jFB8jK5R3Sq3i/lmeZO0cATSzFfZaJq1J2Euan3XKU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0/go.mod h1:FUoWkonphQm3RhTS+kOEhF8h0iDpm4tdXolVCeZ9KKA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -295,6 +326,8 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= +google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= +google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= 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= diff --git a/internal/auth/auth.dto.go b/internal/auth/auth.dto.go index f7502e9..423ba0c 100644 --- a/internal/auth/auth.dto.go +++ b/internal/auth/auth.dto.go @@ -61,45 +61,45 @@ type RegisterDTO struct { } type MockUser struct { - Gender string `json:"gender" example:"male"` - FirstName string `json:"first_name" example:"John"` - LastName string `json:"last_name" example:"Doe"` - School string `json:"school" example:"CU"` - BirthDate string `json:"birth_date" example:"1990-01-01"` - Address string `json:"address" example:"Bangkok"` - FromAbroad string `json:"from_abroad" example:"no"` - Allergy string `json:"allergy" example:"None"` - MedicalCondition string `json:"medical_condition" example:"None"` - JoinCUReason string `json:"join_cu_reason" example:"Interested in the programs offered"` - NewsSource string `json:"news_source" example:"Facebook"` - Status string `json:"status" example:"student"` - Grade string `json:"grade" example:"undergraduate"` + Gender string `example:"male" json:"gender"` + FirstName string `example:"John" json:"first_name"` + LastName string `example:"Doe" json:"last_name"` + School string `example:"CU" json:"school"` + BirthDate string `example:"1990-01-01" json:"birth_date"` + Address string `example:"Bangkok" json:"address"` + FromAbroad string `example:"no" json:"from_abroad"` + Allergy string `example:"None" json:"allergy"` + MedicalCondition string `example:"None" json:"medical_condition"` + JoinCUReason string `example:"Interested in the programs offered" json:"join_cu_reason"` + NewsSource string `example:"Facebook" json:"news_source"` + Status string `example:"student" json:"status"` + Grade string `example:"undergraduate" json:"grade"` DesiredRounds []MockDesiredRound `json:"desired_rounds"` InterestedFaculties []MockInterestedFaculty `json:"interested_faculties"` } type MockDesiredRound struct { - Order uint `json:"order" example:"1"` - Code string `json:"code" example:"1"` + Order uint `example:"1" json:"order"` + Code string `example:"1" json:"code"` } type MockInterestedFaculty struct { - Order uint `json:"order" example:"1"` - Code string `json:"code" example:"1"` + Order uint `example:"1" json:"order"` + Code string `example:"1" json:"code"` } type CallbackResponse struct { - Token string `json:"token" example:"gbxnZjiHVzb_4mDQTQNiJdrZFOCactWXkZvZOxS2_qZsy7vAQY7uA2RFIHe2JABoEjhT0Y3KlOJuOEvE2YJMLrJDagwhpAITGex"` + Token string `example:"gbxnZjiHVzb_4mDQTQNiJdrZFOCactWXkZvZOxS2_qZsy7vAQY7uA2RFIHe2JABoEjhT0Y3KlOJuOEvE2YJMLrJDagwhpAITGex" json:"token"` } type CallbackErrorResponse struct { - Instance string `json:"instance" example:"/auth/callback"` - Title string `json:"title" example:"internal-server-error"` + Instance string `example:"/auth/callback" json:"instance"` + Title string `example:"internal-server-error" json:"title"` } type CallbackInvalidResponse struct { - Instance string `json:"instance" example:"/auth/callback"` - Title string `json:"title" example:"bad-request"` + Instance string `example:"/auth/callback" json:"instance"` + Title string `example:"bad-request" json:"title"` } type MockRegisterResponse struct { @@ -107,23 +107,23 @@ type MockRegisterResponse struct { } type RegisterErrorResponse struct { - Instance string `json:"instance" example:"/auth/register"` - Title string `json:"title" example:"internal-server-error"` + Instance string `example:"/auth/register" json:"instance"` + Title string `example:"internal-server-error" json:"title"` } type RegisterInvalidResponse struct { - Instance string `json:"instance" example:"/auth/register"` - Title string `json:"title" example:"bad-request"` + Instance string `example:"/auth/register" json:"instance"` + Title string `example:"bad-request" json:"title"` } type RegisterUnauthorized struct { - Instance string `json:"instance" example:"/auth/register"` - Title string `json:"title" example:"unauthorized"` + Instance string `example:"/auth/register" json:"instance"` + Title string `example:"unauthorized" json:"title"` } type RegisterInvalidToken struct { - Instance string `json:"instance" example:"/auth/register"` - Title string `json:"title" example:"invalid-token"` + Instance string `example:"/auth/register" json:"instance"` + Title string `example:"invalid-token" json:"title"` } type MockGetProfileResponse struct { @@ -131,16 +131,16 @@ type MockGetProfileResponse struct { } type GetProfileErrorResponse struct { - Instance string `json:"instance" example:"/auth/me"` - Title string `json:"title" example:"internal-server-error"` + Instance string `example:"/auth/me" json:"instance"` + Title string `example:"internal-server-error" json:"title"` } type GetProfileUnauthorized struct { - Instance string `json:"instance" example:"/auth/me"` - Title string `json:"title" example:"unauthorized"` + Instance string `example:"/auth/me" json:"instance"` + Title string `example:"unauthorized" json:"title"` } type GetProfileUserNotFound struct { - Instance string `json:"instance" example:"/auth/me"` - Title string `json:"title" example:"user-not-found"` + Instance string `example:"/auth/me" json:"instance"` + Title string `example:"user-not-found" json:"title"` } diff --git a/internal/auth/auth.model.go b/internal/auth/auth.model.go index 32d00ae..1df427c 100644 --- a/internal/auth/auth.model.go +++ b/internal/auth/auth.model.go @@ -10,6 +10,9 @@ type User struct { FirstName string `json:"first_name"` LastName string `json:"last_name"` Email string `gorm:"index" json:"email"` + School string `json:"school"` + BirthDate string `json:"birth_date"` + Address string `json:"address"` FromAbroad string `json:"from_abroad"` Allergy string `json:"allergy"` MedicalCondition string `json:"medical_condition"` diff --git a/internal/auth/auth.repository.go b/internal/auth/auth.repository.go index 7660a45..276ec02 100644 --- a/internal/auth/auth.repository.go +++ b/internal/auth/auth.repository.go @@ -25,4 +25,4 @@ func (r *repositoryImpl) CreateUser(user *User) error { func (r *repositoryImpl) GetUserByEmail(user *User, email string) error { return r.db.Preload("DesiredRounds").Preload("DesiredRounds.Round").Preload("InterestedFaculties").Preload("InterestedFaculties.Faculty").Preload("InterestedFaculties.Department").Preload("InterestedFaculties.Section").Where("email = ?", email).First(&user).Error -} \ No newline at end of file +} diff --git a/internal/auth/auth.util.go b/internal/auth/auth.util.go index 5330ab8..84d4b3b 100644 --- a/internal/auth/auth.util.go +++ b/internal/auth/auth.util.go @@ -40,4 +40,4 @@ func ConvertFacultyInfoToInterestedFaculty(dto *FacultyInfo, user *User, interes interestedFaculty.FacultyCode = dto.FacultyCode interestedFaculty.DepartmentCode = dto.DepartmentCode interestedFaculty.SectionCode = dto.SectionCode -} \ No newline at end of file +} diff --git a/internal/event/event.dto.go b/internal/event/event.dto.go index 82ad372..899716a 100644 --- a/internal/event/event.dto.go +++ b/internal/event/event.dto.go @@ -5,64 +5,64 @@ import "time" type EventAll []Event type EventInvalidResponse struct { - Instance string `json:"instance" example:"/events/:eventId"` - Title string `json:"title" example:"invalid-event-id"` + Instance string `example:"/events/:eventId" json:"instance"` + Title string `example:"invalid-event-id" json:"title"` } type EventErrorResponse struct { - Instance string `json:"instance" example:"/events/:eventId"` - Title string `json:"title" example:"internal-server-error"` + Instance string `example:"/events/:eventId" json:"instance"` + Title string `example:"internal-server-error" json:"title"` } type EventAllErrorResponse struct { - Instance string `json:"instance" example:"/events"` - Title string `json:"title" example:"internal-server-error"` + Instance string `example:"/events" json:"instance"` + Title string `example:"internal-server-error" json:"title"` } type EventDTO struct { - Id string `json:"id" example:"first-event"` + Id string `example:"first-event" json:"id"` Name NameEventBilingual `json:"name"` FacultyCode int `json:"-"` Faculty Faculty `json:"faculty"` Department DepartmentBilingual `json:"department"` - RequireRegistration bool `json:"require_registration" example:"true"` - MaxCapacity int `json:"max_capacity" example:"100"` + RequireRegistration bool `example:"true" json:"require_registration"` + MaxCapacity int `example:"100" json:"max_capacity"` Schedules []Schedule `json:"schedules"` Location LocationBilingual `json:"location"` Description DescriptionBilingual `json:"description,omitempty"` } type NameEventBilingual struct { - En string `json:"en" example:"First Event"` - Th string `json:"th" example:"อีเวนท์แรก"` + En string `example:"First Event" json:"en"` + Th string `example:"อีเวนท์แรก" json:"th"` } type DepartmentBilingual struct { - En string `json:"en" example:"Computer Engineering"` - Th string `json:"th" example:"ภาควิชาคอมพิวเตอร์"` + En string `example:"Computer Engineering" json:"en"` + Th string `example:"ภาควิชาคอมพิวเตอร์" json:"th"` } type Faculty struct { - Code string `json:"code" example:"21"` + Code string `example:"21" json:"code"` Name NameFacultyBilingual `json:"name"` } type NameFacultyBilingual struct { - En string `json:"en" example:"Faculty of Engineering"` - Th string `json:"th" example:"คณะวิศวกรรมศาสตร์"` + En string `example:"Faculty of Engineering" json:"en"` + Th string `example:"คณะวิศวกรรมศาสตร์" json:"th"` } type LocationBilingual struct { - En string `json:"en" example:"SIT Building"` - Th string `json:"th" example:"อาคาร SIT"` + En string `example:"SIT Building" json:"en"` + Th string `example:"อาคาร SIT" json:"th"` } type DescriptionBilingual struct { - En string `json:"en" example:"This is the first event."` - Th string `json:"th" example:"รายละเอียดอีเวนท์แรก"` + En string `example:"This is the first event." json:"en"` + Th string `example:"รายละเอียดอีเวนท์แรก" json:"th"` } type Schedule struct { - StartsAt time.Time `json:"ends_at" example:"2021-08-01T00:00:00+07:00"` - EndsAt time.Time `json:"starts_at" example:"2021-08-01T00:00:00+07:00"` + StartsAt time.Time `example:"2021-08-01T00:00:00+07:00" json:"ends_at"` + EndsAt time.Time `example:"2021-08-01T00:00:00+07:00" json:"starts_at"` } diff --git a/internal/feature_flag/feature_flag.dto.go b/internal/feature_flag/feature_flag.dto.go index e5af27a..11a1977 100644 --- a/internal/feature_flag/feature_flag.dto.go +++ b/internal/feature_flag/feature_flag.dto.go @@ -1,17 +1,17 @@ package featureflag type response struct { - Key string `json:"key" example:"livestream"` - Enabled bool `json:"enabled" example:"true"` - ExtraInfo string `json:"extra_info" example:"https://www.youtube.com/watch?v=6n3pFFPSlW4"` + Key string `example:"livestream" json:"key"` + Enabled bool `example:"true" json:"enabled"` + ExtraInfo string `example:"https://www.youtube.com/watch?v=6n3pFFPSlW4" json:"extra_info"` } type errorResponse struct { - Instance string `json:"instance" example:"/featureflag/live"` - Title string `json:"title" example:"internal-server-error"` + Instance string `example:"/featureflag/live" json:"instance"` + Title string `example:"internal-server-error" json:"title"` } type invalidResponse struct { - Instance string `json:"instance" example:"/featureflag/live"` - Title string `json:"title" example:"invalid-feature-flag-key"` -} \ No newline at end of file + Instance string `example:"/featureflag/live" json:"instance"` + Title string `example:"invalid-feature-flag-key" json:"title"` +} From d6a231dcb395b579a74c906e163e0f822c0a2730 Mon Sep 17 00:00:00 2001 From: ImSoZRious <30285202+ImSoZRious@users.noreply.github.com> Date: Thu, 28 Dec 2023 01:17:23 +0700 Subject: [PATCH 3/4] chore: remove unused struct --- internal/auth/auth.dto.go | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/internal/auth/auth.dto.go b/internal/auth/auth.dto.go index 423ba0c..868c6e8 100644 --- a/internal/auth/auth.dto.go +++ b/internal/auth/auth.dto.go @@ -42,24 +42,6 @@ type GetProfileResponse struct { User *User `json:"user"` } -type RegisterDTO struct { - Gender string `json:"gender"` - FirstName string `json:"first_name"` - LastName string `json:"last_name"` - School string `json:"school"` - BirthDate string `json:"birth_date"` - Address string `json:"address"` - FromAbroad string `json:"from_abroad"` - Allergy string `json:"allergy"` - MedicalCondition string `json:"medical_condition"` - JoinCUReason string `json:"join_cu_reason"` - NewsSource string `json:"news_source"` - Status string `json:"status"` - Grade string `json:"grade"` - DesiredRounds []DesiredRound `json:"desired_rounds"` - InterestedFaculties []InterestedFaculty `json:"interested_faculties"` -} - type MockUser struct { Gender string `example:"male" json:"gender"` FirstName string `example:"John" json:"first_name"` From 40a35d9c349f339bcc0226c5db40e1ffa470b95f Mon Sep 17 00:00:00 2001 From: ImSoZRious <30285202+ImSoZRious@users.noreply.github.com> Date: Thu, 28 Dec 2023 01:39:07 +0700 Subject: [PATCH 4/4] feat: add host config --- .env.example | 1 + cfgldr/cfgldr.go | 1 + cmd/main.go | 4 +++- docs/docs.go | 3 ++- go.mod | 2 +- go.sum | 18 ++---------------- internal/auth/auth.handler.go | 2 +- 7 files changed, 11 insertions(+), 20 deletions(-) diff --git a/.env.example b/.env.example index 53971c0..060bc43 100644 --- a/.env.example +++ b/.env.example @@ -6,6 +6,7 @@ REDIS_PASSWORD=123456 APP_PORT=3000 APP_ENV=development +APP_HOST=127.0.0.1:3000 OAUTH2_CLIENT_ID=123456 OAUTH2_CLIENT_SECRET=123456 diff --git a/cfgldr/cfgldr.go b/cfgldr/cfgldr.go index 42f62dd..4a93b19 100644 --- a/cfgldr/cfgldr.go +++ b/cfgldr/cfgldr.go @@ -19,6 +19,7 @@ type DatabaseConfig struct { type AppConfig struct { Port string `mapstructure:"PORT"` Env string `mapstructure:"ENV"` + Host string `mapstructure:"HOST"` } type RedisConfig struct { diff --git a/cmd/main.go b/cmd/main.go index 752b469..22cf02e 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -5,7 +5,7 @@ import ( "github.com/gin-gonic/gin" "github.com/isd-sgcu/oph66-backend/di" - _ "github.com/isd-sgcu/oph66-backend/docs" + "github.com/isd-sgcu/oph66-backend/docs" swaggerFiles "github.com/swaggo/files" ginSwagger "github.com/swaggo/gin-swagger" ) @@ -25,6 +25,8 @@ func main() { } container.Logger.Info("init container successfully") + docs.SwaggerInfo.Host = container.Config.AppConfig.Host + if !container.Config.AppConfig.IsDevelopment() { gin.SetMode(gin.ReleaseMode) } diff --git a/docs/docs.go b/docs/docs.go index 176f69d..d0206bb 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -1,4 +1,5 @@ -// Package docs Code generated by swaggo/swag. DO NOT EDIT +// Code generated by swaggo/swag. DO NOT EDIT. + package docs import "github.com/swaggo/swag" diff --git a/go.mod b/go.mod index 805a24f..4aff018 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/gin-gonic/gin v1.9.1 github.com/google/wire v0.5.0 github.com/redis/go-redis/v9 v9.3.1 - github.com/spf13/viper v1.18.2 + github.com/spf13/viper v1.18.1 github.com/swaggo/files v1.0.1 github.com/swaggo/gin-swagger v1.6.0 github.com/swaggo/swag v1.16.2 diff --git a/go.sum b/go.sum index 9919ba8..c73ebac 100644 --- a/go.sum +++ b/go.sum @@ -119,12 +119,8 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 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-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= -github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA= github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY= -github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= github.com/jackc/pgx/v5 v5.5.1 h1:5I9etrGkLrN+2XPCsi6XLlV5DITbSL/xBZdmAxFcXPI= github.com/jackc/pgx/v5 v5.5.1/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= @@ -166,8 +162,6 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN 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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/redis/go-redis/v9 v9.3.0 h1:RiVDjmig62jIWp7Kk4XVLs0hzV6pI3PyTnnL0cnn0u0= -github.com/redis/go-redis/v9 v9.3.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/redis/go-redis/v9 v9.3.1 h1:KqdY8U+3X6z+iACvumCNxnoluToB+9Me+TvyFa21Mds= github.com/redis/go-redis/v9 v9.3.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= @@ -186,8 +180,6 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.18.1 h1:rmuU42rScKWlhhJDyXZRKJQHXFX02chSVW1IvkPGiVM= github.com/spf13/viper v1.18.1/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= -github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= -github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -214,6 +206,8 @@ github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= @@ -237,8 +231,6 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= -golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/exp v0.0.0-20231226003508-02704c960a9b h1:kLiC65FbiHWFAOu+lxwNPujcsl8VYyTYYEZnsOO1WK4= golang.org/x/exp v0.0.0-20231226003508-02704c960a9b/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -304,8 +296,6 @@ golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.153.0 h1:N1AwGhielyKFaUqH07/ZSIQR3uNPcV7NVw0vj+j4iR4= -google.golang.org/api v0.153.0/go.mod h1:3qNJX5eOmhiWYc67jRA/3GsDw97UFb5ivv7Y2PrriAY= google.golang.org/api v0.154.0 h1:X7QkVKZBskztmpPKWQXgjJRPA2dJYrL6r+sYPRLj050= google.golang.org/api v0.154.0/go.mod h1:qhSMkM85hgqiokIYsrRyKxrjfBeIhgl4Z2JmeRkYylc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -315,8 +305,6 @@ google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I= -google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 h1:/jFB8jK5R3Sq3i/lmeZO0cATSzFfZaJq1J2Euan3XKU= google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0/go.mod h1:FUoWkonphQm3RhTS+kOEhF8h0iDpm4tdXolVCeZ9KKA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -324,8 +312,6 @@ google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= -google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= diff --git a/internal/auth/auth.handler.go b/internal/auth/auth.handler.go index 99e7295..af067f7 100644 --- a/internal/auth/auth.handler.go +++ b/internal/auth/auth.handler.go @@ -68,7 +68,7 @@ func (h *handlerImpl) GoogleCallback(c *gin.Context) { // Register godoc // @summary Register -// @description Register new account with @chula email +// @description Register new account with email // @id Register // @produce json // @tags auth