from flask import Blueprint, jsonify api_openapi_bp = Blueprint('api_openapi', __name__, url_prefix='/api/v1') OPENAPI_SPEC = { "openapi": "3.0.3", "info": { "title": "Edu-Space REST API", "description": "Enterprise Academic & Physical Space Management REST API with JWT Authentication and Role-Based Access Control.", "version": "1.0.0" }, "servers": [ { "url": "http://127.0.0.1:5000", "description": "Local Flask Backend Server" } ], "components": { "securitySchemes": { "bearerAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT" } }, "schemas": { "LoginRequest": { "type": "object", "required": ["email", "password"], "properties": { "email": { "type": "string", "format": "email", "example": "admin@eduspace.com" }, "password": { "type": "string", "format": "password", "example": "Admin123!" } } }, "LoginResponse": { "type": "object", "properties": { "access_token": {"type": "string"}, "refresh_token": {"type": "string"}, "token_type": {"type": "string", "example": "Bearer"}, "expires_in": {"type": "integer"}, "user": {"type": "object"} } }, "ErrorResponse": { "type": "object", "properties": { "error": {"type": "string"}, "message": {"type": "string"} } }, "UserResponse": { "type": "object", "properties": { "id": {"type": "integer"}, "email": {"type": "string"}, "first_name": {"type": "string"}, "last_name": {"type": "string"}, "role": {"type": "string"}, "is_active": {"type": "boolean"} } }, "SubjectResponse": { "type": "object", "properties": { "id": {"type": "integer"}, "name": {"type": "string"}, "code": {"type": "string"}, "career": {"type": "string"} } }, "ClassroomResponse": { "type": "object", "properties": { "id": {"type": "integer"}, "name": {"type": "string"}, "capacity": {"type": "integer"}, "building": {"type": "string"}, "floor": {"type": "string"} } } } }, "paths": { "/api/v1/auth/login": { "post": { "summary": "Authenticate user and issue JWT tokens", "tags": ["Authentication"], "requestBody": { "required": True, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LoginRequest" } } } }, "responses": { "200": { "description": "Authentication successful", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/LoginResponse" } } } }, "400": { "description": "Validation error", "content": { "application/json": { "schema": {"$ref": "#/components/schemas/ErrorResponse"} } } }, "401": { "description": "Unauthorized / Bad credentials", "content": { "application/json": { "schema": {"$ref": "#/components/schemas/ErrorResponse"} } } } } } }, "/api/v1/auth/me": { "get": { "summary": "Get authenticated user profile", "tags": ["Authentication"], "security": [{"bearerAuth": []}], "responses": { "200": { "description": "Current user profile", "content": { "application/json": { "schema": {"$ref": "#/components/schemas/UserResponse"} } } }, "401": { "description": "Missing or invalid token", "content": { "application/json": { "schema": {"$ref": "#/components/schemas/ErrorResponse"} } } } } } }, "/api/v1/classrooms": { "get": { "summary": "List all physical classrooms and facilities", "tags": ["Classrooms"], "security": [{"bearerAuth": []}], "responses": { "200": { "description": "List of classrooms", "content": { "application/json": { "schema": { "type": "array", "items": {"$ref": "#/components/schemas/ClassroomResponse"} } } } } } } }, "/api/v1/admin/users": { "get": { "summary": "List all users (Admin only)", "tags": ["Admin - Users"], "security": [{"bearerAuth": []}], "responses": { "200": { "description": "List of users", "content": { "application/json": { "schema": { "type": "array", "items": {"$ref": "#/components/schemas/UserResponse"} } } } }, "403": { "description": "Forbidden - Requires admin role" } } } }, "/api/v1/admin/subjects": { "get": { "summary": "List all academic subjects (Admin only)", "tags": ["Admin - Academic"], "security": [{"bearerAuth": []}], "responses": { "200": { "description": "List of subjects", "content": { "application/json": { "schema": { "type": "array", "items": {"$ref": "#/components/schemas/SubjectResponse"} } } } } } } }, "/api/v1/openapi.json": { "get": { "summary": "Get OpenAPI 3.0.3 specification JSON", "tags": ["Documentation"], "responses": { "200": { "description": "OpenAPI Specification" } } } } } } @api_openapi_bp.route('/openapi.json', methods=['GET']) def get_openapi_spec(): """Serves the OpenAPI 3.0 specification for Schemathesis / DAST and Swagger UI.""" return jsonify(OPENAPI_SPEC)