diff --git a/backend/docs/docs.go b/backend/docs/docs.go index 6d201a8..732f4ad 100644 --- a/backend/docs/docs.go +++ b/backend/docs/docs.go @@ -15,6 +15,1106 @@ const docTemplate = `{ "host": "{{.Host}}", "basePath": "{{.BasePath}}", "paths": { + "/api/v1/admin/cloudflare/cache/purge-all": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Purges all cached content for the configured zone", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin - Cloudflare" + ], + "summary": "Purge All Cache", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/internal_admin_cloudflare.PurgeResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/admin/cloudflare/cache/purge-hosts": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Purges content by hostnames", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin - Cloudflare" + ], + "summary": "Purge Cache by Hosts", + "parameters": [ + { + "description": "Hosts to purge", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/internal_admin_cloudflare.PurgeHostsRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/internal_admin_cloudflare.PurgeResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/admin/cloudflare/cache/purge-tags": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Purges content by cache tags (Enterprise only)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin - Cloudflare" + ], + "summary": "Purge Cache by Tags", + "parameters": [ + { + "description": "Tags to purge", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/internal_admin_cloudflare.PurgeTagsRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/internal_admin_cloudflare.PurgeResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/admin/cloudflare/cache/purge-urls": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Purges specific URLs from cache", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin - Cloudflare" + ], + "summary": "Purge Cache by URLs", + "parameters": [ + { + "description": "URLs to purge", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/internal_admin_cloudflare.PurgeURLsRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/internal_admin_cloudflare.PurgeResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/admin/cloudflare/zones": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Returns all zones associated with the Cloudflare account", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin - Cloudflare" + ], + "summary": "List Cloudflare Zones", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/internal_admin_cloudflare.Zone" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/admin/cpanel/emails": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Returns all email accounts for the cPanel account", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin - cPanel" + ], + "summary": "List Email Accounts", + "parameters": [ + { + "type": "string", + "description": "Filter by domain", + "name": "domain", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/internal_admin_cpanel.EmailAccount" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + }, + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Creates a new email account", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin - cPanel" + ], + "summary": "Create Email Account", + "parameters": [ + { + "description": "Email details", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/internal_admin_cpanel.CreateEmailRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/admin/cpanel/emails/{email}": { + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Deletes an email account", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin - cPanel" + ], + "summary": "Delete Email Account", + "parameters": [ + { + "type": "string", + "description": "Email address", + "name": "email", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/admin/cpanel/emails/{email}/password": { + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Changes the password for an email account", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin - cPanel" + ], + "summary": "Change Email Password", + "parameters": [ + { + "type": "string", + "description": "Email address", + "name": "email", + "in": "path", + "required": true + }, + { + "description": "New password", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/internal_admin_cpanel.ChangePasswordRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/admin/cpanel/emails/{email}/quota": { + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Updates the disk quota for an email account", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin - cPanel" + ], + "summary": "Update Email Quota", + "parameters": [ + { + "type": "string", + "description": "Email address", + "name": "email", + "in": "path", + "required": true + }, + { + "description": "New quota in MB", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/internal_admin_cpanel.UpdateQuotaRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/auth/login": { + "post": { + "description": "Authenticates a user by email and password. Returns JWT and user info.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Auth" + ], + "summary": "User Login", + "parameters": [ + { + "description": "Login Credentials", + "name": "login", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.LoginRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.AuthResponse" + } + }, + "400": { + "description": "Invalid Request", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/companies": { + "get": { + "description": "Returns a list of all companies.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Companies" + ], + "summary": "List Companies", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.CompanyResponse" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + }, + "post": { + "description": "Registers a new company and creates an initial admin user.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Companies" + ], + "summary": "Create Company (Tenant)", + "parameters": [ + { + "description": "Company Details", + "name": "company", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.CreateCompanyRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.CompanyResponse" + } + }, + "400": { + "description": "Invalid Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/storage/download-url": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Generate a pre-signed URL to download a private file from S3", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Storage" + ], + "summary": "Generate download URL", + "parameters": [ + { + "description": "Download request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/internal_handlers.DownloadURLRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/internal_handlers.DownloadURLResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/storage/files": { + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Delete a stored file by key", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Storage" + ], + "summary": "Delete file", + "parameters": [ + { + "type": "string", + "description": "File key", + "name": "key", + "in": "query", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/storage/upload-url": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Generate a pre-signed URL to upload a file to S3", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Storage" + ], + "summary": "Generate upload URL", + "parameters": [ + { + "description": "Upload request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/internal_handlers.UploadURLRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/internal_handlers.UploadURLResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/users": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Returns a list of users belonging to the authenticated tenant.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "List Users", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.UserResponse" + } + } + }, + "403": { + "description": "Forbidden", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + }, + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Creates a new user under the current tenant. Requires Admin role.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Create User", + "parameters": [ + { + "description": "User Details", + "name": "user", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.CreateUserRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.UserResponse" + } + }, + "400": { + "description": "Invalid Request", + "schema": { + "type": "string" + } + }, + "403": { + "description": "Forbidden", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/users/{id}": { + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Deletes a user by ID. Must belong to the same tenant.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Delete User", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "User deleted", + "schema": { + "type": "string" + } + }, + "403": { + "description": "Forbidden", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/applications": { + "get": { + "description": "List all applications for a job", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Applications" + ], + "summary": "List Applications", + "parameters": [ + { + "type": "integer", + "description": "Filter applications by job ID", + "name": "jobId", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + }, + "post": { + "description": "Submit a new job application for a posting", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Applications" + ], + "summary": "Create Application", + "parameters": [ + { + "description": "Application data", + "name": "application", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.CreateApplicationRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/applications/{id}": { + "get": { + "description": "Retrieve a job application by its ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Applications" + ], + "summary": "Get Application", + "parameters": [ + { + "type": "integer", + "description": "Application ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + } + }, + "/applications/{id}/status": { + "put": { + "description": "Update the status of a job application", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Applications" + ], + "summary": "Update Application Status", + "parameters": [ + { + "type": "integer", + "description": "Application ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Status update", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.UpdateApplicationStatusRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, "/jobs": { "get": { "description": "Get a paginated list of job postings with optional filters", @@ -58,7 +1158,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/dto.PaginatedResponse" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.PaginatedResponse" } }, "500": { @@ -88,7 +1188,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.CreateJobRequest" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.CreateJobRequest" } } ], @@ -96,7 +1196,7 @@ const docTemplate = `{ "201": { "description": "Created", "schema": { - "$ref": "#/definitions/models.Job" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Job" } }, "400": { @@ -140,7 +1240,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.Job" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Job" } }, "400": { @@ -183,7 +1283,7 @@ const docTemplate = `{ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.UpdateJobRequest" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.UpdateJobRequest" } } ], @@ -191,7 +1291,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.Job" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Job" } }, "400": { @@ -250,7 +1350,149 @@ const docTemplate = `{ } }, "definitions": { - "dto.CreateJobRequest": { + "github_com_rede5_gohorsejobs_backend_internal_core_dto.AuthResponse": { + "type": "object", + "properties": { + "token": { + "type": "string" + }, + "user": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.UserResponse" + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_core_dto.CompanyResponse": { + "type": "object", + "properties": { + "created_at": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "status": { + "type": "string" + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_core_dto.CreateCompanyRequest": { + "type": "object", + "properties": { + "admin_email": { + "type": "string" + }, + "contact": { + "type": "string" + }, + "document": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_core_dto.CreateUserRequest": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "name": { + "type": "string" + }, + "password": { + "type": "string" + }, + "roles": { + "description": "e.g. [\"RECRUITER\"]", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_core_dto.LoginRequest": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "password": { + "type": "string" + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_core_dto.UserResponse": { + "type": "object", + "properties": { + "created_at": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + } + }, + "status": { + "type": "string" + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_dto.CreateApplicationRequest": { + "type": "object", + "required": [ + "jobId" + ], + "properties": { + "documents": { + "type": "object", + "additionalProperties": true + }, + "email": { + "type": "string" + }, + "jobId": { + "type": "integer" + }, + "lineId": { + "type": "string" + }, + "message": { + "type": "string" + }, + "name": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "resumeUrl": { + "type": "string" + }, + "userId": { + "type": "integer" + }, + "whatsapp": { + "type": "string" + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_dto.CreateJobRequest": { "type": "object", "required": [ "companyId", @@ -329,16 +1571,16 @@ const docTemplate = `{ } } }, - "dto.PaginatedResponse": { + "github_com_rede5_gohorsejobs_backend_internal_dto.PaginatedResponse": { "type": "object", "properties": { "data": {}, "pagination": { - "$ref": "#/definitions/dto.Pagination" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.Pagination" } } }, - "dto.Pagination": { + "github_com_rede5_gohorsejobs_backend_internal_dto.Pagination": { "type": "object", "properties": { "limit": { @@ -352,7 +1594,28 @@ const docTemplate = `{ } } }, - "dto.UpdateJobRequest": { + "github_com_rede5_gohorsejobs_backend_internal_dto.UpdateApplicationStatusRequest": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "notes": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "pending", + "reviewed", + "shortlisted", + "rejected", + "hired" + ] + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_dto.UpdateJobRequest": { "type": "object", "properties": { "benefits": { @@ -423,15 +1686,75 @@ const docTemplate = `{ } } }, - "models.JSONMap": { + "github_com_rede5_gohorsejobs_backend_internal_models.Application": { + "type": "object", + "properties": { + "createdAt": { + "description": "Metadata", + "type": "string" + }, + "documents": { + "description": "Array of {type, url}", + "allOf": [ + { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.JSONMap" + } + ] + }, + "email": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "jobId": { + "type": "integer" + }, + "lineId": { + "type": "string" + }, + "message": { + "description": "Application Content", + "type": "string" + }, + "name": { + "description": "Applicant Info (for guest applications)", + "type": "string" + }, + "notes": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "resumeUrl": { + "type": "string" + }, + "status": { + "description": "Status \u0026 Notes", + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "userId": { + "description": "NULL for guest applications", + "type": "integer" + }, + "whatsapp": { + "type": "string" + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_models.JSONMap": { "type": "object", "additionalProperties": true }, - "models.Job": { + "github_com_rede5_gohorsejobs_backend_internal_models.Job": { "type": "object", "properties": { "benefits": { - "$ref": "#/definitions/models.JSONMap" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.JSONMap" }, "cityId": { "type": "integer" @@ -475,7 +1798,7 @@ const docTemplate = `{ "description": "Requirements \u0026 Benefits (JSONB arrays)", "allOf": [ { - "$ref": "#/definitions/models.JSONMap" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.JSONMap" } ] }, @@ -509,6 +1832,203 @@ const docTemplate = `{ "type": "string" } } + }, + "internal_admin_cloudflare.Error": { + "type": "object", + "properties": { + "code": { + "type": "integer" + }, + "message": { + "type": "string" + } + } + }, + "internal_admin_cloudflare.PurgeHostsRequest": { + "type": "object", + "properties": { + "hosts": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "internal_admin_cloudflare.PurgeResponse": { + "type": "object", + "properties": { + "errors": { + "type": "array", + "items": { + "$ref": "#/definitions/internal_admin_cloudflare.Error" + } + }, + "messages": { + "type": "array", + "items": { + "type": "string" + } + }, + "result": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + "success": { + "type": "boolean" + } + } + }, + "internal_admin_cloudflare.PurgeTagsRequest": { + "type": "object", + "properties": { + "tags": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "internal_admin_cloudflare.PurgeURLsRequest": { + "type": "object", + "properties": { + "urls": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "internal_admin_cloudflare.Zone": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "status": { + "type": "string" + } + } + }, + "internal_admin_cpanel.ChangePasswordRequest": { + "type": "object", + "properties": { + "password": { + "type": "string" + } + } + }, + "internal_admin_cpanel.CreateEmailRequest": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "password": { + "type": "string" + }, + "quota": { + "description": "MB, 0 = unlimited", + "type": "integer" + } + } + }, + "internal_admin_cpanel.EmailAccount": { + "type": "object", + "properties": { + "diskquota": { + "type": "string" + }, + "diskused": { + "type": "string" + }, + "domain": { + "type": "string" + }, + "email": { + "type": "string" + }, + "humandiskquota": { + "type": "string" + }, + "humandiskused": { + "type": "string" + }, + "login": { + "type": "string" + } + } + }, + "internal_admin_cpanel.UpdateQuotaRequest": { + "type": "object", + "properties": { + "quota": { + "description": "MB", + "type": "integer" + } + } + }, + "internal_handlers.DownloadURLRequest": { + "type": "object", + "properties": { + "key": { + "type": "string" + } + } + }, + "internal_handlers.DownloadURLResponse": { + "type": "object", + "properties": { + "downloadUrl": { + "type": "string" + }, + "expiresIn": { + "description": "seconds", + "type": "integer" + } + } + }, + "internal_handlers.UploadURLRequest": { + "type": "object", + "properties": { + "contentType": { + "type": "string" + }, + "filename": { + "type": "string" + }, + "folder": { + "description": "Optional: logos, resumes, documents", + "type": "string" + } + } + }, + "internal_handlers.UploadURLResponse": { + "type": "object", + "properties": { + "expiresIn": { + "description": "seconds", + "type": "integer" + }, + "key": { + "type": "string" + }, + "publicUrl": { + "type": "string" + }, + "uploadUrl": { + "type": "string" + } + } } } }` diff --git a/backend/docs/swagger.json b/backend/docs/swagger.json index a939278..9eed5fa 100644 --- a/backend/docs/swagger.json +++ b/backend/docs/swagger.json @@ -9,6 +9,1106 @@ "host": "localhost:8080", "basePath": "/", "paths": { + "/api/v1/admin/cloudflare/cache/purge-all": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Purges all cached content for the configured zone", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin - Cloudflare" + ], + "summary": "Purge All Cache", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/internal_admin_cloudflare.PurgeResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/admin/cloudflare/cache/purge-hosts": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Purges content by hostnames", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin - Cloudflare" + ], + "summary": "Purge Cache by Hosts", + "parameters": [ + { + "description": "Hosts to purge", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/internal_admin_cloudflare.PurgeHostsRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/internal_admin_cloudflare.PurgeResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/admin/cloudflare/cache/purge-tags": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Purges content by cache tags (Enterprise only)", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin - Cloudflare" + ], + "summary": "Purge Cache by Tags", + "parameters": [ + { + "description": "Tags to purge", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/internal_admin_cloudflare.PurgeTagsRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/internal_admin_cloudflare.PurgeResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/admin/cloudflare/cache/purge-urls": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Purges specific URLs from cache", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin - Cloudflare" + ], + "summary": "Purge Cache by URLs", + "parameters": [ + { + "description": "URLs to purge", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/internal_admin_cloudflare.PurgeURLsRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/internal_admin_cloudflare.PurgeResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/admin/cloudflare/zones": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Returns all zones associated with the Cloudflare account", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin - Cloudflare" + ], + "summary": "List Cloudflare Zones", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/internal_admin_cloudflare.Zone" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/admin/cpanel/emails": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Returns all email accounts for the cPanel account", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin - cPanel" + ], + "summary": "List Email Accounts", + "parameters": [ + { + "type": "string", + "description": "Filter by domain", + "name": "domain", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/internal_admin_cpanel.EmailAccount" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + }, + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Creates a new email account", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin - cPanel" + ], + "summary": "Create Email Account", + "parameters": [ + { + "description": "Email details", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/internal_admin_cpanel.CreateEmailRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/admin/cpanel/emails/{email}": { + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Deletes an email account", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin - cPanel" + ], + "summary": "Delete Email Account", + "parameters": [ + { + "type": "string", + "description": "Email address", + "name": "email", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/admin/cpanel/emails/{email}/password": { + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Changes the password for an email account", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin - cPanel" + ], + "summary": "Change Email Password", + "parameters": [ + { + "type": "string", + "description": "Email address", + "name": "email", + "in": "path", + "required": true + }, + { + "description": "New password", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/internal_admin_cpanel.ChangePasswordRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/admin/cpanel/emails/{email}/quota": { + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Updates the disk quota for an email account", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Admin - cPanel" + ], + "summary": "Update Email Quota", + "parameters": [ + { + "type": "string", + "description": "Email address", + "name": "email", + "in": "path", + "required": true + }, + { + "description": "New quota in MB", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/internal_admin_cpanel.UpdateQuotaRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": { + "type": "string" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/auth/login": { + "post": { + "description": "Authenticates a user by email and password. Returns JWT and user info.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Auth" + ], + "summary": "User Login", + "parameters": [ + { + "description": "Login Credentials", + "name": "login", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.LoginRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.AuthResponse" + } + }, + "400": { + "description": "Invalid Request", + "schema": { + "type": "string" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/companies": { + "get": { + "description": "Returns a list of all companies.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Companies" + ], + "summary": "List Companies", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.CompanyResponse" + } + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + }, + "post": { + "description": "Registers a new company and creates an initial admin user.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Companies" + ], + "summary": "Create Company (Tenant)", + "parameters": [ + { + "description": "Company Details", + "name": "company", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.CreateCompanyRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.CompanyResponse" + } + }, + "400": { + "description": "Invalid Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/storage/download-url": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Generate a pre-signed URL to download a private file from S3", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Storage" + ], + "summary": "Generate download URL", + "parameters": [ + { + "description": "Download request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/internal_handlers.DownloadURLRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/internal_handlers.DownloadURLResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/storage/files": { + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Delete a stored file by key", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Storage" + ], + "summary": "Delete file", + "parameters": [ + { + "type": "string", + "description": "File key", + "name": "key", + "in": "query", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/storage/upload-url": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Generate a pre-signed URL to upload a file to S3", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Storage" + ], + "summary": "Generate upload URL", + "parameters": [ + { + "description": "Upload request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/internal_handlers.UploadURLRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/internal_handlers.UploadURLResponse" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/users": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Returns a list of users belonging to the authenticated tenant.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "List Users", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.UserResponse" + } + } + }, + "403": { + "description": "Forbidden", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + }, + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Creates a new user under the current tenant. Requires Admin role.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Create User", + "parameters": [ + { + "description": "User Details", + "name": "user", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.CreateUserRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.UserResponse" + } + }, + "400": { + "description": "Invalid Request", + "schema": { + "type": "string" + } + }, + "403": { + "description": "Forbidden", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/api/v1/users/{id}": { + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "description": "Deletes a user by ID. Must belong to the same tenant.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Delete User", + "parameters": [ + { + "type": "string", + "description": "User ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "User deleted", + "schema": { + "type": "string" + } + }, + "403": { + "description": "Forbidden", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/applications": { + "get": { + "description": "List all applications for a job", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Applications" + ], + "summary": "List Applications", + "parameters": [ + { + "type": "integer", + "description": "Filter applications by job ID", + "name": "jobId", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application" + } + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + }, + "post": { + "description": "Submit a new job application for a posting", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Applications" + ], + "summary": "Create Application", + "parameters": [ + { + "description": "Application data", + "name": "application", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.CreateApplicationRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, + "/applications/{id}": { + "get": { + "description": "Retrieve a job application by its ID", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Applications" + ], + "summary": "Get Application", + "parameters": [ + { + "type": "integer", + "description": "Application ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "404": { + "description": "Not Found", + "schema": { + "type": "string" + } + } + } + } + }, + "/applications/{id}/status": { + "put": { + "description": "Update the status of a job application", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Applications" + ], + "summary": "Update Application Status", + "parameters": [ + { + "type": "integer", + "description": "Application ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Status update", + "name": "body", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.UpdateApplicationStatusRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "string" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "type": "string" + } + } + } + } + }, "/jobs": { "get": { "description": "Get a paginated list of job postings with optional filters", @@ -52,7 +1152,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/dto.PaginatedResponse" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.PaginatedResponse" } }, "500": { @@ -82,7 +1182,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.CreateJobRequest" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.CreateJobRequest" } } ], @@ -90,7 +1190,7 @@ "201": { "description": "Created", "schema": { - "$ref": "#/definitions/models.Job" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Job" } }, "400": { @@ -134,7 +1234,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.Job" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Job" } }, "400": { @@ -177,7 +1277,7 @@ "in": "body", "required": true, "schema": { - "$ref": "#/definitions/dto.UpdateJobRequest" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.UpdateJobRequest" } } ], @@ -185,7 +1285,7 @@ "200": { "description": "OK", "schema": { - "$ref": "#/definitions/models.Job" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Job" } }, "400": { @@ -244,7 +1344,149 @@ } }, "definitions": { - "dto.CreateJobRequest": { + "github_com_rede5_gohorsejobs_backend_internal_core_dto.AuthResponse": { + "type": "object", + "properties": { + "token": { + "type": "string" + }, + "user": { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.UserResponse" + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_core_dto.CompanyResponse": { + "type": "object", + "properties": { + "created_at": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "status": { + "type": "string" + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_core_dto.CreateCompanyRequest": { + "type": "object", + "properties": { + "admin_email": { + "type": "string" + }, + "contact": { + "type": "string" + }, + "document": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_core_dto.CreateUserRequest": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "name": { + "type": "string" + }, + "password": { + "type": "string" + }, + "roles": { + "description": "e.g. [\"RECRUITER\"]", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_core_dto.LoginRequest": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "password": { + "type": "string" + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_core_dto.UserResponse": { + "type": "object", + "properties": { + "created_at": { + "type": "string" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "roles": { + "type": "array", + "items": { + "type": "string" + } + }, + "status": { + "type": "string" + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_dto.CreateApplicationRequest": { + "type": "object", + "required": [ + "jobId" + ], + "properties": { + "documents": { + "type": "object", + "additionalProperties": true + }, + "email": { + "type": "string" + }, + "jobId": { + "type": "integer" + }, + "lineId": { + "type": "string" + }, + "message": { + "type": "string" + }, + "name": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "resumeUrl": { + "type": "string" + }, + "userId": { + "type": "integer" + }, + "whatsapp": { + "type": "string" + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_dto.CreateJobRequest": { "type": "object", "required": [ "companyId", @@ -323,16 +1565,16 @@ } } }, - "dto.PaginatedResponse": { + "github_com_rede5_gohorsejobs_backend_internal_dto.PaginatedResponse": { "type": "object", "properties": { "data": {}, "pagination": { - "$ref": "#/definitions/dto.Pagination" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.Pagination" } } }, - "dto.Pagination": { + "github_com_rede5_gohorsejobs_backend_internal_dto.Pagination": { "type": "object", "properties": { "limit": { @@ -346,7 +1588,28 @@ } } }, - "dto.UpdateJobRequest": { + "github_com_rede5_gohorsejobs_backend_internal_dto.UpdateApplicationStatusRequest": { + "type": "object", + "required": [ + "status" + ], + "properties": { + "notes": { + "type": "string" + }, + "status": { + "type": "string", + "enum": [ + "pending", + "reviewed", + "shortlisted", + "rejected", + "hired" + ] + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_dto.UpdateJobRequest": { "type": "object", "properties": { "benefits": { @@ -417,15 +1680,75 @@ } } }, - "models.JSONMap": { + "github_com_rede5_gohorsejobs_backend_internal_models.Application": { + "type": "object", + "properties": { + "createdAt": { + "description": "Metadata", + "type": "string" + }, + "documents": { + "description": "Array of {type, url}", + "allOf": [ + { + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.JSONMap" + } + ] + }, + "email": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "jobId": { + "type": "integer" + }, + "lineId": { + "type": "string" + }, + "message": { + "description": "Application Content", + "type": "string" + }, + "name": { + "description": "Applicant Info (for guest applications)", + "type": "string" + }, + "notes": { + "type": "string" + }, + "phone": { + "type": "string" + }, + "resumeUrl": { + "type": "string" + }, + "status": { + "description": "Status \u0026 Notes", + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "userId": { + "description": "NULL for guest applications", + "type": "integer" + }, + "whatsapp": { + "type": "string" + } + } + }, + "github_com_rede5_gohorsejobs_backend_internal_models.JSONMap": { "type": "object", "additionalProperties": true }, - "models.Job": { + "github_com_rede5_gohorsejobs_backend_internal_models.Job": { "type": "object", "properties": { "benefits": { - "$ref": "#/definitions/models.JSONMap" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.JSONMap" }, "cityId": { "type": "integer" @@ -469,7 +1792,7 @@ "description": "Requirements \u0026 Benefits (JSONB arrays)", "allOf": [ { - "$ref": "#/definitions/models.JSONMap" + "$ref": "#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.JSONMap" } ] }, @@ -503,6 +1826,203 @@ "type": "string" } } + }, + "internal_admin_cloudflare.Error": { + "type": "object", + "properties": { + "code": { + "type": "integer" + }, + "message": { + "type": "string" + } + } + }, + "internal_admin_cloudflare.PurgeHostsRequest": { + "type": "object", + "properties": { + "hosts": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "internal_admin_cloudflare.PurgeResponse": { + "type": "object", + "properties": { + "errors": { + "type": "array", + "items": { + "$ref": "#/definitions/internal_admin_cloudflare.Error" + } + }, + "messages": { + "type": "array", + "items": { + "type": "string" + } + }, + "result": { + "type": "object", + "properties": { + "id": { + "type": "string" + } + } + }, + "success": { + "type": "boolean" + } + } + }, + "internal_admin_cloudflare.PurgeTagsRequest": { + "type": "object", + "properties": { + "tags": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "internal_admin_cloudflare.PurgeURLsRequest": { + "type": "object", + "properties": { + "urls": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "internal_admin_cloudflare.Zone": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "status": { + "type": "string" + } + } + }, + "internal_admin_cpanel.ChangePasswordRequest": { + "type": "object", + "properties": { + "password": { + "type": "string" + } + } + }, + "internal_admin_cpanel.CreateEmailRequest": { + "type": "object", + "properties": { + "email": { + "type": "string" + }, + "password": { + "type": "string" + }, + "quota": { + "description": "MB, 0 = unlimited", + "type": "integer" + } + } + }, + "internal_admin_cpanel.EmailAccount": { + "type": "object", + "properties": { + "diskquota": { + "type": "string" + }, + "diskused": { + "type": "string" + }, + "domain": { + "type": "string" + }, + "email": { + "type": "string" + }, + "humandiskquota": { + "type": "string" + }, + "humandiskused": { + "type": "string" + }, + "login": { + "type": "string" + } + } + }, + "internal_admin_cpanel.UpdateQuotaRequest": { + "type": "object", + "properties": { + "quota": { + "description": "MB", + "type": "integer" + } + } + }, + "internal_handlers.DownloadURLRequest": { + "type": "object", + "properties": { + "key": { + "type": "string" + } + } + }, + "internal_handlers.DownloadURLResponse": { + "type": "object", + "properties": { + "downloadUrl": { + "type": "string" + }, + "expiresIn": { + "description": "seconds", + "type": "integer" + } + } + }, + "internal_handlers.UploadURLRequest": { + "type": "object", + "properties": { + "contentType": { + "type": "string" + }, + "filename": { + "type": "string" + }, + "folder": { + "description": "Optional: logos, resumes, documents", + "type": "string" + } + } + }, + "internal_handlers.UploadURLResponse": { + "type": "object", + "properties": { + "expiresIn": { + "description": "seconds", + "type": "integer" + }, + "key": { + "type": "string" + }, + "publicUrl": { + "type": "string" + }, + "uploadUrl": { + "type": "string" + } + } } } } \ No newline at end of file diff --git a/backend/docs/swagger.yaml b/backend/docs/swagger.yaml index ca46362..acb8dee 100644 --- a/backend/docs/swagger.yaml +++ b/backend/docs/swagger.yaml @@ -1,6 +1,99 @@ basePath: / definitions: - dto.CreateJobRequest: + github_com_rede5_gohorsejobs_backend_internal_core_dto.AuthResponse: + properties: + token: + type: string + user: + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.UserResponse' + type: object + github_com_rede5_gohorsejobs_backend_internal_core_dto.CompanyResponse: + properties: + created_at: + type: string + id: + type: string + name: + type: string + status: + type: string + type: object + github_com_rede5_gohorsejobs_backend_internal_core_dto.CreateCompanyRequest: + properties: + admin_email: + type: string + contact: + type: string + document: + type: string + name: + type: string + type: object + github_com_rede5_gohorsejobs_backend_internal_core_dto.CreateUserRequest: + properties: + email: + type: string + name: + type: string + password: + type: string + roles: + description: e.g. ["RECRUITER"] + items: + type: string + type: array + type: object + github_com_rede5_gohorsejobs_backend_internal_core_dto.LoginRequest: + properties: + email: + type: string + password: + type: string + type: object + github_com_rede5_gohorsejobs_backend_internal_core_dto.UserResponse: + properties: + created_at: + type: string + email: + type: string + id: + type: string + name: + type: string + roles: + items: + type: string + type: array + status: + type: string + type: object + github_com_rede5_gohorsejobs_backend_internal_dto.CreateApplicationRequest: + properties: + documents: + additionalProperties: true + type: object + email: + type: string + jobId: + type: integer + lineId: + type: string + message: + type: string + name: + type: string + phone: + type: string + resumeUrl: + type: string + userId: + type: integer + whatsapp: + type: string + required: + - jobId + type: object + github_com_rede5_gohorsejobs_backend_internal_dto.CreateJobRequest: properties: benefits: additionalProperties: true @@ -57,13 +150,13 @@ definitions: - description - title type: object - dto.PaginatedResponse: + github_com_rede5_gohorsejobs_backend_internal_dto.PaginatedResponse: properties: data: {} pagination: - $ref: '#/definitions/dto.Pagination' + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.Pagination' type: object - dto.Pagination: + github_com_rede5_gohorsejobs_backend_internal_dto.Pagination: properties: limit: type: integer @@ -72,7 +165,22 @@ definitions: total: type: integer type: object - dto.UpdateJobRequest: + github_com_rede5_gohorsejobs_backend_internal_dto.UpdateApplicationStatusRequest: + properties: + notes: + type: string + status: + enum: + - pending + - reviewed + - shortlisted + - rejected + - hired + type: string + required: + - status + type: object + github_com_rede5_gohorsejobs_backend_internal_dto.UpdateJobRequest: properties: benefits: additionalProperties: true @@ -123,13 +231,53 @@ definitions: workingHours: type: string type: object - models.JSONMap: + github_com_rede5_gohorsejobs_backend_internal_models.Application: + properties: + createdAt: + description: Metadata + type: string + documents: + allOf: + - $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.JSONMap' + description: Array of {type, url} + email: + type: string + id: + type: integer + jobId: + type: integer + lineId: + type: string + message: + description: Application Content + type: string + name: + description: Applicant Info (for guest applications) + type: string + notes: + type: string + phone: + type: string + resumeUrl: + type: string + status: + description: Status & Notes + type: string + updatedAt: + type: string + userId: + description: NULL for guest applications + type: integer + whatsapp: + type: string + type: object + github_com_rede5_gohorsejobs_backend_internal_models.JSONMap: additionalProperties: true type: object - models.Job: + github_com_rede5_gohorsejobs_backend_internal_models.Job: properties: benefits: - $ref: '#/definitions/models.JSONMap' + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.JSONMap' cityId: type: integer companyId: @@ -159,7 +307,7 @@ definitions: type: integer requirements: allOf: - - $ref: '#/definitions/models.JSONMap' + - $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.JSONMap' description: Requirements & Benefits (JSONB arrays) salaryMax: type: number @@ -183,6 +331,134 @@ definitions: workingHours: type: string type: object + internal_admin_cloudflare.Error: + properties: + code: + type: integer + message: + type: string + type: object + internal_admin_cloudflare.PurgeHostsRequest: + properties: + hosts: + items: + type: string + type: array + type: object + internal_admin_cloudflare.PurgeResponse: + properties: + errors: + items: + $ref: '#/definitions/internal_admin_cloudflare.Error' + type: array + messages: + items: + type: string + type: array + result: + properties: + id: + type: string + type: object + success: + type: boolean + type: object + internal_admin_cloudflare.PurgeTagsRequest: + properties: + tags: + items: + type: string + type: array + type: object + internal_admin_cloudflare.PurgeURLsRequest: + properties: + urls: + items: + type: string + type: array + type: object + internal_admin_cloudflare.Zone: + properties: + id: + type: string + name: + type: string + status: + type: string + type: object + internal_admin_cpanel.ChangePasswordRequest: + properties: + password: + type: string + type: object + internal_admin_cpanel.CreateEmailRequest: + properties: + email: + type: string + password: + type: string + quota: + description: MB, 0 = unlimited + type: integer + type: object + internal_admin_cpanel.EmailAccount: + properties: + diskquota: + type: string + diskused: + type: string + domain: + type: string + email: + type: string + humandiskquota: + type: string + humandiskused: + type: string + login: + type: string + type: object + internal_admin_cpanel.UpdateQuotaRequest: + properties: + quota: + description: MB + type: integer + type: object + internal_handlers.DownloadURLRequest: + properties: + key: + type: string + type: object + internal_handlers.DownloadURLResponse: + properties: + downloadUrl: + type: string + expiresIn: + description: seconds + type: integer + type: object + internal_handlers.UploadURLRequest: + properties: + contentType: + type: string + filename: + type: string + folder: + description: 'Optional: logos, resumes, documents' + type: string + type: object + internal_handlers.UploadURLResponse: + properties: + expiresIn: + description: seconds + type: integer + key: + type: string + publicUrl: + type: string + uploadUrl: + type: string + type: object host: localhost:8080 info: contact: {} @@ -190,6 +466,709 @@ info: title: GoHorseJobs API version: "1.0" paths: + /api/v1/admin/cloudflare/cache/purge-all: + post: + consumes: + - application/json + description: Purges all cached content for the configured zone + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/internal_admin_cloudflare.PurgeResponse' + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Purge All Cache + tags: + - Admin - Cloudflare + /api/v1/admin/cloudflare/cache/purge-hosts: + post: + consumes: + - application/json + description: Purges content by hostnames + parameters: + - description: Hosts to purge + in: body + name: body + required: true + schema: + $ref: '#/definitions/internal_admin_cloudflare.PurgeHostsRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/internal_admin_cloudflare.PurgeResponse' + "400": + description: Bad Request + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Purge Cache by Hosts + tags: + - Admin - Cloudflare + /api/v1/admin/cloudflare/cache/purge-tags: + post: + consumes: + - application/json + description: Purges content by cache tags (Enterprise only) + parameters: + - description: Tags to purge + in: body + name: body + required: true + schema: + $ref: '#/definitions/internal_admin_cloudflare.PurgeTagsRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/internal_admin_cloudflare.PurgeResponse' + "400": + description: Bad Request + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Purge Cache by Tags + tags: + - Admin - Cloudflare + /api/v1/admin/cloudflare/cache/purge-urls: + post: + consumes: + - application/json + description: Purges specific URLs from cache + parameters: + - description: URLs to purge + in: body + name: body + required: true + schema: + $ref: '#/definitions/internal_admin_cloudflare.PurgeURLsRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/internal_admin_cloudflare.PurgeResponse' + "400": + description: Bad Request + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Purge Cache by URLs + tags: + - Admin - Cloudflare + /api/v1/admin/cloudflare/zones: + get: + consumes: + - application/json + description: Returns all zones associated with the Cloudflare account + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/internal_admin_cloudflare.Zone' + type: array + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: List Cloudflare Zones + tags: + - Admin - Cloudflare + /api/v1/admin/cpanel/emails: + get: + consumes: + - application/json + description: Returns all email accounts for the cPanel account + parameters: + - description: Filter by domain + in: query + name: domain + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/internal_admin_cpanel.EmailAccount' + type: array + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: List Email Accounts + tags: + - Admin - cPanel + post: + consumes: + - application/json + description: Creates a new email account + parameters: + - description: Email details + in: body + name: body + required: true + schema: + $ref: '#/definitions/internal_admin_cpanel.CreateEmailRequest' + produces: + - application/json + responses: + "201": + description: Created + schema: + additionalProperties: + type: string + type: object + "400": + description: Bad Request + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Create Email Account + tags: + - Admin - cPanel + /api/v1/admin/cpanel/emails/{email}: + delete: + consumes: + - application/json + description: Deletes an email account + parameters: + - description: Email address + in: path + name: email + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: + type: string + type: object + "400": + description: Bad Request + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Delete Email Account + tags: + - Admin - cPanel + /api/v1/admin/cpanel/emails/{email}/password: + put: + consumes: + - application/json + description: Changes the password for an email account + parameters: + - description: Email address + in: path + name: email + required: true + type: string + - description: New password + in: body + name: body + required: true + schema: + $ref: '#/definitions/internal_admin_cpanel.ChangePasswordRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: + type: string + type: object + "400": + description: Bad Request + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Change Email Password + tags: + - Admin - cPanel + /api/v1/admin/cpanel/emails/{email}/quota: + put: + consumes: + - application/json + description: Updates the disk quota for an email account + parameters: + - description: Email address + in: path + name: email + required: true + type: string + - description: New quota in MB + in: body + name: body + required: true + schema: + $ref: '#/definitions/internal_admin_cpanel.UpdateQuotaRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: + type: string + type: object + "400": + description: Bad Request + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Update Email Quota + tags: + - Admin - cPanel + /api/v1/auth/login: + post: + consumes: + - application/json + description: Authenticates a user by email and password. Returns JWT and user + info. + parameters: + - description: Login Credentials + in: body + name: login + required: true + schema: + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.LoginRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.AuthResponse' + "400": + description: Invalid Request + schema: + type: string + "401": + description: Unauthorized + schema: + type: string + summary: User Login + tags: + - Auth + /api/v1/companies: + get: + consumes: + - application/json + description: Returns a list of all companies. + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.CompanyResponse' + type: array + "500": + description: Internal Server Error + schema: + type: string + summary: List Companies + tags: + - Companies + post: + consumes: + - application/json + description: Registers a new company and creates an initial admin user. + parameters: + - description: Company Details + in: body + name: company + required: true + schema: + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.CreateCompanyRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.CompanyResponse' + "400": + description: Invalid Request + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + summary: Create Company (Tenant) + tags: + - Companies + /api/v1/storage/download-url: + post: + consumes: + - application/json + description: Generate a pre-signed URL to download a private file from S3 + parameters: + - description: Download request + in: body + name: request + required: true + schema: + $ref: '#/definitions/internal_handlers.DownloadURLRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/internal_handlers.DownloadURLResponse' + "400": + description: Bad Request + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Generate download URL + tags: + - Storage + /api/v1/storage/files: + delete: + consumes: + - application/json + description: Delete a stored file by key + parameters: + - description: File key + in: query + name: key + required: true + type: string + produces: + - application/json + responses: + "204": + description: No Content + "400": + description: Bad Request + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Delete file + tags: + - Storage + /api/v1/storage/upload-url: + post: + consumes: + - application/json + description: Generate a pre-signed URL to upload a file to S3 + parameters: + - description: Upload request + in: body + name: request + required: true + schema: + $ref: '#/definitions/internal_handlers.UploadURLRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/internal_handlers.UploadURLResponse' + "400": + description: Bad Request + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Generate upload URL + tags: + - Storage + /api/v1/users: + get: + consumes: + - application/json + description: Returns a list of users belonging to the authenticated tenant. + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.UserResponse' + type: array + "403": + description: Forbidden + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: List Users + tags: + - Users + post: + consumes: + - application/json + description: Creates a new user under the current tenant. Requires Admin role. + parameters: + - description: User Details + in: body + name: user + required: true + schema: + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.CreateUserRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_core_dto.UserResponse' + "400": + description: Invalid Request + schema: + type: string + "403": + description: Forbidden + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Create User + tags: + - Users + /api/v1/users/{id}: + delete: + consumes: + - application/json + description: Deletes a user by ID. Must belong to the same tenant. + parameters: + - description: User ID + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: User deleted + schema: + type: string + "403": + description: Forbidden + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + security: + - BearerAuth: [] + summary: Delete User + tags: + - Users + /applications: + get: + consumes: + - application/json + description: List all applications for a job + parameters: + - description: Filter applications by job ID + in: query + name: jobId + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + items: + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application' + type: array + "400": + description: Bad Request + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + summary: List Applications + tags: + - Applications + post: + consumes: + - application/json + description: Submit a new job application for a posting + parameters: + - description: Application data + in: body + name: application + required: true + schema: + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.CreateApplicationRequest' + produces: + - application/json + responses: + "201": + description: Created + schema: + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application' + "400": + description: Bad Request + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + summary: Create Application + tags: + - Applications + /applications/{id}: + get: + consumes: + - application/json + description: Retrieve a job application by its ID + parameters: + - description: Application ID + in: path + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application' + "400": + description: Bad Request + schema: + type: string + "404": + description: Not Found + schema: + type: string + summary: Get Application + tags: + - Applications + /applications/{id}/status: + put: + consumes: + - application/json + description: Update the status of a job application + parameters: + - description: Application ID + in: path + name: id + required: true + type: integer + - description: Status update + in: body + name: body + required: true + schema: + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.UpdateApplicationStatusRequest' + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Application' + "400": + description: Bad Request + schema: + type: string + "500": + description: Internal Server Error + schema: + type: string + summary: Update Application Status + tags: + - Applications /jobs: get: consumes: @@ -218,7 +1197,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/dto.PaginatedResponse' + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.PaginatedResponse' "500": description: Internal Server Error schema: @@ -236,14 +1215,14 @@ paths: name: job required: true schema: - $ref: '#/definitions/dto.CreateJobRequest' + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.CreateJobRequest' produces: - application/json responses: "201": description: Created schema: - $ref: '#/definitions/models.Job' + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Job' "400": description: Bad Request schema: @@ -298,7 +1277,7 @@ paths: "200": description: OK schema: - $ref: '#/definitions/models.Job' + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Job' "400": description: Bad Request schema: @@ -325,14 +1304,14 @@ paths: name: job required: true schema: - $ref: '#/definitions/dto.UpdateJobRequest' + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_dto.UpdateJobRequest' produces: - application/json responses: "200": description: OK schema: - $ref: '#/definitions/models.Job' + $ref: '#/definitions/github_com_rede5_gohorsejobs_backend_internal_models.Job' "400": description: Bad Request schema: diff --git a/backend/internal/handlers/application_handler.go b/backend/internal/handlers/application_handler.go index da6dd59..10f8c73 100644 --- a/backend/internal/handlers/application_handler.go +++ b/backend/internal/handlers/application_handler.go @@ -6,6 +6,7 @@ import ( "strconv" "github.com/rede5/gohorsejobs/backend/internal/dto" + "github.com/rede5/gohorsejobs/backend/internal/models" "github.com/rede5/gohorsejobs/backend/internal/services" ) @@ -17,6 +18,17 @@ func NewApplicationHandler(service *services.ApplicationService) *ApplicationHan return &ApplicationHandler{Service: service} } +// CreateApplication submits a new job application +// @Summary Create Application +// @Description Submit a new job application for a posting +// @Tags Applications +// @Accept json +// @Produce json +// @Param application body dto.CreateApplicationRequest true "Application data" +// @Success 201 {object} models.Application +// @Failure 400 {string} string "Bad Request" +// @Failure 500 {string} string "Internal Server Error" +// @Router /applications [post] func (h *ApplicationHandler) CreateApplication(w http.ResponseWriter, r *http.Request) { var req dto.CreateApplicationRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { @@ -35,6 +47,17 @@ func (h *ApplicationHandler) CreateApplication(w http.ResponseWriter, r *http.Re json.NewEncoder(w).Encode(app) } +// GetApplications lists applications for a job +// @Summary List Applications +// @Description List all applications for a job +// @Tags Applications +// @Accept json +// @Produce json +// @Param jobId query int true "Filter applications by job ID" +// @Success 200 {array} models.Application +// @Failure 400 {string} string "Bad Request" +// @Failure 500 {string} string "Internal Server Error" +// @Router /applications [get] func (h *ApplicationHandler) GetApplications(w http.ResponseWriter, r *http.Request) { // For now, simple get by Job ID query param jobIDStr := r.URL.Query().Get("jobId") @@ -58,6 +81,17 @@ func (h *ApplicationHandler) GetApplications(w http.ResponseWriter, r *http.Requ json.NewEncoder(w).Encode(apps) } +// GetApplicationByID returns a single application by ID +// @Summary Get Application +// @Description Retrieve a job application by its ID +// @Tags Applications +// @Accept json +// @Produce json +// @Param id path int true "Application ID" +// @Success 200 {object} models.Application +// @Failure 400 {string} string "Bad Request" +// @Failure 404 {string} string "Not Found" +// @Router /applications/{id} [get] func (h *ApplicationHandler) GetApplicationByID(w http.ResponseWriter, r *http.Request) { idStr := r.PathValue("id") id, err := strconv.Atoi(idStr) @@ -76,6 +110,18 @@ func (h *ApplicationHandler) GetApplicationByID(w http.ResponseWriter, r *http.R json.NewEncoder(w).Encode(app) } +// UpdateApplicationStatus updates the status of an application +// @Summary Update Application Status +// @Description Update the status of a job application +// @Tags Applications +// @Accept json +// @Produce json +// @Param id path int true "Application ID" +// @Param body body dto.UpdateApplicationStatusRequest true "Status update" +// @Success 200 {object} models.Application +// @Failure 400 {string} string "Bad Request" +// @Failure 500 {string} string "Internal Server Error" +// @Router /applications/{id}/status [put] func (h *ApplicationHandler) UpdateApplicationStatus(w http.ResponseWriter, r *http.Request) { idStr := r.PathValue("id") id, err := strconv.Atoi(idStr) diff --git a/backend/internal/handlers/storage_handler.go b/backend/internal/handlers/storage_handler.go index 3572d13..a4d2431 100644 --- a/backend/internal/handlers/storage_handler.go +++ b/backend/internal/handlers/storage_handler.go @@ -48,7 +48,18 @@ type DownloadURLResponse struct { ExpiresIn int `json:"expiresIn"` // seconds } -// GenerateUploadURL handles POST /api/v1/storage/upload-url +// GenerateUploadURL creates a pre-signed S3 URL for uploads +// @Summary Generate upload URL +// @Description Generate a pre-signed URL to upload a file to S3 +// @Tags Storage +// @Accept json +// @Produce json +// @Security BearerAuth +// @Param request body UploadURLRequest true "Upload request" +// @Success 200 {object} UploadURLResponse +// @Failure 400 {string} string "Bad Request" +// @Failure 500 {string} string "Internal Server Error" +// @Router /api/v1/storage/upload-url [post] func (h *StorageHandler) GenerateUploadURL(w http.ResponseWriter, r *http.Request) { var req UploadURLRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { @@ -123,7 +134,18 @@ func (h *StorageHandler) GenerateUploadURL(w http.ResponseWriter, r *http.Reques json.NewEncoder(w).Encode(response) } -// GenerateDownloadURL handles POST /api/v1/storage/download-url +// GenerateDownloadURL creates a pre-signed S3 URL for downloads +// @Summary Generate download URL +// @Description Generate a pre-signed URL to download a private file from S3 +// @Tags Storage +// @Accept json +// @Produce json +// @Security BearerAuth +// @Param request body DownloadURLRequest true "Download request" +// @Success 200 {object} DownloadURLResponse +// @Failure 400 {string} string "Bad Request" +// @Failure 500 {string} string "Internal Server Error" +// @Router /api/v1/storage/download-url [post] func (h *StorageHandler) GenerateDownloadURL(w http.ResponseWriter, r *http.Request) { var req DownloadURLRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { @@ -153,7 +175,18 @@ func (h *StorageHandler) GenerateDownloadURL(w http.ResponseWriter, r *http.Requ json.NewEncoder(w).Encode(response) } -// DeleteFile handles DELETE /api/v1/storage/files +// DeleteFile removes an object from S3 +// @Summary Delete file +// @Description Delete a stored file by key +// @Tags Storage +// @Accept json +// @Produce json +// @Security BearerAuth +// @Param key query string true "File key" +// @Success 204 +// @Failure 400 {string} string "Bad Request" +// @Failure 500 {string} string "Internal Server Error" +// @Router /api/v1/storage/files [delete] func (h *StorageHandler) DeleteFile(w http.ResponseWriter, r *http.Request) { key := r.URL.Query().Get("key") if key == "" {