1
+ import os
1
2
from flask import Blueprint , current_app , json , Response
2
3
from config .auth_config import AuthMethod
3
4
4
5
docs_bp = Blueprint ("docs" , __name__ )
5
6
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
+
6
15
@docs_bp .route ("" , methods = ["GET" ])
7
16
def api_docs ():
8
17
"""Provide comprehensive API documentation."""
9
18
docs = {}
10
19
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
11
29
auth_docs = _get_auth_docs ()
12
30
if auth_docs :
13
31
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
+
114
33
return Response (
115
34
json .dumps (docs , sort_keys = False , indent = 2 ) + "\n " ,
116
35
mimetype = 'application/json'
@@ -122,60 +41,21 @@ def _get_auth_docs():
122
41
if not auth_config or auth_config .auth_method == AuthMethod .NONE :
123
42
return None
124
43
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'
179
48
}
180
49
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