From bc56844a1b9671fa78000a6e0e88eea1ff3bb5c4 Mon Sep 17 00:00:00 2001 From: Alfex4936 Date: Sat, 2 Mar 2024 13:03:07 +0900 Subject: [PATCH] [Backend][Docs] Auth API Swagger-fy --- backend/.gitignore | 5 +- backend/docs/docs.go | 425 +++++++++++++++++++++++++++++ backend/go.mod | 62 +++-- backend/go.sum | 156 +++++++---- backend/handlers/auth_api.go | 127 +++++++-- backend/main.go | 32 ++- backend/services/marker_service.go | 4 +- 7 files changed, 711 insertions(+), 100 deletions(-) create mode 100644 backend/docs/docs.go diff --git a/backend/.gitignore b/backend/.gitignore index 747bf72a..4050c12c 100644 --- a/backend/.gitignore +++ b/backend/.gitignore @@ -1,4 +1,7 @@ .env *.sql fly.toml -Dockerfile \ No newline at end of file +Dockerfile +swagger.json +swagger.yaml +swagformat.txt \ No newline at end of file diff --git a/backend/docs/docs.go b/backend/docs/docs.go new file mode 100644 index 00000000..4d02f02f --- /dev/null +++ b/backend/docs/docs.go @@ -0,0 +1,425 @@ +// 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": { + "name": "API Support", + "email": "chulbong.kr@gmail.com" + }, + "license": { + "name": "MIT", + "url": "https://github.com/Alfex4936/chulbong-kr/blob/main/LICENSE" + }, + "version": "{{.Version}}" + }, + "host": "{{.Host}}", + "basePath": "{{.BasePath}}", + "paths": { + "/auth/login": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "This endpoint is responsible for authenticating a user in the system.\nIt validates the user's login credentials (email and password).\nIf the credentials are invalid, it returns an error.\nOn successful authentication, it returns the user's information along with a token.\nThe token is also set in a secure cookie for client-side storage.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Log in a user", + "operationId": "login-user", + "parameters": [ + { + "description": "Login Request", + "name": "loginRequest", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.LoginRequest" + } + } + ], + "responses": { + "200": { + "description": "User logged in successfully, includes user info and token", + "schema": { + "$ref": "#/definitions/dto.LoginResponse" + } + }, + "400": { + "description": "Cannot parse JSON, wrong login form.", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "401": { + "description": "Invalid email or password", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "500": { + "description": "Failed to generate token", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/auth/request-reset-password": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "This endpoint initiates the password reset process for a user.\nIt generates a password reset token and sends a reset password email to the user.\nThe email sending process is executed in a non-blocking manner using a goroutine.\nIf there is an issue generating the token or sending the email, it returns an error.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Request password reset", + "operationId": "request-reset-password", + "parameters": [ + { + "type": "string", + "description": "User's email address for password reset", + "name": "email", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "Password reset request initiated successfully" + }, + "500": { + "description": "Failed to request reset password", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/auth/reset-password": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "This endpoint allows a user to reset their password using a valid token.\nThe token is typically obtained from a password reset email.\nIf the token is invalid or the reset fails, it returns an error.\nOn successful password reset, it returns a success status.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Reset password", + "operationId": "reset-password", + "parameters": [ + { + "type": "string", + "description": "Password reset token", + "name": "token", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "New password", + "name": "password", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "Password reset successfully" + }, + "500": { + "description": "Failed to reset password", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/auth/send-verification-email": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "This endpoint triggers sending a verification email to the user.\nIt checks if the email is already registered in the system.\nIf the email is already in use, it returns an error.\nIf the email is not in use, it asynchronously sends a verification email to the user.\nThe operation of sending the email does not block the API response, making use of a goroutine for asynchronous execution.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Send verification email", + "operationId": "send-verification-email", + "parameters": [ + { + "type": "string", + "description": "User Email", + "name": "email", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "Email sending initiated successfully" + }, + "409": { + "description": "Email already registered", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "500": { + "description": "An unexpected error occurred", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/auth/signup": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "This endpoint is responsible for registering a new user in the system.\nIt checks the verification status of the user's email before proceeding.\nIf the email is not verified, it returns an error.\nOn successful creation, it returns the user's information.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Sign up a new user", + "operationId": "sign-up-user", + "parameters": [ + { + "description": "SignUp Request", + "name": "signUpRequest", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/dto.SignUpRequest" + } + } + ], + "responses": { + "201": { + "description": "User registered successfully", + "schema": { + "$ref": "#/definitions/models.User" + } + }, + "400": { + "description": "Email not verified", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "409": { + "description": "Email already registered", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "500": { + "description": "An error occurred while creating the user", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/auth/validate-token": { + "post": { + "security": [ + { + "ApiKeyAuth": [] + } + ], + "description": "This endpoint is responsible for validating a user's token.\nIt checks the token's validity against the provided email.\nIf the token is invalid or expired, it returns an error.\nOn successful validation, it returns a success status.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "auth" + ], + "summary": "Validate token", + "operationId": "validate-token", + "parameters": [ + { + "type": "string", + "description": "Token for validation", + "name": "token", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "User's email associated with the token", + "name": "email", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "Token validated successfully" + }, + "400": { + "description": "Invalid or expired token", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "500": { + "description": "Error validating token", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + } + }, + "definitions": { + "dto.LoginRequest": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "password": { + "type": "string" + } + } + }, + "dto.LoginResponse": { + "type": "object", + "properties": { + "token": { + "type": "string" + }, + "user": { + "$ref": "#/definitions/models.User" + } + } + }, + "dto.SignUpRequest": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "password": { + "description": "Optional, not used for OAuth2 sign-ups", + "type": "string" + }, + "provider": { + "description": "e.g., \"google\", \"kakao\", empty for traditional sign-ups", + "type": "string" + }, + "providerId": { + "description": "Unique ID from the provider, empty for traditional sign-ups", + "type": "string" + }, + "username": { + "description": "Optional for traditional, used if provided for OAuth2", + "type": "string" + } + } + }, + "models.User": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "userId": { + "description": "TODO: UUID?", + "type": "integer" + }, + "username": { + "type": "string" + } + } + } + } +}` + +// SwaggerInfo holds exported Swagger Info so clients can modify it +var SwaggerInfo = &swag.Spec{ + Version: "1.0", + Host: "localhost:9452", + BasePath: "/api/v1/", + Schemes: []string{}, + Title: "chulbong-kr API", + Description: "Pullup bar locations with KakaoMap API", + InfoInstanceName: "swagger", + SwaggerTemplate: docTemplate, + LeftDelim: "{{", + RightDelim: "}}", +} + +func init() { + swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo) +} diff --git a/backend/go.mod b/backend/go.mod index 14cdf0c7..52056302 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -3,49 +3,65 @@ module chulbong-kr go 1.22.0 require ( - github.com/aws/aws-sdk-go-v2/config v1.27.0 - github.com/aws/aws-sdk-go-v2/service/s3 v1.49.0 + github.com/aws/aws-sdk-go-v2/config v1.27.4 + github.com/aws/aws-sdk-go-v2/service/s3 v1.51.1 github.com/go-sql-driver/mysql v1.7.1 - github.com/gofiber/fiber/v2 v2.52.0 + github.com/gofiber/fiber/v2 v2.52.1 github.com/google/uuid v1.6.0 github.com/jmoiron/sqlx v1.3.5 github.com/joho/godotenv v1.5.1 github.com/robfig/cron/v3 v3.0.1 - golang.org/x/crypto v0.19.0 + golang.org/x/crypto v0.20.0 golang.org/x/oauth2 v0.17.0 ) require ( - cloud.google.com/go/compute v1.20.1 // indirect + cloud.google.com/go/compute v1.24.0 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect + github.com/KyleBanks/depth v1.2.1 // indirect + github.com/PuerkitoBio/purell v1.2.1 // indirect + github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/andybalholm/brotli v1.1.0 // indirect - github.com/aws/aws-sdk-go-v2 v1.25.0 // indirect - github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.0 // indirect - github.com/aws/aws-sdk-go-v2/credentials v1.17.0 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.0 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.0 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.0 // indirect + github.com/aws/aws-sdk-go-v2 v1.25.2 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.4 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.2 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.2 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.2 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.0 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.0 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.19.0 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.22.0 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.27.0 // indirect - github.com/aws/smithy-go v1.20.0 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.2 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.2 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.2 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.2 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.20.1 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.1 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.28.1 // indirect + github.com/aws/smithy-go v1.20.1 // 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.14 // indirect + github.com/go-openapi/swag v0.22.9 // indirect + github.com/gofiber/swagger v1.0.0 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/klauspost/compress v1.17.6 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/klauspost/compress v1.17.7 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/rivo/uniseg v0.4.7 // indirect + github.com/swaggo/files/v2 v2.0.0 // indirect + github.com/swaggo/swag v1.16.3 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.52.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect golang.org/x/net v0.21.0 // indirect golang.org/x/sys v0.17.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.31.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/tools v0.18.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/protobuf v1.32.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/backend/go.sum b/backend/go.sum index 8f1de657..32fde7f6 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -1,67 +1,89 @@ -cloud.google.com/go/compute v1.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg= -cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= +cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40= 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/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= +github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= +github.com/PuerkitoBio/purell v1.2.1 h1:QsZ4TjvwiMpat6gBCBxEQI0rcS9ehtkKtSpiUnd9N28= +github.com/PuerkitoBio/purell v1.2.1/go.mod h1:ZwHcC/82TOaovDi//J/804umJFFmbOHPngi8iYYv/Eo= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M= github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY= -github.com/aws/aws-sdk-go-v2 v1.25.0 h1:sv7+1JVJxOu/dD/sz/csHX7jFqmP001TIY7aytBWDSQ= -github.com/aws/aws-sdk-go-v2 v1.25.0/go.mod h1:G104G1Aho5WqF+SR3mDIobTABQzpYV0WxMsKxlMggOA= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.0 h1:2UO6/nT1lCZq1LqM67Oa4tdgP1CvL1sLSxvuD+VrOeE= -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.0/go.mod h1:5zGj2eA85ClyedTDK+Whsu+w9yimnVIZvhvBKrDquM8= -github.com/aws/aws-sdk-go-v2/config v1.27.0 h1:J5sdGCAHuWKIXLeXiqr8II/adSvetkx0qdZwdbXXpb0= -github.com/aws/aws-sdk-go-v2/config v1.27.0/go.mod h1:cfh8v69nuSUohNFMbIISP2fhmblGmYEOKs5V53HiHnk= -github.com/aws/aws-sdk-go-v2/credentials v1.17.0 h1:lMW2x6sKBsiAJrpi1doOXqWFyEPoE886DTb1X0wb7So= -github.com/aws/aws-sdk-go-v2/credentials v1.17.0/go.mod h1:uT41FIH8cCIxOdUYIL0PYyHlL1NoneDuDSCwg5VE/5o= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.0 h1:xWCwjjvVz2ojYTP4kBKUuUh9ZrXfcAXpflhOUUeXg1k= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.0/go.mod h1:j3fACuqXg4oMTQOR2yY7m0NmJY0yBK4L4sLsRXq1Ins= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.0 h1:NPs/EqVO+ajwOoq56EfcGKa3L3ruWuazkIw1BqxwOPw= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.0/go.mod h1:D+duLy2ylgatV+yTlQ8JTuLfDD0BnFvnQRc+o6tbZ4M= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.0 h1:ks7KGMVUMoDzcxNWUlEdI+/lokMFD136EL6DWmUOV80= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.0/go.mod h1:hL6BWM/d/qz113fVitZjbXR0E+RCTU1+x+1Idyn5NgE= +github.com/aws/aws-sdk-go-v2 v1.25.2 h1:/uiG1avJRgLGiQM9X3qJM8+Qa6KRGK5rRPuXE0HUM+w= +github.com/aws/aws-sdk-go-v2 v1.25.2/go.mod h1:Evoc5AsmtveRt1komDwIsjHFyrP5tDuF1D1U+6z6pNo= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 h1:gTK2uhtAPtFcdRRJilZPx8uJLL2J85xK11nKtWL0wfU= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1/go.mod h1:sxpLb+nZk7tIfCWChfd+h4QwHNUR57d8hA1cleTkjJo= +github.com/aws/aws-sdk-go-v2/config v1.27.4 h1:AhfWb5ZwimdsYTgP7Od8E9L1u4sKmDW2ZVeLcf2O42M= +github.com/aws/aws-sdk-go-v2/config v1.27.4/go.mod h1:zq2FFXK3A416kiukwpsd+rD4ny6JC7QSkp4QdN1Mp2g= +github.com/aws/aws-sdk-go-v2/credentials v1.17.4 h1:h5Vztbd8qLppiPwX+y0Q6WiwMZgpd9keKe2EAENgAuI= +github.com/aws/aws-sdk-go-v2/credentials v1.17.4/go.mod h1:+30tpwrkOgvkJL1rUZuRLoxcJwtI/OkeBLYnHxJtVe0= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.2 h1:AK0J8iYBFeUk2Ax7O8YpLtFsfhdOByh2QIkHmigpRYk= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.15.2/go.mod h1:iRlGzMix0SExQEviAyptRWRGdYNo3+ufW/lCzvKVTUc= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.2 h1:bNo4LagzUKbjdxE0tIcR9pMzLR2U/Tgie1Hq1HQ3iH8= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.2/go.mod h1:wRQv0nN6v9wDXuWThpovGQjqF1HFdcgWjporw14lS8k= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.2 h1:EtOU5jsPdIQNP+6Q2C5e3d65NKT1PeCiQk+9OdzO12Q= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.2/go.mod h1:tyF5sKccmDz0Bv4NrstEr+/9YkSPJHrcO7UsUKf7pWM= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.0 h1:TkbRExyKSVHELwG9gz2+gql37jjec2R5vus9faTomwE= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.0/go.mod h1:T3/9xMKudHhnj8it5EqIrhvv11tVZqWYkKcot+BFStc= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.0 h1:a33HuFlO0KsveiP90IUJh8Xr/cx9US2PqkSroaLc+o8= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.0/go.mod h1:SxIkWpByiGbhbHYTo9CMTUnx2G4p4ZQMrDPcRRy//1c= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.0 h1:UiSyK6ent6OKpkMJN3+k5HZ4sk4UfchEaaW5wv7SblQ= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.0/go.mod h1:l7kzl8n8DXoRyFz5cIMG70HnPauWa649TUhgw8Rq6lo= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.0 h1:SHN/umDLTmFTmYfI+gkanz6da3vK8Kvj/5wkqnTHbuA= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.0/go.mod h1:l8gPU5RYGOFHJqWEpPMoRTP0VoaWQSkJdKo+hwWnnDA= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.0 h1:l5puwOHr7IxECuPMIuZG7UKOzAnF24v6t4l+Z5Moay4= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.0/go.mod h1:Oov79flWa/n7Ni+lQC3z+VM7PoRM47omRqbJU9B5Y7E= -github.com/aws/aws-sdk-go-v2/service/s3 v1.49.0 h1:VfU15izXQjz4m9y1DkbY79iylIiuPwWtrram4cSpWEI= -github.com/aws/aws-sdk-go-v2/service/s3 v1.49.0/go.mod h1:1o/W6JFUuREj2ExoQ21vHJgO7wakvjhol91M9eknFgs= -github.com/aws/aws-sdk-go-v2/service/sso v1.19.0 h1:u6OkVDxtBPnxPkZ9/63ynEe+8kHbtS5IfaC4PzVxzWM= -github.com/aws/aws-sdk-go-v2/service/sso v1.19.0/go.mod h1:YqbU3RS/pkDVu+v+Nwxvn0i1WB0HkNWEePWbmODEbbs= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.22.0 h1:6DL0qu5+315wbsAEEmzK+P9leRwNbkp+lGjPC+CEvb8= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.22.0/go.mod h1:olUAyg+FaoFaL/zFaeQQONjOZ9HXoxgvI/c7mQTYz7M= -github.com/aws/aws-sdk-go-v2/service/sts v1.27.0 h1:cjTRjh700H36MQ8M0LnDn33W3JmwC77mdxIIyPWCdpM= -github.com/aws/aws-sdk-go-v2/service/sts v1.27.0/go.mod h1:nXfOBMWPokIbOY+Gi7a1psWMSvskUCemZzI+SMB7Akc= -github.com/aws/smithy-go v1.20.0 h1:6+kZsCXZwKxZS9RfISnPc4EXlHoyAkm2hPuM8X2BrrQ= -github.com/aws/smithy-go v1.20.0/go.mod h1:uo5RKksAl4PzhqaAbjd4rLgFoq5koTsQKYuGe7dklGc= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.2 h1:en92G0Z7xlksoOylkUhuBSfJgijC7rHVLRdnIlHEs0E= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.2/go.mod h1:HgtQ/wN5G+8QSlK62lbOtNwQ3wTSByJ4wH2rCkPt+AE= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1 h1:EyBZibRTVAs6ECHZOw5/wlylS9OcTzwyjeQMudmREjE= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.1/go.mod h1:JKpmtYhhPs7D97NL/ltqz7yCkERFW5dOlHyVl66ZYF8= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.2 h1:zSdTXYLwuXDNPUS+V41i1SFDXG7V0ITp0D9UT9Cvl18= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.2/go.mod h1:v8m8k+qVy95nYi7d56uP1QImleIIY25BPiNJYzPBdFE= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.2 h1:5ffmXjPtwRExp1zc7gENLgCPyHFbhEPwVTkTiH9niSk= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.2/go.mod h1:Ru7vg1iQ7cR4i7SZ/JTLYN9kaXtbL69UdgG0OQWQxW0= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.2 h1:1oY1AVEisRI4HNuFoLdRUB0hC63ylDAN6Me3MrfclEg= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.2/go.mod h1:KZ03VgvZwSjkT7fOetQ/wF3MZUvYFirlI1H5NklUNsY= +github.com/aws/aws-sdk-go-v2/service/s3 v1.51.1 h1:juZ+uGargZOrQGNxkVHr9HHR/0N+Yu8uekQnV7EAVRs= +github.com/aws/aws-sdk-go-v2/service/s3 v1.51.1/go.mod h1:SoR0c7Jnq8Tpmt0KSLXIavhjmaagRqQpe9r70W3POJg= +github.com/aws/aws-sdk-go-v2/service/sso v1.20.1 h1:utEGkfdQ4L6YW/ietH7111ZYglLJvS+sLriHJ1NBJEQ= +github.com/aws/aws-sdk-go-v2/service/sso v1.20.1/go.mod h1:RsYqzYr2F2oPDdpy+PdhephuZxTfjHQe7SOBcZGoAU8= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.1 h1:9/GylMS45hGGFCcMrUZDVayQE1jYSIN6da9jo7RAYIw= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.1/go.mod h1:YjAPFn4kGFqKC54VsHs5fn5B6d+PCY2tziEa3U/GB5Y= +github.com/aws/aws-sdk-go-v2/service/sts v1.28.1 h1:3I2cBEYgKhrWlwyZgfpSO2BpaMY1LHPqXYk/QGlu2ew= +github.com/aws/aws-sdk-go-v2/service/sts v1.28.1/go.mod h1:uQ7YYKZt3adCRrdCBREm1CD3efFLOUNH77MrUCvx5oA= +github.com/aws/smithy-go v1.20.1 h1:4SZlSlMr36UEqC7XOyRVb27XMeZubNcBNN+9IgEPIQw= +github.com/aws/smithy-go v1.20.1/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +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.14 h1:7CBlRnw+mtjFGlPDRZmAMnq35cRzI91xj03HVyUi/Do= +github.com/go-openapi/spec v0.20.14/go.mod h1:8EOhTpBoFiask8rrgwbLC3zmJfz4zsCUueRuPM6GNkw= +github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE= +github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= -github.com/gofiber/fiber/v2 v2.52.0 h1:S+qXi7y+/Pgvqq4DrSmREGiFwtB7Bu6+QFLuIHYw/UE= -github.com/gofiber/fiber/v2 v2.52.0/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/gofiber/fiber/v2 v2.52.1 h1:1RoU2NS+b98o1L77sdl5mboGPiW+0Ypsi5oLmcYlgHI= +github.com/gofiber/fiber/v2 v2.52.1/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ= +github.com/gofiber/swagger v1.0.0 h1:BzUzDS9ZT6fDUa692kxmfOjc1DZiloLiPK/W5z1H1tc= +github.com/gofiber/swagger v1.0.0/go.mod h1:QrYNF1Yrc7ggGK6ATsJ6yfH/8Zi5bu9lA7wB8TmCecg= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI= -github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +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/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= @@ -71,37 +93,69 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= +github.com/swaggo/files/v2 v2.0.0 h1:hmAt8Dkynw7Ssz46F6pn8ok6YmGZqHSVLZ+HQM7i0kw= +github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0JQj66kyM= +github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg= +github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.52.0 h1:wqBQpxH71XW0e2g+Og4dzQM8pk34aFYlA1Ga8db7gU0= github.com/valyala/fasthttp v1.52.0/go.mod h1:hf5C4QnVMkNXMspnsUlfM3WitlgYflyhHYoKol/szxQ= github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= -golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.20.0 h1:jmAMJJZXr5KiCw05dfYK9QnqaqKLYXijU23lsEdcQqg= +golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +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.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.17.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/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +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.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= +golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= +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/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= 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/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/backend/handlers/auth_api.go b/backend/handlers/auth_api.go index dceaa897..30c54511 100644 --- a/backend/handlers/auth_api.go +++ b/backend/handlers/auth_api.go @@ -2,7 +2,6 @@ package handlers import ( "chulbong-kr/dto" - "chulbong-kr/models" "chulbong-kr/services" "database/sql" "fmt" @@ -12,25 +11,25 @@ import ( "github.com/gofiber/fiber/v2" ) -// DeleteExample handler -func DeleteExample(c *fiber.Ctx) error { - return c.SendString("DELETE request example") -} - -// PostExample handler -func PostExample(c *fiber.Ctx) error { - user := new(models.User) - - // Parse the body into the struct - if err := c.BodyParser(user); err != nil { - return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{ - "error": "Cannot parse JSON", - }) - } - // Return the user as JSON - return c.Status(fiber.StatusOK).JSON(user) -} - +// SignUp User godoc +// +// @Summary Sign up a new user +// @Description This endpoint is responsible for registering a new user in the system. +// @Description It checks the verification status of the user's email before proceeding. +// @Description If the email is not verified, it returns an error. +// @Description On successful creation, it returns the user's information. +// @ID sign-up-user +// @Tags auth +// @Accept json +// @Produce json +// @Param signUpRequest body dto.SignUpRequest true "SignUp Request" +// @Security ApiKeyAuth +// @Success 201 {object} models.User "User registered successfully" +// @Failure 400 {object} map[string]interface{} "Cannot parse JSON, wrong sign up form." +// @Failure 400 {object} map[string]interface{} "Email not verified" +// @Failure 409 {object} map[string]interface{} "Email already registered" +// @Failure 500 {object} map[string]interface{} "An error occurred while creating the user" +// @Router /auth/signup [post] func SignUpHandler(c *fiber.Ctx) error { var signUpReq dto.SignUpRequest if err := c.BodyParser(&signUpReq); err != nil { @@ -61,6 +60,25 @@ func SignUpHandler(c *fiber.Ctx) error { return c.Status(fiber.StatusCreated).JSON(user) } +// Login User godoc +// +// @Summary Log in a user +// @Description This endpoint is responsible for authenticating a user in the system. +// @Description It validates the user's login credentials (email and password). +// @Description If the credentials are invalid, it returns an error. +// @Description On successful authentication, it returns the user's information along with a token. +// @Description The token is also set in a secure cookie for client-side storage. +// @ID login-user +// @Tags auth +// @Accept json +// @Produce json +// @Param loginRequest body dto.LoginRequest true "Login Request" +// @Security ApiKeyAuth +// @Success 200 {object} dto.LoginResponse "User logged in successfully, includes user info and token" +// @Failure 400 {object} map[string]interface{} "Cannot parse JSON, wrong login form." +// @Failure 401 {object} map[string]interface{} "Invalid email or password" +// @Failure 500 {object} map[string]interface{} "Failed to generate token" +// @Router /auth/login [post] func LoginHandler(c *fiber.Ctx) error { var request dto.LoginRequest if err := c.BodyParser(&request); err != nil { @@ -90,6 +108,24 @@ func LoginHandler(c *fiber.Ctx) error { return c.JSON(response) } +// Send Verification Email godoc +// +// @Summary Send verification email +// @Description This endpoint triggers sending a verification email to the user. +// @Description It checks if the email is already registered in the system. +// @Description If the email is already in use, it returns an error. +// @Description If the email is not in use, it asynchronously sends a verification email to the user. +// @Description The operation of sending the email does not block the API response, making use of a goroutine for asynchronous execution. +// @ID send-verification-email +// @Tags auth +// @Accept json +// @Produce json +// @Param email formData string true "User Email" +// @Security ApiKeyAuth +// @Success 200 "Email sending initiated successfully" +// @Failure 409 {object} map[string]interface{} "Email already registered" +// @Failure 500 {object} map[string]interface{} "An unexpected error occurred" +// @Router /auth/send-verification-email [post] func SendVerificationEmailHandler(c *fiber.Ctx) error { userEmail := c.FormValue("email") _, err := services.GetUserByEmail(userEmail) @@ -134,6 +170,24 @@ func SendVerificationEmailHandler(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusOK) } +// Validate Token godoc +// +// @Summary Validate token +// @Description This endpoint is responsible for validating a user's token. +// @Description It checks the token's validity against the provided email. +// @Description If the token is invalid or expired, it returns an error. +// @Description On successful validation, it returns a success status. +// @ID validate-token +// @Tags auth +// @Accept json +// @Produce json +// @Param token formData string true "Token for validation" +// @Param email formData string true "User's email associated with the token" +// @Security ApiKeyAuth +// @Success 200 "Token validated successfully" +// @Failure 400 {object} map[string]interface{} "Invalid or expired token" +// @Failure 500 {object} map[string]interface{} "Error validating token" +// @Router /auth/validate-token [post] func ValidateTokenHandler(c *fiber.Ctx) error { token := c.FormValue("token") email := c.FormValue("email") @@ -151,6 +205,22 @@ func ValidateTokenHandler(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusOK) } +// Request Reset Password godoc +// +// @Summary Request password reset +// @Description This endpoint initiates the password reset process for a user. +// @Description It generates a password reset token and sends a reset password email to the user. +// @Description The email sending process is executed in a non-blocking manner using a goroutine. +// @Description If there is an issue generating the token or sending the email, it returns an error. +// @ID request-reset-password +// @Tags auth +// @Accept json +// @Produce json +// @Param email formData string true "User's email address for password reset" +// @Security ApiKeyAuth +// @Success 200 "Password reset request initiated successfully" +// @Failure 500 {object} map[string]interface{} "Failed to request reset password" +// @Router /auth/request-reset-password [post] func RequestResetPasswordHandler(c *fiber.Ctx) error { email := c.FormValue("email") @@ -175,6 +245,23 @@ func RequestResetPasswordHandler(c *fiber.Ctx) error { return c.SendStatus(fiber.StatusOK) } +// Reset Password godoc +// +// @Summary Reset password +// @Description This endpoint allows a user to reset their password using a valid token. +// @Description The token is typically obtained from a password reset email. +// @Description If the token is invalid or the reset fails, it returns an error. +// @Description On successful password reset, it returns a success status. +// @ID reset-password +// @Tags auth +// @Accept json +// @Produce json +// @Param token formData string true "Password reset token" +// @Param password formData string true "New password" +// @Security ApiKeyAuth +// @Success 200 "Password reset successfully" +// @Failure 500 {object} map[string]interface{} "Failed to reset password" +// @Router /auth/reset-password [post] func ResetPasswordHandler(c *fiber.Ctx) error { token := c.FormValue("token") newPassword := c.FormValue("password") diff --git a/backend/main.go b/backend/main.go index d62ad4bf..9799a262 100644 --- a/backend/main.go +++ b/backend/main.go @@ -14,11 +14,23 @@ import ( "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/cors" "github.com/gofiber/fiber/v2/middleware/logger" + "github.com/gofiber/swagger" "github.com/joho/godotenv" "golang.org/x/oauth2" "golang.org/x/oauth2/google" + + _ "chulbong-kr/docs" ) +// @title chulbong-kr API +// @version 1.0 +// @description Pullup bar locations with KakaoMap API +// @contact.name API Support +// @contact.email chulbong.kr@gmail.com +// @license.name MIT +// @license.url https://github.com/Alfex4936/chulbong-kr/blob/main/LICENSE +// @host localhost:9452 +// @BasePath /api/v1/ func main() { // Load .env file err := godotenv.Load() @@ -62,14 +74,16 @@ func main() { // Enable CORS for all routes app.Use(cors.New(cors.Config{ - AllowOrigins: "http://localhost:5173, https://chulbong-kr.vercel.app", // List allowed origins - AllowMethods: "GET,POST,PUT,DELETE,OPTIONS", // Explicitly list allowed methods - AllowHeaders: "*", // TODO: Allow specific headers + AllowOrigins: "http://localhost:5173,https://chulbong-kr.vercel.app", // List allowed origins + AllowMethods: "GET,POST,PUT,DELETE,OPTIONS", // Explicitly list allowed methods + AllowHeaders: "*", // TODO: Allow specific headers ExposeHeaders: "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers", AllowCredentials: true, })) app.Use(logger.New()) + app.Get("/", healthCheck) + app.Get("/swagger/*", swagger.HandlerDefault) // default // Setup routes api := app.Group("/api/v1") @@ -150,3 +164,15 @@ func setTokenExpirationTime() { // Assign the converted duration to the global variable services.TOKEN_DURATION = time.Duration(durationInt) * time.Hour } + +func healthCheck(c *fiber.Ctx) error { + res := map[string]interface{}{ + "data": "Server is up and running", + } + + if err := c.JSON(res); err != nil { + return err + } + + return nil +} diff --git a/backend/services/marker_service.go b/backend/services/marker_service.go index 67fe1681..dde58c06 100644 --- a/backend/services/marker_service.go +++ b/backend/services/marker_service.go @@ -299,7 +299,7 @@ SELECT EXISTS ( // Haversine formula func approximateDistance(lat1, long1, lat2, long2 float64) float64 { - const R = 6371000 // Radius of the Earth in meters + const R = 6370986 // Radius of the Earth in meters lat1Rad := lat1 * (math.Pi / 180) lat2Rad := lat2 * (math.Pi / 180) deltaLat := (lat2 - lat1) * (math.Pi / 180) @@ -317,7 +317,7 @@ func distance(lat1, long1, lat2, long2 float64) float64 { math.Cos(lat1*(math.Pi/180))*math.Cos(lat2*(math.Pi/180))* math.Sin(deltaLong/2)*math.Sin(deltaLong/2) var c = 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a)) - return 6371000 * c // Earth radius in meters + return 6370986 * c // Earth radius in meters } // IsInSouthKorea checks if given latitude and longitude are within South Korea (roughly)