1+ import os
12from flask import Blueprint , current_app , json , Response
23from config .auth_config import AuthMethod
34
45docs_bp = Blueprint ("docs" , __name__ )
56
7+ def load_json_file (filename ):
8+ """Load and parse a JSON file."""
9+ try :
10+ with open (filename , 'r' ) as f :
11+ return json .load (f )
12+ except (FileNotFoundError , json .JSONDecodeError ):
13+ return {}
14+
615@docs_bp .route ("" , methods = ["GET" ])
716def api_docs ():
817 """Provide comprehensive API documentation."""
918 docs = {}
1019
20+ # Load route documentation in specific order
21+ route_files = ['todos.json' , 'notes.json' ] # Define order explicitly
22+ docs_dir = os .path .join (current_app .root_path , '..' , 'docs' , 'routes' )
23+
24+ for filename in route_files :
25+ route_docs = load_json_file (os .path .join (docs_dir , filename ))
26+ docs .update (route_docs )
27+
28+ # Load authentication documentation
1129 auth_docs = _get_auth_docs ()
1230 if auth_docs :
1331 docs ["authentication" ] = auth_docs
14-
15- docs .update ({
16- "/todos" : {
17- "GET" : {
18- "description" : "Fetch all TODO items with optional filtering and pagination." ,
19- "query_params" : {
20- "done" : "Filter by completion status (true/false)." ,
21- "title" : "Filter by TODO item title prefix." ,
22- "page" : "Page number for pagination (optional, starts at 1)." ,
23- "limit" : "Number of items per page (optional)."
24- },
25- "responses" : {
26- "200" : "List of todo items"
27- }
28- },
29- "POST" : {
30- "description" : "Add a new TODO item." ,
31- "body_params" : {
32- "title" : "The TODO item title (required)." ,
33- "done" : "Completion status (optional, default: false)." ,
34- "description" : "Detailed TODO item description (optional)."
35- },
36- "responses" : {
37- "201" : "Created todo item" ,
38- "400" : "Invalid request (missing title)"
39- }
40- }
41- },
42- "/todos/<int:todo_id>" : {
43- "GET" : {
44- "description" : "Fetch a single TODO item by its ID." ,
45- "responses" : {
46- "200" : "Todo item" ,
47- "404" : "Todo not found"
48- }
49- },
50- "PUT" : {
51- "description" : "Replace an existing TODO item by its ID (all fields required)." ,
52- "body_params" : {
53- "title" : "The TODO item title (required)." ,
54- "done" : "Completion status (required)." ,
55- "description" : "Detailed TODO item description (required)."
56- },
57- "responses" : {
58- "200" : "Updated todo item" ,
59- "400" : "Invalid request (missing required fields)" ,
60- "404" : "Todo not found"
61- }
62- },
63- "PATCH" : {
64- "description" : "Update part of a TODO item by its ID (any field can be provided)." ,
65- "body_params" : {
66- "title" : "The TODO item title (optional)." ,
67- "done" : "Completion status (optional)." ,
68- "description" : "Detailed TODO item description (optional)."
69- },
70- "responses" : {
71- "200" : "Updated todo item" ,
72- "400" : "Invalid request (empty body)" ,
73- "404" : "Todo not found"
74- }
75- },
76- "DELETE" : {
77- "description" : "Delete a TODO item by its ID." ,
78- "responses" : {
79- "204" : "Todo deleted successfully" ,
80- "404" : "Todo not found"
81- }
82- }
83- },
84- "/notes" : {
85- "POST" : {
86- "description" : "Upload a new note file." ,
87- "content_type" : "multipart/form-data" ,
88- "form_params" : {
89- "file" : "The .txt file to upload (required, max size: 1MB)"
90- },
91- "responses" : {
92- "201" : "Note created successfully" ,
93- "400" : "Invalid request (empty file, wrong format, etc.)"
94- }
95- }
96- },
97- "/notes/<note_name>" : {
98- "GET" : {
99- "description" : "Download a note by its name." ,
100- "responses" : {
101- "200" : "Note file content" ,
102- "404" : "Note not found"
103- }
104- },
105- "DELETE" : {
106- "description" : "Delete a note by its name." ,
107- "responses" : {
108- "204" : "Note deleted successfully" ,
109- "404" : "Note not found"
110- }
111- }
112- }
113- })
32+
11433 return Response (
11534 json .dumps (docs , sort_keys = False , indent = 2 ) + "\n " ,
11635 mimetype = 'application/json'
@@ -122,60 +41,21 @@ def _get_auth_docs():
12241 if not auth_config or auth_config .auth_method == AuthMethod .NONE :
12342 return None
12443
125- auth_docs = {
126- AuthMethod .API_KEY : {
127- "method" : "api_key" ,
128- "description" : "API Key authentication required for protected endpoints." ,
129- "how_to_authenticate" : "Include your API key in the X-API-Key header for all requests." ,
130- "example" : {
131- "headers" : {
132- "X-API-Key" : "your-api-key-here"
133- }
134- },
135- "protected_endpoints" : ["/todos/*" , "/notes/*" ]
136- },
137- AuthMethod .JWT : {
138- "method" : "jwt" ,
139- "description" : "JWT (JSON Web Token) authentication required for protected endpoints." ,
140- "how_to_authenticate" : "1. Get a token via /auth/login or /auth/signup\n 2. Include the token in the Authorization header." ,
141- "endpoints" : {
142- "/auth/signup" : {
143- "method" : "POST" ,
144- "body" : {"username" : "string" , "password" : "string" },
145- "response" : {"token" : "string" }
146- },
147- "/auth/login" : {
148- "method" : "POST" ,
149- "body" : {"username" : "string" , "password" : "string" },
150- "response" : {"token" : "string" }
151- }
152- },
153- "example" : {
154- "headers" : {
155- "Authorization" : "Bearer your-jwt-token-here"
156- }
157- },
158- "protected_endpoints" : ["/todos/*" , "/notes/*" ]
159- },
160- AuthMethod .SESSION : {
161- "method" : "session" ,
162- "description" : "Session-based authentication required for protected endpoints." ,
163- "how_to_authenticate" : "1. Login via /auth/login or signup via /auth/signup\n 2. Session cookie will be automatically managed by your browser." ,
164- "endpoints" : {
165- "/auth/signup" : {
166- "method" : "POST" ,
167- "body" : {"username" : "string" , "password" : "string" }
168- },
169- "/auth/login" : {
170- "method" : "POST" ,
171- "body" : {"username" : "string" , "password" : "string" }
172- },
173- "/auth/logout" : {
174- "method" : "POST"
175- }
176- },
177- "protected_endpoints" : ["/todos/*" , "/notes/*" ]
178- }
44+ auth_method_map = {
45+ AuthMethod .API_KEY : 'api_key' ,
46+ AuthMethod .JWT : 'jwt' ,
47+ AuthMethod .SESSION : 'session'
17948 }
18049
181- return auth_docs .get (auth_config .auth_method , {"error" : "Unknown authentication method" })
50+ method_name = auth_method_map .get (auth_config .auth_method )
51+ if not method_name :
52+ return {"error" : "Unknown authentication method" }
53+
54+ auth_file = os .path .join (
55+ current_app .root_path ,
56+ '..' ,
57+ 'docs' ,
58+ 'auth' ,
59+ f'{ method_name } .json'
60+ )
61+ return load_json_file (auth_file )
0 commit comments