appmanager-server 0.2.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.
- appmanager/__init__.py +52 -0
- appmanager/admin/__init__.py +3 -0
- appmanager/admin/app_installer.py +739 -0
- appmanager/admin/members.py +95 -0
- appmanager/admin/registry.py +372 -0
- appmanager/admin/routes.py +900 -0
- appmanager/api/__init__.py +5 -0
- appmanager/api/routes.py +373 -0
- appmanager/app_config.py +101 -0
- appmanager/auth/__init__.py +3 -0
- appmanager/auth/oauth.py +77 -0
- appmanager/auth/routes.py +224 -0
- appmanager/auth/utils.py +175 -0
- appmanager/bridge.py +90 -0
- appmanager/cli.py +1171 -0
- appmanager/config.py +58 -0
- appmanager/database.py +120 -0
- appmanager/extension.py +198 -0
- appmanager/extensions.py +225 -0
- appmanager/health.py +133 -0
- appmanager/hooks.py +187 -0
- appmanager/middleware.py +256 -0
- appmanager/models.py +307 -0
- appmanager/py.typed +1 -0
- appmanager/sdk.py +30 -0
- appmanager/security.py +227 -0
- appmanager/security_scanner.py +582 -0
- appmanager/signals.py +21 -0
- appmanager/static/css/app.css +808 -0
- appmanager/static/vendor/fonts/fonts.css +288 -0
- appmanager/static/vendor/fonts/jetbrainsmono-0.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-1.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-10.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-11.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-12.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-13.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-14.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-15.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-16.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-17.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-18.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-19.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-2.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-20.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-21.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-22.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-23.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-3.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-4.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-5.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-6.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-7.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-8.woff2 +0 -0
- appmanager/static/vendor/fonts/jetbrainsmono-9.woff2 +0 -0
- appmanager/static/vendor/fonts/spacegrotesk-0.woff2 +0 -0
- appmanager/static/vendor/fonts/spacegrotesk-1.woff2 +0 -0
- appmanager/static/vendor/fonts/spacegrotesk-10.woff2 +0 -0
- appmanager/static/vendor/fonts/spacegrotesk-11.woff2 +0 -0
- appmanager/static/vendor/fonts/spacegrotesk-2.woff2 +0 -0
- appmanager/static/vendor/fonts/spacegrotesk-3.woff2 +0 -0
- appmanager/static/vendor/fonts/spacegrotesk-4.woff2 +0 -0
- appmanager/static/vendor/fonts/spacegrotesk-5.woff2 +0 -0
- appmanager/static/vendor/fonts/spacegrotesk-6.woff2 +0 -0
- appmanager/static/vendor/fonts/spacegrotesk-7.woff2 +0 -0
- appmanager/static/vendor/fonts/spacegrotesk-8.woff2 +0 -0
- appmanager/static/vendor/fonts/spacegrotesk-9.woff2 +0 -0
- appmanager/static/vendor/htmx/htmx.min.js +1 -0
- appmanager/templates/admin/_member_drawer.html +98 -0
- appmanager/templates/admin/_members_table.html +108 -0
- appmanager/templates/admin/app_detail.html +136 -0
- appmanager/templates/admin/dashboard.html +902 -0
- appmanager/templates/admin/flairs.html +90 -0
- appmanager/templates/admin/permissions.html +88 -0
- appmanager/templates/admin/roles.html +119 -0
- appmanager/templates/admin/users.html +156 -0
- appmanager/templates/auth/login.html +58 -0
- appmanager/templates/auth/profile.html +44 -0
- appmanager/templates/base.html +76 -0
- appmanager/templates/errors/401.html +19 -0
- appmanager/templates/errors/403.html +19 -0
- appmanager/templates/errors/404.html +18 -0
- appmanager/templates/errors/500.html +19 -0
- appmanager/templates/index.html +54 -0
- appmanager_server-0.2.0.dist-info/METADATA +320 -0
- appmanager_server-0.2.0.dist-info/RECORD +89 -0
- appmanager_server-0.2.0.dist-info/WHEEL +5 -0
- appmanager_server-0.2.0.dist-info/entry_points.txt +5 -0
- appmanager_server-0.2.0.dist-info/licenses/LICENSE +21 -0
- appmanager_server-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
|
|
3
|
+
{% block title %}401 — Authentication Required | AppManager{% endblock %}
|
|
4
|
+
|
|
5
|
+
{% block content %}
|
|
6
|
+
<div style="display:flex; justify-content:center; align-items:center; min-height:60vh;">
|
|
7
|
+
<div class="card boot-item" style="max-width:500px; text-align:center; padding:2.5rem;">
|
|
8
|
+
<div class="mono" style="font-size:4rem; font-weight:700; color:var(--accent); line-height:1; margin-bottom:0.5rem;">401</div>
|
|
9
|
+
<h1 style="font-size:1.4rem; font-weight:600; margin-bottom:1rem;">Authentication Required</h1>
|
|
10
|
+
<p class="text-muted" style="margin-bottom:2rem; line-height:1.6;">
|
|
11
|
+
You must be logged into AppManager to access this protected application or feature.
|
|
12
|
+
</p>
|
|
13
|
+
<div class="flex-center" style="justify-content:center; gap:1rem;">
|
|
14
|
+
<a href="/auth/login" class="btn btn-primary">Log In to Continue</a>
|
|
15
|
+
<a href="/" class="btn btn-secondary">Return to Home</a>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
{% endblock %}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
|
|
3
|
+
{% block title %}403 — Access Denied | AppManager{% endblock %}
|
|
4
|
+
|
|
5
|
+
{% block content %}
|
|
6
|
+
<div style="display:flex; justify-content:center; align-items:center; min-height:60vh;">
|
|
7
|
+
<div class="card boot-item" style="max-width:500px; text-align:center; padding:2.5rem;">
|
|
8
|
+
<div class="mono" style="font-size:4rem; font-weight:700; color:var(--danger); line-height:1; margin-bottom:0.5rem;">403</div>
|
|
9
|
+
<h1 style="font-size:1.4rem; font-weight:600; margin-bottom:1rem;">Access Denied</h1>
|
|
10
|
+
<p class="text-muted" style="margin-bottom:2rem; line-height:1.6;">
|
|
11
|
+
You do not have permission to access this resource or application. Please contact your administrator if you believe this is an error.
|
|
12
|
+
</p>
|
|
13
|
+
<div class="flex-center" style="justify-content:center; gap:1rem;">
|
|
14
|
+
<a href="/" class="btn btn-primary">Return to Home</a>
|
|
15
|
+
<a href="/auth/profile" class="btn btn-secondary">My Profile</a>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
{% endblock %}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
|
|
3
|
+
{% block title %}404 — Not Found | AppManager{% endblock %}
|
|
4
|
+
|
|
5
|
+
{% block content %}
|
|
6
|
+
<div style="display:flex; justify-content:center; align-items:center; min-height:60vh;">
|
|
7
|
+
<div class="card boot-item" style="max-width:500px; text-align:center; padding:2.5rem;">
|
|
8
|
+
<div class="mono" style="font-size:4rem; font-weight:700; color:var(--danger); line-height:1; margin-bottom:0.5rem;">404</div>
|
|
9
|
+
<h1 style="font-size:1.4rem; font-weight:600; margin-bottom:1rem;">Page or App Not Found</h1>
|
|
10
|
+
<p class="text-muted" style="margin-bottom:2rem; line-height:1.6;">
|
|
11
|
+
The page or application you requested could not be located. It may have been uninstalled, moved, or the URL might be mistyped.
|
|
12
|
+
</p>
|
|
13
|
+
<div class="flex-center" style="justify-content:center;">
|
|
14
|
+
<a href="/" class="btn btn-primary">Return to Home</a>
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
{% endblock %}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
|
|
3
|
+
{% block title %}500 — Server Error | AppManager{% endblock %}
|
|
4
|
+
|
|
5
|
+
{% block content %}
|
|
6
|
+
<div style="display:flex; justify-content:center; align-items:center; min-height:60vh;">
|
|
7
|
+
<div class="card boot-item" style="max-width:520px; text-align:center; padding:2.5rem;">
|
|
8
|
+
<div class="mono" style="font-size:4rem; font-weight:700; color:var(--warning); line-height:1; margin-bottom:0.5rem;">500</div>
|
|
9
|
+
<h1 style="font-size:1.4rem; font-weight:600; margin-bottom:1rem;">Internal Server Error</h1>
|
|
10
|
+
<p class="text-muted" style="margin-bottom:2rem; line-height:1.6;">
|
|
11
|
+
AppManager encountered an unexpected condition while processing your request. Please try refreshing the page or contact system administrators if the issue persists.
|
|
12
|
+
</p>
|
|
13
|
+
<div class="flex-center" style="justify-content:center; gap:1rem;">
|
|
14
|
+
<a href="javascript:location.reload()" class="btn btn-primary">↻ Refresh Page</a>
|
|
15
|
+
<a href="/" class="btn btn-secondary">Return to Home</a>
|
|
16
|
+
</div>
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
{% endblock %}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
|
|
3
|
+
{% block title %}Applications — AppManager{% endblock %}
|
|
4
|
+
|
|
5
|
+
{% block content %}
|
|
6
|
+
<div class="page-header">
|
|
7
|
+
<div>
|
|
8
|
+
<h1 class="page-title">Installed Applications</h1>
|
|
9
|
+
<p class="page-subtitle">Select an application below to launch it inside your session.</p>
|
|
10
|
+
</div>
|
|
11
|
+
{% if apps %}
|
|
12
|
+
<span class="badge badge-primary">{{ apps|length }} available</span>
|
|
13
|
+
{% endif %}
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
{{ render_slot('dashboard_widget', user=user) if render_slot is defined else '' }}
|
|
17
|
+
|
|
18
|
+
{% if apps %}
|
|
19
|
+
<div class="grid grid-apps">
|
|
20
|
+
{% for app in apps %}
|
|
21
|
+
<div class="app-card boot-item" style="animation-delay: {{ loop.index0 * 60 }}ms;">
|
|
22
|
+
<div class="app-body">
|
|
23
|
+
<div class="flex-between mb-1">
|
|
24
|
+
<span class="badge badge-primary">{{ app.source_type }}</span>
|
|
25
|
+
{% if app.app_type == 'extension' %}
|
|
26
|
+
<span class="badge badge-accent">Extension</span>
|
|
27
|
+
{% endif %}
|
|
28
|
+
</div>
|
|
29
|
+
<h2 class="app-title">{{ app.name }}</h2>
|
|
30
|
+
<p class="app-desc">{{ app.description or "Flask application hosted under AppManager wrapper." }}</p>
|
|
31
|
+
</div>
|
|
32
|
+
<div class="app-footer">
|
|
33
|
+
<span class="app-meta">
|
|
34
|
+
{% if app.app_type == 'extension' %}Extension App{% else %}/apps/{{ app.slug }}{% endif %}
|
|
35
|
+
</span>
|
|
36
|
+
{% if app.has_web_ui %}
|
|
37
|
+
<a href="/apps/{{ app.slug }}/" class="btn btn-primary btn-sm">Launch →</a>
|
|
38
|
+
{% else %}
|
|
39
|
+
<span class="btn btn-secondary btn-sm disabled">No UI</span>
|
|
40
|
+
{% endif %}
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
{% endfor %}
|
|
44
|
+
</div>
|
|
45
|
+
{% else %}
|
|
46
|
+
<div class="empty-state">
|
|
47
|
+
<h2>No Applications Available</h2>
|
|
48
|
+
<p>There are currently no sub-apps installed or you do not have permission to access any installed applications.</p>
|
|
49
|
+
{% if user and user.is_admin() %}
|
|
50
|
+
<a href="/admin" class="btn btn-primary">Go to Admin Dashboard to Install Apps</a>
|
|
51
|
+
{% endif %}
|
|
52
|
+
</div>
|
|
53
|
+
{% endif %}
|
|
54
|
+
{% endblock %}
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: appmanager-server
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Multi-tenant Flask sub-application portal & dynamic WSGI dispatcher with in-process isolation, telemetry, and automated health checks.
|
|
5
|
+
Author: AppManager Contributors
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/r3sbarra/appmanager-server
|
|
8
|
+
Project-URL: Documentation, https://github.com/r3sbarra/appmanager-server#readme
|
|
9
|
+
Project-URL: Repository, https://github.com/r3sbarra/appmanager-server.git
|
|
10
|
+
Project-URL: Issues, https://github.com/r3sbarra/appmanager-server/issues
|
|
11
|
+
Project-URL: Changelog, https://github.com/r3sbarra/appmanager-server/blob/master/CHANGELOG.md
|
|
12
|
+
Keywords: flask,wsgi,multi-tenant,sub-apps,pythonanywhere,dispatcher,microfrontends,portal,appmanager
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Environment :: Web Environment
|
|
15
|
+
Classifier: Framework :: Flask
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
25
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
|
|
26
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
27
|
+
Requires-Python: >=3.10
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
License-File: LICENSE
|
|
30
|
+
Requires-Dist: Flask>=3.0.0
|
|
31
|
+
Requires-Dist: Flask-SQLAlchemy>=3.1.1
|
|
32
|
+
Requires-Dist: blinker>=1.6.0
|
|
33
|
+
Requires-Dist: PyJWT>=2.8.0
|
|
34
|
+
Requires-Dist: requests>=2.31.0
|
|
35
|
+
Requires-Dist: Authlib>=1.3.0
|
|
36
|
+
Requires-Dist: GitPython>=3.1.41
|
|
37
|
+
Requires-Dist: Werkzeug>=3.0.1
|
|
38
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
39
|
+
Requires-Dist: appmanager-sdk>=0.1.0
|
|
40
|
+
Provides-Extra: mysql
|
|
41
|
+
Requires-Dist: PyMySQL>=1.1.0; extra == "mysql"
|
|
42
|
+
Requires-Dist: cryptography>=41.0.0; extra == "mysql"
|
|
43
|
+
Provides-Extra: postgres
|
|
44
|
+
Requires-Dist: psycopg2-binary>=2.9.0; extra == "postgres"
|
|
45
|
+
Provides-Extra: all
|
|
46
|
+
Requires-Dist: PyMySQL>=1.1.0; extra == "all"
|
|
47
|
+
Requires-Dist: cryptography>=41.0.0; extra == "all"
|
|
48
|
+
Requires-Dist: psycopg2-binary>=2.9.0; extra == "all"
|
|
49
|
+
Provides-Extra: dev
|
|
50
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
51
|
+
Requires-Dist: pytest-cov>=5.0.0; extra == "dev"
|
|
52
|
+
Requires-Dist: ruff>=0.5.0; extra == "dev"
|
|
53
|
+
Requires-Dist: build>=1.1.0; extra == "dev"
|
|
54
|
+
Requires-Dist: twine>=5.0.0; extra == "dev"
|
|
55
|
+
Requires-Dist: PyMySQL>=1.1.0; extra == "dev"
|
|
56
|
+
Provides-Extra: docs
|
|
57
|
+
Requires-Dist: mkdocs-material>=9.5.0; extra == "docs"
|
|
58
|
+
Requires-Dist: mkdocstrings[python]>=0.25.0; extra == "docs"
|
|
59
|
+
Requires-Dist: pymdown-extensions>=10.7; extra == "docs"
|
|
60
|
+
Dynamic: license-file
|
|
61
|
+
|
|
62
|
+
<p align="center">
|
|
63
|
+
<img src="docs/assets/banner.svg" alt="AppManager Banner" width="100%">
|
|
64
|
+
</p>
|
|
65
|
+
|
|
66
|
+
<p align="center">
|
|
67
|
+
<a href="https://github.com/r3sbarra/appmanager-server/actions"><img src="https://github.com/r3sbarra/appmanager-server/actions/workflows/ci.yml/badge.svg" alt="CI Status"></a>
|
|
68
|
+
<a href="https://pypi.org/project/appmanager-server/"><img src="https://img.shields.io/pypi/v/appmanager-server.svg" alt="PyPI Version"></a>
|
|
69
|
+
<a href="https://www.python.org/downloads/"><img src="https://img.shields.io/pypi/pyversions/appmanager-server.svg" alt="Python Versions"></a>
|
|
70
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="License: MIT"></a>
|
|
71
|
+
</p>
|
|
72
|
+
|
|
73
|
+
# AppManager Server (`appmanager-server`)
|
|
74
|
+
|
|
75
|
+
**AppManager Server** is a high-performance Python/Flask application portal and extension framework designed to dynamically host, dispatch, and manage standalone WSGI sub-applications and modular extensions under a unified host server.
|
|
76
|
+
|
|
77
|
+
Optimized specifically for **PythonAnywhere**, cloud VMs, and multi-tenant hosting environments, AppManager provides scoped in-process module isolation, a pluggable UI slot & lifecycle hook system, automated health monitoring, telemetry reporting, live developer tooling, a headless REST API, and per-app settings configuration.
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## 🏛️ System Architecture
|
|
82
|
+
|
|
83
|
+
<p align="center">
|
|
84
|
+
<img src="docs/assets/appmanager-architecture.svg" alt="AppManager Architecture" width="100%">
|
|
85
|
+
</p>
|
|
86
|
+
|
|
87
|
+
```mermaid
|
|
88
|
+
graph LR
|
|
89
|
+
Client([🌐 Client / Browser]) --> Dispatcher[⚡ DynamicAppDispatcherMiddleware]
|
|
90
|
+
|
|
91
|
+
subgraph Host [AppManager Host Portal]
|
|
92
|
+
Dispatcher --> Auth[🔒 Authentication & Context Forwarder]
|
|
93
|
+
Auth --> DB[(🗄️ SQLite / MySQL Database)]
|
|
94
|
+
Auth --> Hooks[🧩 Hook & Slot Registry]
|
|
95
|
+
Auth --> Signals[🔔 Signal Hub & Telemetry]
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
subgraph SubApps [Installed Sub-Apps & Extensions /apps/*]
|
|
99
|
+
Auth --> FlaskApp[🚀 Standalone Flask Sub-App]
|
|
100
|
+
Auth --> APIApp[🌐 RESTful API Sub-App]
|
|
101
|
+
Auth --> ExtPlugin[🧩 UI Slot Extension Plugin]
|
|
102
|
+
Auth --> HTMXApp[⚡ HTMX Reactive Dashboard]
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
FlaskApp -. SDK Telemetry & Settings .-> Host
|
|
106
|
+
ExtPlugin -. Injects Badges & Widgets .-> Hooks
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 🚀 Key Features
|
|
112
|
+
|
|
113
|
+
- 🔌 **Standard Flask Extension (`AppManager`)**: Seamlessly embeds into existing Flask applications (`AppManager(app)`) or runs as a standalone turnkey portal.
|
|
114
|
+
- 🔀 **Dynamic WSGI Sub-App Dispatcher**: Dynamically intercepts `/apps/<slug>/*` requests via `DynamicAppDispatcherMiddleware` and dispatches requests to installed sub-apps on-the-fly.
|
|
115
|
+
- 🧩 **Pluggable Hook & UI Slot System (`appmanager.hooks`)**: Mount custom HTML badges (`user_badge`), interactive cards (`dashboard_widget`), top navigation links (`nav_item`), and assets (`head_assets`) without altering host code.
|
|
116
|
+
- 🧰 **Developer SDK (`appmanager.sdk` / `appmanager-sdk`)**: Fluent `AppManagerClient` offering `@require_auth(role=...)`, typed user identity header parsing, telemetry metrics, and extension key-value data storage.
|
|
117
|
+
- ⚙️ **Per-App Settings Configuration**: Define customizable settings schemas in `manifest.json` with live configuration from the Admin Dashboard.
|
|
118
|
+
- 👤 **Verified Context & Header Forwarding**: Injects verified non-spoofed user identity (`X-AppManager-User-Id`, `X-AppManager-User-Email`, `X-AppManager-User-Role`, `X-Forwarded-Prefix`) directly into sub-app request headers.
|
|
119
|
+
- 🛠️ **Multi-Template Scaffolding & Dev Server**: Rapidly scaffold sub-apps (`appmanager new-subapp --template [basic|api|extension|htmx|full]`) and test locally in isolation with mock auth (`appmanager dev <slug>`).
|
|
120
|
+
- 🩺 **Automated Health Monitoring**: Sub-app health evaluation contract (`/health` endpoint or `get_health()` callable) tracked in `AppHealthLog` with one-click admin execution.
|
|
121
|
+
- 📊 **In-Process Telemetry Bridge**: High-performance telemetry reporting allowing sub-apps to record events and metrics directly to the host database with zero network overhead.
|
|
122
|
+
- 🔒 **Granular Role & Permissions Matrix**: Full RBAC role management and per-user permission matrix controlling access to every installed sub-app.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## 📦 Quickstart & Installation
|
|
127
|
+
|
|
128
|
+
### 1. Install via pip
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
pip install appmanager-server
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
CLI commands available: `appmanager-server`, `appmgr-server`, `appmanager`, or `appmgr`.
|
|
135
|
+
|
|
136
|
+
### 2. Initialize and Seed
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
appmanager-server init
|
|
140
|
+
# or: appmgr-server init / appmanager init
|
|
141
|
+
appmanager seed
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### 3. Run Development Server
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
appmanager run
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Navigate to `http://localhost:5000` to access the AppManager portal.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 💻 Developer SDK & Sub-App Creation
|
|
155
|
+
|
|
156
|
+
### Scaffolding a New Sub-App or Extension
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
# Standalone Flask sub-app
|
|
160
|
+
appmanager new-subapp "Analytics Dashboard" --slug analytics --template basic
|
|
161
|
+
|
|
162
|
+
# RESTful JSON API sub-app
|
|
163
|
+
appmanager new-subapp "Payment Gateway" --slug payments --template api
|
|
164
|
+
|
|
165
|
+
# UI Slot Extension Plugin
|
|
166
|
+
appmanager new-subapp "User Badges" --slug user-badges --template extension
|
|
167
|
+
|
|
168
|
+
# Interactive HTMX sub-app
|
|
169
|
+
appmanager new-subapp "Live Monitor" --slug live-monitor --template htmx
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Local Sub-App Development Runner
|
|
173
|
+
|
|
174
|
+
Debug and test your sub-app locally with mock user authentication headers:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
appmanager dev analytics --port 5001 --email dev@example.com --role admin
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## 🛠️ Sub-App Specification (`manifest.json`)
|
|
183
|
+
|
|
184
|
+
To make an application deployable on AppManager, provide a `manifest.json` in the root:
|
|
185
|
+
|
|
186
|
+
```json
|
|
187
|
+
{
|
|
188
|
+
"name": "Analytics Dashboard",
|
|
189
|
+
"slug": "analytics",
|
|
190
|
+
"version": "1.0.0",
|
|
191
|
+
"description": "Standardized analytics sub-application.",
|
|
192
|
+
"entry_point": "app:app",
|
|
193
|
+
"health_check_path": "/health",
|
|
194
|
+
"app_type": "standalone",
|
|
195
|
+
"has_web_ui": true,
|
|
196
|
+
"settings": {
|
|
197
|
+
"api_key": {
|
|
198
|
+
"type": "string",
|
|
199
|
+
"default": "demo-key-12345",
|
|
200
|
+
"description": "API key for external data ingestion."
|
|
201
|
+
},
|
|
202
|
+
"refresh_interval_sec": {
|
|
203
|
+
"type": "number",
|
|
204
|
+
"default": 60,
|
|
205
|
+
"description": "Dashboard polling interval in seconds."
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
"scheduled_tasks": [
|
|
209
|
+
{
|
|
210
|
+
"name": "daily_aggregation",
|
|
211
|
+
"entry_point": "tasks:run_aggregation",
|
|
212
|
+
"frequency": "daily"
|
|
213
|
+
}
|
|
214
|
+
]
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Sub-App Implementation with `appmanager.sdk`
|
|
219
|
+
|
|
220
|
+
```python
|
|
221
|
+
from flask import Flask, jsonify, request
|
|
222
|
+
from appmanager.sdk import AppManagerClient
|
|
223
|
+
|
|
224
|
+
app = Flask(__name__)
|
|
225
|
+
client = AppManagerClient("analytics")
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
@app.route("/")
|
|
229
|
+
@client.require_auth(role="user")
|
|
230
|
+
def index():
|
|
231
|
+
user = client.get_current_user(request.headers)
|
|
232
|
+
api_key = client.get_setting("api_key", default="demo-key")
|
|
233
|
+
client.report_event("dashboard_view", {"user_id": user["id"]})
|
|
234
|
+
|
|
235
|
+
return f"<h1>Welcome, {user['email']}</h1><p>Active API Key: {api_key}</p>"
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
@app.route("/health")
|
|
239
|
+
def health():
|
|
240
|
+
return jsonify({"status": "healthy", "app": "analytics"})
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
if __name__ == "__main__":
|
|
244
|
+
app.run(port=5001, debug=True)
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## 🧩 Pluggable UI Slots & Extension Hooks
|
|
250
|
+
|
|
251
|
+
Extensions can inject components into host slots:
|
|
252
|
+
|
|
253
|
+
```python
|
|
254
|
+
from markupsafe import Markup
|
|
255
|
+
from appmanager.sdk import AppManagerClient
|
|
256
|
+
|
|
257
|
+
client = AppManagerClient("banner-extension")
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def render_dashboard_widget(user=None):
|
|
261
|
+
return Markup('<div class="card">✨ Custom analytics summary card</div>')
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
# Register to the host dashboard
|
|
265
|
+
client.register_slot("dashboard_widget", render_dashboard_widget, priority=5)
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Available UI slots:
|
|
269
|
+
- `user_badge`: Injected next to user names across profiles, tables, and headers.
|
|
270
|
+
- `dashboard_widget`: Mounted on the main `/dashboard` landing view.
|
|
271
|
+
- `nav_item`: Injected into the top navigation header bar.
|
|
272
|
+
- `head_assets`: Injected into the HTML `<head>` tag.
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## 🖥️ CLI Commands
|
|
277
|
+
|
|
278
|
+
| Command | Description |
|
|
279
|
+
| :--- | :--- |
|
|
280
|
+
| `appmanager init` | Bootstrap local directory with `installed_apps/` and `.env` template |
|
|
281
|
+
| `appmanager run` | Start the WSGI dynamic dispatcher host server |
|
|
282
|
+
| `appmanager dev <slug>` | Run standalone local test server with mock authentication |
|
|
283
|
+
| `appmanager seed` | Seed database with default starter apps, roles, and flairs |
|
|
284
|
+
| `appmanager new-subapp <name>` | Scaffold a sub-app with templates (`basic`, `api`, `extension`, `htmx`, `full`) |
|
|
285
|
+
| `appmanager validate-subapp <path>` | Validate a sub-app folder or ZIP package against manifest rules |
|
|
286
|
+
| `appmanager export-app <slug>` | Package an installed sub-app into a deployable ZIP archive |
|
|
287
|
+
| `appmanager reload-app <slug>` | Invalidate in-memory WSGI cache for zero-downtime updates |
|
|
288
|
+
| `appmanager hooks` | Inspect all registered UI slots, lifecycle hooks, and listeners |
|
|
289
|
+
| `appmanager check-health` | Run health evaluation checks across all active sub-apps |
|
|
290
|
+
| `appmanager run-scheduled-tasks` | Run background scheduled cron jobs and maintenance |
|
|
291
|
+
| `appmanager list-apps` | List all registered applications and their operational status |
|
|
292
|
+
| `appmanager list-users` | List all registered users and their assigned roles |
|
|
293
|
+
| `appmanager set-role <email>` | Elevate or update user role (`admin` or `user`) |
|
|
294
|
+
| `appmanager list-roles` | List all system and custom RBAC roles |
|
|
295
|
+
| `appmanager create-role <name>` | Create a new custom RBAC role |
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## 📖 Documentation
|
|
300
|
+
|
|
301
|
+
Full documentation is available at [https://appmanager.github.io/appmanager](https://appmanager.github.io/appmanager):
|
|
302
|
+
- [Getting Started](https://appmanager.github.io/appmanager/getting-started/)
|
|
303
|
+
- [Sub-App Development Guide](https://appmanager.github.io/appmanager/sub-apps/)
|
|
304
|
+
- [Hook & Slot Extension Guide](https://appmanager.github.io/appmanager/sub-apps/#ui-slots--extension-hooks)
|
|
305
|
+
- [Configuration & Settings Reference](https://appmanager.github.io/appmanager/configuration/)
|
|
306
|
+
- [PythonAnywhere & WSGI Deployment](https://appmanager.github.io/appmanager/deployment/)
|
|
307
|
+
- [CLI Reference](https://appmanager.github.io/appmanager/cli/)
|
|
308
|
+
- [Python API Reference](https://appmanager.github.io/appmanager/api/)
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## 🤝 Contributing
|
|
313
|
+
|
|
314
|
+
Contributions are welcome! Please check out [CONTRIBUTING.md](CONTRIBUTING.md) and our [Code of Conduct](CODE_OF_CONDUCT.md).
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## 📄 License
|
|
319
|
+
|
|
320
|
+
This project is licensed under the terms of the [MIT License](LICENSE).
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
appmanager/__init__.py,sha256=fB9XjEp2UKAGh_0_ys9DBaT3EgtiJweSSZV3r1S_Pb4,1429
|
|
2
|
+
appmanager/app_config.py,sha256=28PsFjviC0E-CXgeqf1SGLnYLfolUodRB5RN6VPt3es,3291
|
|
3
|
+
appmanager/bridge.py,sha256=5hpvoL9W3ZUusy9gUWac-1Hk2sRRZdKOJmv0ZTjTpR0,2871
|
|
4
|
+
appmanager/cli.py,sha256=Y-JedYy2b-7J8WIiFW-uLHhvvjSlh8xwKLl03EH2rv4,43368
|
|
5
|
+
appmanager/config.py,sha256=7eP9KytNFbq41lvEhXzsF_YIeqWY1n2-bwAqe8W14wU,2251
|
|
6
|
+
appmanager/database.py,sha256=HEmDzoo6Rd3-c_4PKY79peQ6EViiEGKLuYvejj0lyyI,5151
|
|
7
|
+
appmanager/extension.py,sha256=hoftCeXZTrt1CxLGLVm4ONuBpA65QBacuW_2Qz3Pf6E,7329
|
|
8
|
+
appmanager/extensions.py,sha256=85eaTx0OE0RTcc2WetQWbFu7BbTLNUV5GH_fofy5n1c,7889
|
|
9
|
+
appmanager/health.py,sha256=-JbtlHJov3LdSR_NHnNIUE6fkSZbMziu-gz7638tdDU,4796
|
|
10
|
+
appmanager/hooks.py,sha256=Ad46orPZ-CS2BEBoRE6rUSP1kmgVulFZI2XYFkM9SSk,6285
|
|
11
|
+
appmanager/middleware.py,sha256=iXwziZ8VzDygTo7WE7bM9e5UZGrV4XKXE4YBxO6cubQ,11052
|
|
12
|
+
appmanager/models.py,sha256=t3Dx3uUlqD38SaFC9Cif7aNVeboRKIkfVwcR9hld4X0,11770
|
|
13
|
+
appmanager/py.typed,sha256=bWew9mHgMy8LqMu7RuqQXFXLBxh2CRx0dUbSx-3wE48,27
|
|
14
|
+
appmanager/sdk.py,sha256=BwMOwlyGf6u7ItBLRNPVM6aRhVvkjjeym7gZ7zuIQZw,577
|
|
15
|
+
appmanager/security.py,sha256=8a2fPY6sTULs37sT2AWz-jrEppUMQ07YXWYwMKfH1pw,8281
|
|
16
|
+
appmanager/security_scanner.py,sha256=w-q1BdeEz99kItyUCUZqkJX0GkuvUU7Ltk8kbKi8aB8,22012
|
|
17
|
+
appmanager/signals.py,sha256=dAHOhS0MNTzeVYuu7n0RtjKC7W01Rhp_xMC_UBgpwwQ,640
|
|
18
|
+
appmanager/admin/__init__.py,sha256=ft9m2Y85sGfmcShQm4O_8Do_UOqWExu3FTA73B3RR48,69
|
|
19
|
+
appmanager/admin/app_installer.py,sha256=Py4Yv2MhIhILS9DK-iPYmbEAf_1126Zh7aiXHuVTIs8,27392
|
|
20
|
+
appmanager/admin/members.py,sha256=R5JSH1ppkBBVTO-pYTxjXGZ5hariGU0tFbUH7njbHRs,2914
|
|
21
|
+
appmanager/admin/registry.py,sha256=iP8r9AaKJpafoJThIP06FYPJ6fdtEi_BpAewUCzSSBw,13911
|
|
22
|
+
appmanager/admin/routes.py,sha256=jfjW1Q-0-VJzOwOp620B6rJyI8YQkKrlwHudbPfOQ50,30567
|
|
23
|
+
appmanager/api/__init__.py,sha256=h7wQ0h6yT4M8oEaIR6yTlkp9l9QBn550iKah4iQ2NY0,142
|
|
24
|
+
appmanager/api/routes.py,sha256=a_SBI5LwM7d_sJB8tJCG1NFMe8sHi2N8N43JdPG5hdo,12574
|
|
25
|
+
appmanager/auth/__init__.py,sha256=TJE7qpIGNZzivoYzP-MxPPxBO92VvVTkouNvmdRxDOs,66
|
|
26
|
+
appmanager/auth/oauth.py,sha256=_6z4toSNMY3VOHBUXtQJ2dQqZ4Wy5d0aOdUAhHMG5AU,2375
|
|
27
|
+
appmanager/auth/routes.py,sha256=tJQWptA2FzqgZ9mIxvzS9qzkZClts2ihZx6S217Goxk,7438
|
|
28
|
+
appmanager/auth/utils.py,sha256=0r7eYfznnsdSyO-CTdX1PgFrAXiVjB135cP_C-XoUnw,6272
|
|
29
|
+
appmanager/static/css/app.css,sha256=SHfVXfuMaBBZ6oll3aOVGkNVkPtydT3kDQjESpT_6N0,30234
|
|
30
|
+
appmanager/static/vendor/fonts/fonts.css,sha256=yVDimL64odFqGXwctH7FRz96Y9vMKsHSqUe93VFRv08,11451
|
|
31
|
+
appmanager/static/vendor/fonts/jetbrainsmono-0.woff2,sha256=YiE76KeLQvHinRRS2R4viz50VXKp3ZjTlB45-gCzfXY,1640
|
|
32
|
+
appmanager/static/vendor/fonts/jetbrainsmono-1.woff2,sha256=4Xz9FfuWkJ1kCVAV-VggcGOgwHGR2jUS331WCnga698,8872
|
|
33
|
+
appmanager/static/vendor/fonts/jetbrainsmono-10.woff2,sha256=21_024PlgEJigOkzeljcV9OoN4ShsDrYCRRlFZREHVI,11624
|
|
34
|
+
appmanager/static/vendor/fonts/jetbrainsmono-11.woff2,sha256=g8AF1J2KalBHTHOlo2rARoB26cSinae9sUmV2AVgpb4,31432
|
|
35
|
+
appmanager/static/vendor/fonts/jetbrainsmono-12.woff2,sha256=YiE76KeLQvHinRRS2R4viz50VXKp3ZjTlB45-gCzfXY,1640
|
|
36
|
+
appmanager/static/vendor/fonts/jetbrainsmono-13.woff2,sha256=4Xz9FfuWkJ1kCVAV-VggcGOgwHGR2jUS331WCnga698,8872
|
|
37
|
+
appmanager/static/vendor/fonts/jetbrainsmono-14.woff2,sha256=ClV3IbH4s20_P4REJomnHKSnRDAKvLRqGVP1G_xmO2Y,6836
|
|
38
|
+
appmanager/static/vendor/fonts/jetbrainsmono-15.woff2,sha256=yJucwLxiYr1PjYSUtpYWAfOu-oKdCMLjY19NUB06R8I,5888
|
|
39
|
+
appmanager/static/vendor/fonts/jetbrainsmono-16.woff2,sha256=21_024PlgEJigOkzeljcV9OoN4ShsDrYCRRlFZREHVI,11624
|
|
40
|
+
appmanager/static/vendor/fonts/jetbrainsmono-17.woff2,sha256=g8AF1J2KalBHTHOlo2rARoB26cSinae9sUmV2AVgpb4,31432
|
|
41
|
+
appmanager/static/vendor/fonts/jetbrainsmono-18.woff2,sha256=YiE76KeLQvHinRRS2R4viz50VXKp3ZjTlB45-gCzfXY,1640
|
|
42
|
+
appmanager/static/vendor/fonts/jetbrainsmono-19.woff2,sha256=4Xz9FfuWkJ1kCVAV-VggcGOgwHGR2jUS331WCnga698,8872
|
|
43
|
+
appmanager/static/vendor/fonts/jetbrainsmono-2.woff2,sha256=ClV3IbH4s20_P4REJomnHKSnRDAKvLRqGVP1G_xmO2Y,6836
|
|
44
|
+
appmanager/static/vendor/fonts/jetbrainsmono-20.woff2,sha256=ClV3IbH4s20_P4REJomnHKSnRDAKvLRqGVP1G_xmO2Y,6836
|
|
45
|
+
appmanager/static/vendor/fonts/jetbrainsmono-21.woff2,sha256=yJucwLxiYr1PjYSUtpYWAfOu-oKdCMLjY19NUB06R8I,5888
|
|
46
|
+
appmanager/static/vendor/fonts/jetbrainsmono-22.woff2,sha256=21_024PlgEJigOkzeljcV9OoN4ShsDrYCRRlFZREHVI,11624
|
|
47
|
+
appmanager/static/vendor/fonts/jetbrainsmono-23.woff2,sha256=g8AF1J2KalBHTHOlo2rARoB26cSinae9sUmV2AVgpb4,31432
|
|
48
|
+
appmanager/static/vendor/fonts/jetbrainsmono-3.woff2,sha256=yJucwLxiYr1PjYSUtpYWAfOu-oKdCMLjY19NUB06R8I,5888
|
|
49
|
+
appmanager/static/vendor/fonts/jetbrainsmono-4.woff2,sha256=21_024PlgEJigOkzeljcV9OoN4ShsDrYCRRlFZREHVI,11624
|
|
50
|
+
appmanager/static/vendor/fonts/jetbrainsmono-5.woff2,sha256=g8AF1J2KalBHTHOlo2rARoB26cSinae9sUmV2AVgpb4,31432
|
|
51
|
+
appmanager/static/vendor/fonts/jetbrainsmono-6.woff2,sha256=YiE76KeLQvHinRRS2R4viz50VXKp3ZjTlB45-gCzfXY,1640
|
|
52
|
+
appmanager/static/vendor/fonts/jetbrainsmono-7.woff2,sha256=4Xz9FfuWkJ1kCVAV-VggcGOgwHGR2jUS331WCnga698,8872
|
|
53
|
+
appmanager/static/vendor/fonts/jetbrainsmono-8.woff2,sha256=ClV3IbH4s20_P4REJomnHKSnRDAKvLRqGVP1G_xmO2Y,6836
|
|
54
|
+
appmanager/static/vendor/fonts/jetbrainsmono-9.woff2,sha256=yJucwLxiYr1PjYSUtpYWAfOu-oKdCMLjY19NUB06R8I,5888
|
|
55
|
+
appmanager/static/vendor/fonts/spacegrotesk-0.woff2,sha256=iJXj1JglEov6UjjkyW6bQy16Pa2-XBfGCBJnOYMF3HE,6712
|
|
56
|
+
appmanager/static/vendor/fonts/spacegrotesk-1.woff2,sha256=lS3dtF0vlvccvzt_UQskN5r8PInqAvz4nTd7RdYsAWY,18940
|
|
57
|
+
appmanager/static/vendor/fonts/spacegrotesk-10.woff2,sha256=lS3dtF0vlvccvzt_UQskN5r8PInqAvz4nTd7RdYsAWY,18940
|
|
58
|
+
appmanager/static/vendor/fonts/spacegrotesk-11.woff2,sha256=BkCJBHb8EZirTeVx-2WN5EPE2FtmRm7AlTSoc3qxzp0,22288
|
|
59
|
+
appmanager/static/vendor/fonts/spacegrotesk-2.woff2,sha256=BkCJBHb8EZirTeVx-2WN5EPE2FtmRm7AlTSoc3qxzp0,22288
|
|
60
|
+
appmanager/static/vendor/fonts/spacegrotesk-3.woff2,sha256=iJXj1JglEov6UjjkyW6bQy16Pa2-XBfGCBJnOYMF3HE,6712
|
|
61
|
+
appmanager/static/vendor/fonts/spacegrotesk-4.woff2,sha256=lS3dtF0vlvccvzt_UQskN5r8PInqAvz4nTd7RdYsAWY,18940
|
|
62
|
+
appmanager/static/vendor/fonts/spacegrotesk-5.woff2,sha256=BkCJBHb8EZirTeVx-2WN5EPE2FtmRm7AlTSoc3qxzp0,22288
|
|
63
|
+
appmanager/static/vendor/fonts/spacegrotesk-6.woff2,sha256=iJXj1JglEov6UjjkyW6bQy16Pa2-XBfGCBJnOYMF3HE,6712
|
|
64
|
+
appmanager/static/vendor/fonts/spacegrotesk-7.woff2,sha256=lS3dtF0vlvccvzt_UQskN5r8PInqAvz4nTd7RdYsAWY,18940
|
|
65
|
+
appmanager/static/vendor/fonts/spacegrotesk-8.woff2,sha256=BkCJBHb8EZirTeVx-2WN5EPE2FtmRm7AlTSoc3qxzp0,22288
|
|
66
|
+
appmanager/static/vendor/fonts/spacegrotesk-9.woff2,sha256=iJXj1JglEov6UjjkyW6bQy16Pa2-XBfGCBJnOYMF3HE,6712
|
|
67
|
+
appmanager/static/vendor/htmx/htmx.min.js,sha256=RJMXreeIHpSVENthSZHhlcOgmcTHkcJNrOxV-fSipFI,48101
|
|
68
|
+
appmanager/templates/base.html,sha256=mlkcVJkgy9p-YRwt1SapCX-KWu9Jcr4x6tW3vGzMGGc,3202
|
|
69
|
+
appmanager/templates/index.html,sha256=EQtid6aCXY4lMNsmLAgeVjdyV9c3UzyaSF0C8pAh9cs,2278
|
|
70
|
+
appmanager/templates/admin/_member_drawer.html,sha256=6PLC4jVOpcsxUjb0jkl1wkd8eMqt-IY13m3ygAcf_ms,5345
|
|
71
|
+
appmanager/templates/admin/_members_table.html,sha256=7Ts-I058NVmOPWmymRA3etBoWppJGzypYnATXSKb1VA,5616
|
|
72
|
+
appmanager/templates/admin/app_detail.html,sha256=ZHVY7lXQmgmyUiH4tjnkorj-N7Eh4jxQhgbSRpV-JEk,7006
|
|
73
|
+
appmanager/templates/admin/dashboard.html,sha256=sc8BTn-zUareZ4Wh2AtLIqyzdsjvoshBspHoavxbr4A,48303
|
|
74
|
+
appmanager/templates/admin/flairs.html,sha256=Zg-MK_8OuAcdWJ5bEBBjmg7w-0MnkDEbJ-Hi1OCqVow,5409
|
|
75
|
+
appmanager/templates/admin/permissions.html,sha256=gvjd24uaRH6WR0CiG3F_PyTjAhMBTnRwoqm3OoIAq8w,3746
|
|
76
|
+
appmanager/templates/admin/roles.html,sha256=wFq-1YXljZd5tUX6sgjV50x2DWROif7-0Lg_XRBFUZc,6204
|
|
77
|
+
appmanager/templates/admin/users.html,sha256=JyqcRUp4k6Bk4skP5NOr7mCiFwBXRM6X8C6jbSPfJDY,11454
|
|
78
|
+
appmanager/templates/auth/login.html,sha256=t4ouI_VgUypxtLZyRE2KbAccSHJFrtYWgDv_hFA4qoI,3500
|
|
79
|
+
appmanager/templates/auth/profile.html,sha256=HWXuSnxkojVbnxZ4zqt1GdRd8qauT38N-BCpkyvZe-s,1962
|
|
80
|
+
appmanager/templates/errors/401.html,sha256=MRBkiPWki4EzUS3kPSCQSEbJgWIvM9_CO74Pn9pl39U,1004
|
|
81
|
+
appmanager/templates/errors/403.html,sha256=-os4ImOyx9m0xzrfcUYetvWsUHg-q5khEVUitPvq2ME,1028
|
|
82
|
+
appmanager/templates/errors/404.html,sha256=VPFAXI2Q-oCI4VpmLzV45tyR9FqTgqBkb5_9e4Tjhos,938
|
|
83
|
+
appmanager/templates/errors/500.html,sha256=1pbGuQSF3iDWRnHIAS228H_SsA5SM-YJcFsgMJN1CN4,1088
|
|
84
|
+
appmanager_server-0.2.0.dist-info/licenses/LICENSE,sha256=qY1OzUfb40jXi0TraUNB5gVksYQUMRPNXTJyyLd0EMo,1080
|
|
85
|
+
appmanager_server-0.2.0.dist-info/METADATA,sha256=fMbjTZP0xvC6ythjqdrOPz3WFyb3hB-msAuym6Yeux8,12940
|
|
86
|
+
appmanager_server-0.2.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
87
|
+
appmanager_server-0.2.0.dist-info/entry_points.txt,sha256=QVR-FLkvt0DlE2QdhMyKrwnXAcD1N3d1N_YmBPWptPQ,156
|
|
88
|
+
appmanager_server-0.2.0.dist-info/top_level.txt,sha256=KJpiBWALar-zQTpA9mX9cNbdRcN4NQ67m3gkcnrKkD0,11
|
|
89
|
+
appmanager_server-0.2.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AppManager Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
appmanager
|