keepup-admin 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. keepup/THIRD-PARTY.md +44 -0
  2. keepup/__init__.py +41 -0
  3. keepup/api_versions.py +100 -0
  4. keepup/audit.py +499 -0
  5. keepup/auth/__init__.py +7 -0
  6. keepup/auth/config.py +128 -0
  7. keepup/auth/dependencies.py +485 -0
  8. keepup/auth/dto/__init__.py +0 -0
  9. keepup/auth/dto/token.py +31 -0
  10. keepup/auth/factory.py +28 -0
  11. keepup/auth/login_throttle.py +151 -0
  12. keepup/auth/oidc.py +245 -0
  13. keepup/auth/oidc_policy.py +111 -0
  14. keepup/auth/oidc_routes.py +288 -0
  15. keepup/auth/panel_session.py +220 -0
  16. keepup/auth/permissions.py +59 -0
  17. keepup/auth/providers/__init__.py +0 -0
  18. keepup/auth/providers/base.py +168 -0
  19. keepup/auth/providers/local.py +180 -0
  20. keepup/auth/routes.py +660 -0
  21. keepup/auth/seed_accounts.py +322 -0
  22. keepup/auth/session_lifetime.py +104 -0
  23. keepup/auth/signing_key.py +138 -0
  24. keepup/auth/websocket.py +86 -0
  25. keepup/cluster.py +634 -0
  26. keepup/db.py +663 -0
  27. keepup/events.py +764 -0
  28. keepup/factory.py +484 -0
  29. keepup/instance.py +46 -0
  30. keepup/integrations.py +260 -0
  31. keepup/locks.py +412 -0
  32. keepup/logging_setup.py +690 -0
  33. keepup/metrics.py +818 -0
  34. keepup/metrics_retention.py +376 -0
  35. keepup/modules.py +572 -0
  36. keepup/notification_bus.py +355 -0
  37. keepup/plugins/__init__.py +9 -0
  38. keepup/plugins/admin.py +246 -0
  39. keepup/plugins/base.py +234 -0
  40. keepup/plugins/enablement.py +184 -0
  41. keepup/plugins/registry.py +171 -0
  42. keepup/plugins/route_mask.py +338 -0
  43. keepup/plugins/routes.py +376 -0
  44. keepup/roles.py +17 -0
  45. keepup/scheduler.py +93 -0
  46. keepup/schema.py +295 -0
  47. keepup/sections.json +104 -0
  48. keepup/settings.py +184 -0
  49. keepup/static/css/aos.css +1 -0
  50. keepup/static/css/main_nebula.css +232 -0
  51. keepup/static/css/main_new.css +852 -0
  52. keepup/static/css/tailwind.css +1 -0
  53. keepup/static/index_nebula.html +293 -0
  54. keepup/static/index_new.html +286 -0
  55. keepup/static/js/aos.js +1 -0
  56. keepup/static/js/feather-icons.js +13 -0
  57. keepup/static/js/main_new.js +1861 -0
  58. keepup/static/js/tailwind.js +83 -0
  59. keepup/static/modules/css/background_tasks.css +233 -0
  60. keepup/static/modules/css/cluster.css +16 -0
  61. keepup/static/modules/css/event_manager.css +386 -0
  62. keepup/static/modules/css/integration_logs.css +33 -0
  63. keepup/static/modules/css/metrics.css +115 -0
  64. keepup/static/modules/css/modules.css +189 -0
  65. keepup/static/modules/css/themes.css +563 -0
  66. keepup/static/modules/css/users.css +278 -0
  67. keepup/static/modules/js/background_tasks.js +657 -0
  68. keepup/static/modules/js/chart.js +14 -0
  69. keepup/static/modules/js/chartjs-adapter-date-fns.bundle.min.js +7 -0
  70. keepup/static/modules/js/cluster.js +363 -0
  71. keepup/static/modules/js/event_manager.js +979 -0
  72. keepup/static/modules/js/integration_logs.js +767 -0
  73. keepup/static/modules/js/metrics.js +908 -0
  74. keepup/static/modules/js/modules.js +1086 -0
  75. keepup/static/modules/js/themes.js +653 -0
  76. keepup/static/modules/js/users.js +784 -0
  77. keepup/tables.py +302 -0
  78. keepup/themes.py +496 -0
  79. keepup/web.py +182 -0
  80. keepup_admin-0.1.0.dist-info/METADATA +117 -0
  81. keepup_admin-0.1.0.dist-info/RECORD +86 -0
  82. keepup_admin-0.1.0.dist-info/WHEEL +5 -0
  83. keepup_admin-0.1.0.dist-info/licenses/LICENSE +202 -0
  84. keepup_admin-0.1.0.dist-info/licenses/NOTICE +22 -0
  85. keepup_admin-0.1.0.dist-info/licenses/THIRD-PARTY.md +44 -0
  86. keepup_admin-0.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,233 @@
