zeltera commited on
Commit
1063df3
·
verified ·
1 Parent(s): eb64c49

Upload 3 files

Browse files
Files changed (2) hide show
  1. app.py +2 -2
  2. static/script.js +49 -50
app.py CHANGED
@@ -24,9 +24,9 @@ app.config['SQLALCHEMY_DATABASE_URI'] = os.environ.get('DATABASE_URL', 'sqlite:/
24
  app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
25
  app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'dev-key-change-in-production-xyz123')
26
  app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7)
27
- app.config['SESSION_COOKIE_SECURE'] = False
28
  app.config['SESSION_COOKIE_HTTPONLY'] = True
29
- app.config['SESSION_COOKIE_SAMESITE'] = 'Lax'
30
  app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {
31
  'pool_recycle': 300,
32
  'pool_pre_ping': True,
 
24
  app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
25
  app.config['SECRET_KEY'] = os.environ.get('SECRET_KEY', 'dev-key-change-in-production-xyz123')
26
  app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7)
27
+ app.config['SESSION_COOKIE_SECURE'] = True # ← HF Spaces uses HTTPS
28
  app.config['SESSION_COOKIE_HTTPONLY'] = True
29
+ app.config['SESSION_COOKIE_SAMESITE'] = 'None' # ← Allow cross-site cookies
30
  app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {
31
  'pool_recycle': 300,
32
  'pool_pre_ping': True,
static/script.js CHANGED
@@ -1,4 +1,5 @@
1
- // Navigation Logic
 
2
  function showSection(sectionId) {
3
  document.querySelectorAll('.section').forEach(el => el.classList.remove('active'));
4
  document.querySelectorAll('.nav-links li').forEach(el => el.classList.remove('active'));
@@ -6,13 +7,18 @@ function showSection(sectionId) {
6
  document.getElementById(sectionId).classList.add('active');
7
  event.target.classList.add('active');
8
 
9
- if(sectionId === 'dashboard') loadStats();
 
 
 
10
  if(sectionId === 'list') loadApis();
 
11
  }
12
 
13
- // Load Stats
 
14
  async function loadStats() {
15
- const res = await fetch('/api/cms/stats');
16
  const data = await res.json();
17
 
18
  document.getElementById('stat-calls').innerText = data.total_calls;
@@ -21,7 +27,8 @@ async function loadStats() {
21
  document.getElementById('stat-apis').innerText = data.active_apis;
22
  }
23
 
24
- // Create API
 
25
  document.getElementById('create-form').addEventListener('submit', async (e) => {
26
  e.preventDefault();
27
 
@@ -34,18 +41,24 @@ document.getElementById('create-form').addEventListener('submit', async (e) => {
34
  const res = await fetch('/api/cms/create', {
35
  method: 'POST',
36
  headers: {'Content-Type': 'application/json'},
37
- body: JSON.stringify(payload)
 
38
  });
39
 
40
  if(res.ok) {
41
- alert('API Created! You can now POST to: http://localhost:5000/user-api/' + payload.route);
42
  document.getElementById('create-form').reset();
43
  showSection('list');
 
 
 
44
  }
45
  });
46
 
 
 
47
  async function loadLogs() {
48
- const res = await fetch('/api/cms/logs');
49
  const logs = await res.json();
50
  const container = document.getElementById('logs-container');
51
 
@@ -72,24 +85,10 @@ async function loadLogs() {
72
  container.innerHTML = html;
73
  }
74
 
75
- // Update showSection function to load logs
76
- function showSection(sectionId) {
77
- document.querySelectorAll('.section').forEach(el => el.classList.remove('active'));
78
- document.querySelectorAll('.nav-links li').forEach(el => el.classList.remove('active'));
79
-
80
- document.getElementById(sectionId).classList.add('active');
81
- event.target.classList.add('active');
82
 
83
- if(sectionId === 'dashboard') {
84
- loadStats();
85
- loadLogs();
86
- }
87
- if(sectionId === 'list') loadApis();
88
- }
89
-
90
- // Load API List
91
  async function loadApis() {
92
- const res = await fetch('/api/cms/list');
93
  const apis = await res.json();
94
  const tbody = document.getElementById('api-table-body');
95
 
@@ -111,18 +110,21 @@ async function loadApis() {
111
  });
112
  }
113
 
114
- // Add delete function
115
  async function deleteApi(id) {
116
  if(confirm('Are you sure you want to delete this API?')) {
117
- await fetch(`/api/cms/delete/${id}`, { method: 'DELETE' });
 
 
 
118
  loadApis();
119
  loadStats();
120
  }
121
  }
122
 
123
- // API Keys Functions
 
124
  async function loadKeys() {
125
- const res = await fetch('/api/cms/keys');
126
  const keys = await res.json();
127
  const tbody = document.getElementById('keys-table-body');
128
 
@@ -151,7 +153,8 @@ async function createKey() {
151
  const res = await fetch('/api/cms/keys', {
152
  method: 'POST',
153
  headers: {'Content-Type': 'application/json'},
154
- body: JSON.stringify({name})
 
155
  });
156
 
157
  const data = await res.json();
@@ -160,52 +163,48 @@ async function createKey() {
160
  alert('New API Key Generated:\n\n' + data.key + '\n\nSave this key! It won\'t be shown again.');
161
  document.getElementById('key-name').value = '';
162
  loadKeys();
 
 
163
  }
164
  }
165
 
166
  async function toggleKey(id) {
167
- await fetch(`/api/cms/keys/${id}/toggle`, {method: 'POST'});
 
 
 
168
  loadKeys();
169
  }
170
 
171
  async function deleteKey(id) {
172
  if(confirm('Delete this API Key?')) {
173
- await fetch(`/api/cms/keys/${id}`, {method: 'DELETE'});
 
 
 
174
  loadKeys();
175
  }
176
  }
177
 
178
- // Export Function
 
179
  function exportLogs() {
180
  window.open('/api/cms/export', '_blank');
181
  }
182
 
183
- // Update showSection to handle keys
184
- function showSection(sectionId) {
185
- document.querySelectorAll('.section').forEach(el => el.classList.remove('active'));
186
- document.querySelectorAll('.nav-links li').forEach(el => el.classList.remove('active'));
187
-
188
- document.getElementById(sectionId).classList.add('active');
189
- event.target.classList.add('active');
190
-
191
- if(sectionId === 'dashboard') {
192
- loadStats();
193
- loadLogs();
194
- }
195
- if(sectionId === 'list') loadApis();
196
- if(sectionId === 'keys') loadKeys();
197
- }
198
 
199
- // Simple Test Function
200
  async function testApi(route) {
201
  const res = await fetch(`/user-api/${route}`, {
202
  method: 'POST',
203
  headers: {'Content-Type': 'application/json'},
204
- body: JSON.stringify({test: "data"})
 
205
  });
206
  const data = await res.json();
207
  alert("Response:\n" + JSON.stringify(data, null, 2));
208
  }
209
 
210
- // Initial Load
 
211
  loadStats();
 
1
+ // ==================== NAVIGATION ====================
2
+
3
  function showSection(sectionId) {
4
  document.querySelectorAll('.section').forEach(el => el.classList.remove('active'));
5
  document.querySelectorAll('.nav-links li').forEach(el => el.classList.remove('active'));
 
7
  document.getElementById(sectionId).classList.add('active');
8
  event.target.classList.add('active');
9
 
10
+ if(sectionId === 'dashboard') {
11
+ loadStats();
12
+ loadLogs();
13
+ }
14
  if(sectionId === 'list') loadApis();
15
+ if(sectionId === 'keys') loadKeys();
16
  }
17
 
18
+ // ==================== STATS ====================
19
+
20
  async function loadStats() {
21
+ const res = await fetch('/api/cms/stats', { credentials: 'include' });
22
  const data = await res.json();
23
 
24
  document.getElementById('stat-calls').innerText = data.total_calls;
 
27
  document.getElementById('stat-apis').innerText = data.active_apis;
28
  }
29
 
30
+ // ==================== CREATE API ====================
31
+
32
  document.getElementById('create-form').addEventListener('submit', async (e) => {
33
  e.preventDefault();
34
 
 
41
  const res = await fetch('/api/cms/create', {
42
  method: 'POST',
43
  headers: {'Content-Type': 'application/json'},
44
+ body: JSON.stringify(payload),
45
+ credentials: 'include'
46
  });
47
 
48
  if(res.ok) {
49
+ alert('API Created! You can now POST to: /user-api/' + payload.route);
50
  document.getElementById('create-form').reset();
51
  showSection('list');
52
+ } else {
53
+ const data = await res.json();
54
+ alert('Error: ' + data.message);
55
  }
56
  });
57
 
58
+ // ==================== LOGS ====================
59
+
60
  async function loadLogs() {
61
+ const res = await fetch('/api/cms/logs', { credentials: 'include' });
62
  const logs = await res.json();
63
  const container = document.getElementById('logs-container');
64
 
 
85
  container.innerHTML = html;
86
  }
87
 
88
+ // ==================== API LIST ====================
 
 
 
 
 
 
89
 
 
 
 
 
 
 
 
 
90
  async function loadApis() {
91
+ const res = await fetch('/api/cms/list', { credentials: 'include' });
92
  const apis = await res.json();
93
  const tbody = document.getElementById('api-table-body');
94
 
 
110
  });
111
  }
112
 
 
113
  async function deleteApi(id) {
114
  if(confirm('Are you sure you want to delete this API?')) {
115
+ await fetch(`/api/cms/delete/${id}`, {
116
+ method: 'DELETE',
117
+ credentials: 'include'
118
+ });
119
  loadApis();
120
  loadStats();
121
  }
122
  }
123
 
124
+ // ==================== API KEYS ====================
125
+
126
  async function loadKeys() {
127
+ const res = await fetch('/api/cms/keys', { credentials: 'include' });
128
  const keys = await res.json();
129
  const tbody = document.getElementById('keys-table-body');
130
 
 
153
  const res = await fetch('/api/cms/keys', {
154
  method: 'POST',
155
  headers: {'Content-Type': 'application/json'},
156
+ body: JSON.stringify({name}),
157
+ credentials: 'include'
158
  });
159
 
160
  const data = await res.json();
 
163
  alert('New API Key Generated:\n\n' + data.key + '\n\nSave this key! It won\'t be shown again.');
164
  document.getElementById('key-name').value = '';
165
  loadKeys();
166
+ } else {
167
+ alert('Error: ' + data.message);
168
  }
169
  }
170
 
171
  async function toggleKey(id) {
172
+ await fetch(`/api/cms/keys/${id}/toggle`, {
173
+ method: 'POST',
174
+ credentials: 'include'
175
+ });
176
  loadKeys();
177
  }
178
 
179
  async function deleteKey(id) {
180
  if(confirm('Delete this API Key?')) {
181
+ await fetch(`/api/cms/keys/${id}`, {
182
+ method: 'DELETE',
183
+ credentials: 'include'
184
+ });
185
  loadKeys();
186
  }
187
  }
188
 
189
+ // ==================== EXPORT ====================
190
+
191
  function exportLogs() {
192
  window.open('/api/cms/export', '_blank');
193
  }
194
 
195
+ // ==================== TEST API ====================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
 
 
197
  async function testApi(route) {
198
  const res = await fetch(`/user-api/${route}`, {
199
  method: 'POST',
200
  headers: {'Content-Type': 'application/json'},
201
+ body: JSON.stringify({test: "data"}),
202
+ credentials: 'include'
203
  });
204
  const data = await res.json();
205
  alert("Response:\n" + JSON.stringify(data, null, 2));
206
  }
207
 
208
+ // ==================== INITIAL LOAD ====================
209
+
210
  loadStats();