1
+ .background-tasks-module {
2
+ font-family: 'Inter', sans-serif;
3
+ }
4
+
5
+ .tasks-stats-grid {
6
+ display: grid;
7
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
8
+ gap: 1.5rem;
9
+ margin-bottom: 2rem;
10
+ }
11
+
12
+ .stat-card {
13
+ background: white;
14
+ border-radius: 12px;
15
+ padding: 1.5rem;
16
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
17
+ border-left: 4px solid #3b82f6;
18
+ }
19
+
20
+ .stat-card.warning {
21
+ border-left-color: #f59e0b;
22
+ }
23
+
24
+ .stat-card.danger {
25
+ border-left-color: #ef4444;
26
+ }
27
+
28
+ .stat-card.success {
29
+ border-left-color: #10b981;
30
+ }
31
+
32
+ .stat-value {
33
+ font-size: 2rem;
34
+ font-weight: bold;
35
+ color: #1f2937;
36
+ margin-bottom: 0.5rem;
37
+ }
38
+
39
+ .stat-label {
40
+ color: #6b7280;
41
+ font-size: 0.875rem;
42
+ text-transform: uppercase;
43
+ letter-spacing: 0.05em;
44
+ }
45
+
46
+ .locks-table {
47
+ width: 100%;
48
+ background: white;
49
+ border-radius: 12px;
50
+ overflow: hidden;
51
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
52
+ }
53
+
54
+ .locks-table th {
55
+ background: #f8fafc;
56
+ padding: 1rem;
57
+ text-align: left;
58
+ font-weight: 600;
59
+ color: #374151;
60
+ border-bottom: 1px solid #e5e7eb;
61
+ }
62
+
63
+ .locks-table td {
64
+ padding: 1rem;
65
+ border-bottom: 1px solid #f3f4f6;
66
+ }
67
+
68
+ .lock-expired {
69
+ background-color: #fef2f2;
70
+ }
71
+
72
+ .lock-expired td {
73
+ color: #dc2626;
74
+ }
75
+
76
+ .lock-actions {
77
+ display: flex;
78
+ gap: 0.5rem;
79
+ }
80
+
81
+ .btn {
82
+ padding: 0.5rem 1rem;
83
+ border-radius: 6px;
84
+ font-size: 0.875rem;
85
+ font-weight: 500;
86
+ cursor: pointer;
87
+ border: none;
88
+ transition: all 0.2s;
89
+ }
90
+
91
+ .btn-primary {
92
+ background: #3b82f6;
93
+ color: white;
94
+ }
95
+
96
+ .btn-primary:hover {
97
+ background: #2563eb;
98
+ }
99
+
100
+ .btn-danger {
101
+ background: #ef4444;
102
+ color: white;
103
+ }
104
+
105
+ .btn-danger:hover {
106
+ background: #dc2626;
107
+ }
108
+
109
+ .btn-warning {
110
+ background: #f59e0b;
111
+ color: white;
112
+ }
113
+
114
+ .btn-warning:hover {
115
+ background: #d97706;
116
+ }
117
+
118
+ .btn:disabled {
119
+ opacity: 0.5;
120
+ cursor: not-allowed;
121
+ }
122
+
123
+ .scheduler-section {
124
+ background: white;
125
+ border-radius: 12px;
126
+ padding: 1.5rem;
127
+ margin-top: 2rem;
128
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
129
+ }
130
+
131
+ .job-card {
132
+ background: #f8fafc;
133
+ border-radius: 8px;
134
+ padding: 1rem;
135
+ margin-bottom: 1rem;
136
+ border-left: 4px solid #3b82f6;
137
+ }
138
+
139
+ .job-header {
140
+ display: flex;
141
+ justify-content: between;
142
+ align-items: center;
143
+ margin-bottom: 0.5rem;
144
+ }
145
+
146
+ .job-name {
147
+ font-weight: 600;
148
+ color: #1f2937;
149
+ }
150
+
151
+ .job-status {
152
+ padding: 0.25rem 0.5rem;
153
+ border-radius: 9999px;
154
+ font-size: 0.75rem;
155
+ font-weight: 500;
156
+ }
157
+
158
+ .status-running {
159
+ background: #d1fae5;
160
+ color: #065f46;
161
+ }
162
+
163
+ .status-paused {
164
+ background: #fef3c7;
165
+ color: #92400e;
166
+ }
167
+
168
+ .job-details {
169
+ display: grid;
170
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
171
+ gap: 1rem;
172
+ font-size: 0.875rem;
173
+ }
174
+
175
+ .job-detail {
176
+ display: flex;
177
+ flex-direction: column;
178
+ }
179
+
180
+ .detail-label {
181
+ color: #6b7280;
182
+ font-size: 0.75rem;
183
+ text-transform: uppercase;
184
+ letter-spacing: 0.05em;
185
+ }
186
+
187
+ .detail-value {
188
+ color: #1f2937;
189
+ font-weight: 500;
190
+ }
191
+
192
+ .loading-spinner {
193
+ display: inline-block;
194
+ width: 1rem;
195
+ height: 1rem;
196
+ border: 2px solid #f3f4f6;
197
+ border-top: 2px solid #3b82f6;
198
+ border-radius: 50%;
199
+ animation: spin 1s linear infinite;
200
+ }
201
+
202
+ @keyframes spin {
203
+ 0% { transform: rotate(0deg); }
204
+ 100% { transform: rotate(360deg); }
205
+ }
206
+
207
+ .auto-refresh-controls {
208
+ display: flex;
209
+ align-items: center;
210
+ gap: 1rem;
211
+ margin-bottom: 1rem;
212
+ }
213
+
214
+ .refresh-badge {
215
+ background: #dbeafe;
216
+ color: #1e40af;
217
+ padding: 0.25rem 0.5rem;
218
+ border-radius: 6px;
219
+ font-size: 0.75rem;
220
+ font-weight: 500;
221
+ }
222
+
223
+ .empty-state {
224
+ text-align: center;
225
+ padding: 3rem;
226
+ color: #6b7280;
227
+ }
228
+
229
+ .empty-state i {
230
+ font-size: 3rem;
231
+ margin-bottom: 1rem;
232
+ color: #d1d5db;
233
+ }
@@ -0,0 +1,16 @@
1
+ /* cluster.css -- the Cluster section (role ADMIN).
2
+ Its own section only: the panel's chrome belongs to the theme. */
3
+
4
+ #cluster-section .cluster-admin {
5
+ animation: clusterFadeIn 0.2s ease-out;
6
+ }
7
+
8
+ #cluster-section .responsive-table td,
9
+ #cluster-section .responsive-table th {
10
+ vertical-align: top;
11
+ }
12
+
13
+ @keyframes clusterFadeIn {
14
+ from { opacity: 0; transform: translateY(6px); }
15
+ to { opacity: 1; transform: translateY(0); }
16
+ }
@@ -0,0 +1,386 @@
1
+ /* audit_module.css -- styles for the event log section */
2
+
3
+ /* The event log section itself */
4
+ #audit-section {
5
+ animation: fadeIn 0.3s ease;
6
+ }
7
+
8
+ /* Appearance animation */
9
+ @keyframes fadeIn {
10
+ from {
11
+ opacity: 0;
12
+ transform: translateY(10px);
13
+ }
14
+ to {
15
+ opacity: 1;
16
+ transform: translateY(0);
17
+ }
18
+ }
19
+
20
+ /* Event cards */
21
+ .audit-event {
22
+ transition: all 0.2s ease;
23
+ cursor: pointer;
24
+ }
25
+
26
+ .audit-event:hover {
27
+ transform: translateY(-2px);
28
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
29
+ }
30
+
31
+ /* Event types -- the colours themselves are set from the script, as classes */
32
+ .bg-green-100.text-green-800 {
33
+ background-color: #d1fae5;
34
+ color: #065f46;
35
+ }
36
+
37
+ .bg-gray-100.text-gray-800 {
38
+ background-color: #f3f4f6;
39
+ color: #1f2937;
40
+ }
41
+
42
+ .bg-blue-100.text-blue-800 {
43
+ background-color: #dbeafe;
44
+ color: #1e40af;
45
+ }
46
+
47
+ .bg-red-100.text-red-800 {
48
+ background-color: #fee2e2;
49
+ color: #991b1b;
50
+ }
51
+
52
+ .bg-yellow-100.text-yellow-800 {
53
+ background-color: #fef9c3;
54
+ color: #854d0e;
55
+ }
56
+
57
+ .bg-purple-100.text-purple-800 {
58
+ background-color: #ede9fe;
59
+ color: #5b21b6;
60
+ }
61
+
62
+ .bg-indigo-100.text-indigo-800 {
63
+ background-color: #e0e7ff;
64
+ color: #3730a3;
65
+ }
66
+
67
+ /* The container holding an event's data */
68
+ #audit-events-container {
69
+ min-height: 400px;
70
+ }
71
+
72
+ /* Preformatted text (JSON) */
73
+ #audit-events-container pre {
74
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', monospace;
75
+ font-size: 12px;
76
+ line-height: 1.5;
77
+ white-space: pre-wrap;
78
+ word-wrap: break-word;
79
+ background-color: #f9fafb;
80
+ border: 1px solid #e5e7eb;
81
+ }
82
+
83
+ /* Action buttons */
84
+ .audit-event button {
85
+ transition: all 0.2s ease;
86
+ }
87
+
88
+ .audit-event button:hover {
89
+ transform: translateX(2px);
90
+ }
91
+
92
+ /* Pagination */
93
+ #audit-pagination button {
94
+ transition: all 0.2s ease;
95
+ min-width: 40px;
96
+ }
97
+
98
+ #audit-pagination button:hover:not(:disabled) {
99
+ background-color: #f3f4f6;
100
+ transform: translateY(-1px);
101
+ }
102
+
103
+ #audit-pagination button:active:not(:disabled) {
104
+ transform: translateY(0);
105
+ }
106
+
107
+ #audit-pagination button:disabled {
108
+ cursor: not-allowed;
109
+ opacity: 0.5;
110
+ }
111
+
112
+ /* Filters */
113
+ #audit-filters-form select,
114
+ #audit-filters-form input {
115
+ transition: all 0.2s ease;
116
+ }
117
+
118
+ #audit-filters-form select:focus,
119
+ #audit-filters-form input:focus {
120
+ outline: none;
121
+ ring: 2px solid #3b82f6;
122
+ border-color: #3b82f6;
123
+ }
124
+
125
+ /* Statistics cards */
126
+ #audit-stats-container .bg-blue-50,
127
+ #audit-stats-container .bg-green-50,
128
+ #audit-stats-container .bg-purple-50 {
129
+ transition: all 0.2s ease;
130
+ }
131
+
132
+ #audit-stats-container .bg-blue-50:hover,
133
+ #audit-stats-container .bg-green-50:hover,
134
+ #audit-stats-container .bg-purple-50:hover {
135
+ transform: translateY(-2px);
136
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
137
+ }
138
+
139
+ /* Progress bars */
140
+ .bg-gray-200 {
141
+ background-color: #e5e7eb;
142
+ }
143
+
144
+ .bg-blue-600 {
145
+ background-color: #2563eb;
146
+ }
147
+
148
+ .rounded-full {
149
+ border-radius: 9999px;
150
+ }
151
+
152
+ .h-2 {
153
+ height: 0.5rem;
154
+ }
155
+
156
+ /* The loading indicator's animation */
157
+ @keyframes spin {
158
+ from {
159
+ transform: rotate(0deg);
160
+ }
161
+ to {
162
+ transform: rotate(360deg);
163
+ }
164
+ }
165
+
166
+ .animate-spin {
167
+ animation: spin 1s linear infinite;
168
+ }
169
+
170
+ /* Notifications, where the shared ones are not used */
171
+ .audit-notification {
172
+ position: fixed;
173
+ top: 20px;
174
+ right: 20px;
175
+ z-index: 1000;
176
+ animation: slideIn 0.3s ease;
177
+ }
178
+
179
+ @keyframes slideIn {
180
+ from {
181
+ transform: translateX(100%);
182
+ opacity: 0;
183
+ }
184
+ to {
185
+ transform: translateX(0);
186
+ opacity: 1;
187
+ }
188
+ }
189
+
190
+ /* Narrow layout, for phones */
191
+ @media (max-width: 768px) {
192
+ #audit-section .flex.justify-between {
193
+ flex-direction: column;
194
+ gap: 1rem;
195
+ }
196
+
197
+ #audit-section .flex.space-x-2 {
198
+ justify-content: flex-start;
199
+ }
200
+
201
+ .audit-event {
202
+ margin-bottom: 1rem;
203
+ }
204
+
205
+ #audit-pagination .flex {
206
+ flex-wrap: wrap;
207
+ gap: 0.5rem;
208
+ }
209
+
210
+ #audit-pagination button {
211
+ padding: 0.5rem 0.75rem;
212
+ font-size: 0.875rem;
213
+ }
214
+
215
+ #audit-filters-form {
216
+ grid-template-columns: 1fr;
217
+ }
218
+ }
219
+
220
+ /* The scrollbar inside pre blocks */
221
+ #audit-events-container pre::-webkit-scrollbar {
222
+ width: 8px;
223
+ height: 8px;
224
+ }
225
+
226
+ #audit-events-container pre::-webkit-scrollbar-track {
227
+ background: #f1f1f1;
228
+ border-radius: 4px;
229
+ }
230
+
231
+ #audit-events-container pre::-webkit-scrollbar-thumb {
232
+ background: #cbd5e1;
233
+ border-radius: 4px;
234
+ }
235
+
236
+ #audit-events-container pre::-webkit-scrollbar-thumb:hover {
237
+ background: #94a3b8;
238
+ }
239
+
240
+ /* The empty state */
241
+ #audit-events-container .text-center {
242
+ padding: 3rem;
243
+ }
244
+
245
+ #audit-events-container .text-center i {
246
+ opacity: 0.5;
247
+ }
248
+
249
+ /* Active filters */
250
+ .bg-gray-100.px-2.py-1.rounded {
251
+ font-size: 0.75rem;
252
+ background-color: #f3f4f6;
253
+ transition: all 0.2s ease;
254
+ }
255
+
256
+ .bg-gray-100.px-2.py-1.rounded:hover {
257
+ background-color: #e5e7eb;
258
+ }
259
+
260
+ /* The reset filters button */
261
+ .text-red-600.hover\:text-red-800 {
262
+ transition: color 0.2s ease;
263
+ }
264
+
265
+ /* The confirmation modal */
266
+ .audit-modal {
267
+ position: fixed;
268
+ top: 0;
269
+ left: 0;
270
+ right: 0;
271
+ bottom: 0;
272
+ background-color: rgba(0, 0, 0, 0.5);
273
+ display: flex;
274
+ align-items: center;
275
+ justify-content: center;
276
+ z-index: 1050;
277
+ animation: fadeIn 0.2s ease;
278
+ }
279
+
280
+ .audit-modal-content {
281
+ background: white;
282
+ border-radius: 0.5rem;
283
+ max-width: 500px;
284
+ width: 90%;
285
+ max-height: 90vh;
286
+ overflow-y: auto;
287
+ animation: slideUp 0.3s ease;
288
+ }
289
+
290
+ @keyframes slideUp {
291
+ from {
292
+ transform: translateY(50px);
293
+ opacity: 0;
294
+ }
295
+ to {
296
+ transform: translateY(0);
297
+ opacity: 1;
298
+ }
299
+ }
300
+
301
+ /* The export table */
302
+ .audit-table {
303
+ width: 100%;
304
+ border-collapse: collapse;
305
+ }
306
+
307
+ .audit-table th,
308
+ .audit-table td {
309
+ padding: 0.75rem;
310
+ text-align: left;
311
+ border-bottom: 1px solid #e5e7eb;
312
+ }
313
+
314
+ .audit-table th {
315
+ background-color: #f9fafb;
316
+ font-weight: 600;
317
+ }
318
+
319
+ .audit-table tr:hover {
320
+ background-color: #f9fafb;
321
+ }
322
+
323
+ /* Status badges */
324
+ .status-badge {
325
+ display: inline-flex;
326
+ align-items: center;
327
+ padding: 0.25rem 0.5rem;
328
+ font-size: 0.75rem;
329
+ font-weight: 500;
330
+ border-radius: 9999px;
331
+ }
332
+
333
+ .status-active {
334
+ background-color: #d1fae5;
335
+ color: #065f46;
336
+ }
337
+
338
+ .status-blocked {
339
+ background-color: #fee2e2;
340
+ color: #991b1b;
341
+ }
342
+
343
+ .role-badge {
344
+ display: inline-flex;
345
+ align-items: center;
346
+ padding: 0.25rem 0.5rem;
347
+ font-size: 0.75rem;
348
+ font-weight: 500;
349
+ border-radius: 9999px;
350
+ }
351
+
352
+ .role-admin {
353
+ background-color: #dbeafe;
354
+ color: #1e40af;
355
+ }
356
+
357
+ .role-client {
358
+ background-color: #f3f4f6;
359
+ color: #374151;
360
+ }
361
+
362
+ /* Tooltips */
363
+ [data-tooltip] {
364
+ position: relative;
365
+ cursor: help;
366
+ }
367
+
368
+ [data-tooltip]:before {
369
+ content: attr(data-tooltip);
370
+ position: absolute;
371
+ bottom: 100%;
372
+ left: 50%;
373
+ transform: translateX(-50%);
374
+ padding: 0.5rem;
375
+ background-color: #1f2937;
376
+ color: white;
377
+ font-size: 0.75rem;
378
+ white-space: nowrap;
379
+ border-radius: 0.25rem;
380
+ display: none;
381
+ z-index: 10;
382
+ }
383
+
384
+ [data-tooltip]:hover:before {
385
+ display: block;
386
+ }
@@ -0,0 +1,33 @@
1
+ .integration-logs-table {
2
+ font-size: 0.875rem;
3
+ }
4
+
5
+ .integration-logs-table th {
6
+ background-color: #f9fafb;
7
+ font-weight: 600;
8
+ text-transform: uppercase;
9
+ letter-spacing: 0.05em;
10
+ }
11
+
12
+ .log-detail-pre {
13
+ white-space: pre-wrap;
14
+ word-break: break-all;
15
+ font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
16
+ font-size: 0.75rem;
17
+ }
18
+
19
+ .stats-grid {
20
+ display: grid;
21
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
22
+ gap: 1rem;
23
+ }
24
+
25
+ @media (max-width: 768px) {
26
+ .stats-grid {
27
+ grid-template-columns: 1fr;
28
+ }
29
+
30
+ .integration-logs-table {
31
+ font-size: 0.75rem;
32
+ }
33
+ }