aa-srp-access 0.1.0__tar.gz
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.
- aa_srp_access-0.1.0/.github/workflows/release.yml +40 -0
- aa_srp_access-0.1.0/.github/workflows/tests.yml +38 -0
- aa_srp_access-0.1.0/.gitignore +10 -0
- aa_srp_access-0.1.0/CHANGELOG.md +13 -0
- aa_srp_access-0.1.0/LICENSE +21 -0
- aa_srp_access-0.1.0/PKG-INFO +214 -0
- aa_srp_access-0.1.0/README.md +164 -0
- aa_srp_access-0.1.0/pyproject.toml +58 -0
- aa_srp_access-0.1.0/srp_access/__init__.py +3 -0
- aa_srp_access-0.1.0/srp_access/access.py +79 -0
- aa_srp_access-0.1.0/srp_access/admin.py +39 -0
- aa_srp_access-0.1.0/srp_access/apps.py +8 -0
- aa_srp_access-0.1.0/srp_access/auth_hooks.py +33 -0
- aa_srp_access-0.1.0/srp_access/forms.py +5 -0
- aa_srp_access-0.1.0/srp_access/migrations/0001_initial.py +77 -0
- aa_srp_access-0.1.0/srp_access/migrations/0002_alter_exposedsrpfleet_fleet_and_more.py +37 -0
- aa_srp_access-0.1.0/srp_access/migrations/__init__.py +1 -0
- aa_srp_access-0.1.0/srp_access/models.py +56 -0
- aa_srp_access-0.1.0/srp_access/services.py +65 -0
- aa_srp_access-0.1.0/srp_access/static/srp_access/css/srp_access.css +1 -0
- aa_srp_access-0.1.0/srp_access/templates/srp_access/fleet_detail.html +27 -0
- aa_srp_access-0.1.0/srp_access/templates/srp_access/fleet_list.html +45 -0
- aa_srp_access-0.1.0/srp_access/templates/srp_access/request.html +20 -0
- aa_srp_access-0.1.0/srp_access/tests/__init__.py +1 -0
- aa_srp_access-0.1.0/srp_access/tests/test_access.py +68 -0
- aa_srp_access-0.1.0/srp_access/tests/test_views.py +150 -0
- aa_srp_access-0.1.0/srp_access/urls.py +11 -0
- aa_srp_access-0.1.0/srp_access/views.py +61 -0
- aa_srp_access-0.1.0/testauth/__init__.py +1 -0
- aa_srp_access-0.1.0/testauth/manage.py +10 -0
- aa_srp_access-0.1.0/testauth/settings.py +33 -0
- aa_srp_access-0.1.0/testauth/urls.py +5 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
build:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v4
|
|
12
|
+
- uses: actions/setup-python@v5
|
|
13
|
+
with:
|
|
14
|
+
python-version: "3.12"
|
|
15
|
+
- name: Install build tools
|
|
16
|
+
run: python -m pip install --upgrade build twine
|
|
17
|
+
- name: Build distributions
|
|
18
|
+
run: python -m build
|
|
19
|
+
- name: Validate distributions
|
|
20
|
+
run: python -m twine check dist/*
|
|
21
|
+
- uses: actions/upload-artifact@v4
|
|
22
|
+
with:
|
|
23
|
+
name: python-package-distributions
|
|
24
|
+
path: dist/
|
|
25
|
+
|
|
26
|
+
publish:
|
|
27
|
+
needs: build
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
environment:
|
|
30
|
+
name: pypi
|
|
31
|
+
url: https://pypi.org/p/aa-srp-access
|
|
32
|
+
permissions:
|
|
33
|
+
id-token: write
|
|
34
|
+
steps:
|
|
35
|
+
- uses: actions/download-artifact@v4
|
|
36
|
+
with:
|
|
37
|
+
name: python-package-distributions
|
|
38
|
+
path: dist/
|
|
39
|
+
- name: Publish to PyPI with Trusted Publishing
|
|
40
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
test:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
services:
|
|
11
|
+
redis:
|
|
12
|
+
image: redis:7
|
|
13
|
+
ports:
|
|
14
|
+
- 6379:6379
|
|
15
|
+
options: >-
|
|
16
|
+
--health-cmd "redis-cli ping"
|
|
17
|
+
--health-interval 10s
|
|
18
|
+
--health-timeout 5s
|
|
19
|
+
--health-retries 5
|
|
20
|
+
steps:
|
|
21
|
+
- uses: actions/checkout@v4
|
|
22
|
+
- uses: actions/setup-python@v5
|
|
23
|
+
with:
|
|
24
|
+
python-version: "3.12"
|
|
25
|
+
cache: pip
|
|
26
|
+
- name: Install package and test tools
|
|
27
|
+
run: python -m pip install --upgrade pip ".[test]"
|
|
28
|
+
- name: Django checks and tests
|
|
29
|
+
env:
|
|
30
|
+
DJANGO_SETTINGS_MODULE: testauth.settings
|
|
31
|
+
run: |
|
|
32
|
+
python -m django check
|
|
33
|
+
python -m django makemigrations srp_access --check --dry-run
|
|
34
|
+
python -m django test srp_access.tests
|
|
35
|
+
- name: Build distributions
|
|
36
|
+
run: python -m build
|
|
37
|
+
- name: Validate distributions
|
|
38
|
+
run: python -m twine check dist/*
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The project follows
|
|
4
|
+
Semantic Versioning.
|
|
5
|
+
|
|
6
|
+
## 0.1.0 - 2026-09-12
|
|
7
|
+
|
|
8
|
+
- Add configurable State and Group authorization.
|
|
9
|
+
- Add mappings for explicitly exposed built-in SRP fleets.
|
|
10
|
+
- Add restricted fleet list, detail, and request submission views.
|
|
11
|
+
- Store submissions as normal Alliance Auth built-in `SrpUserRequest` records.
|
|
12
|
+
- Add server-side direct URL protection, administration, tests, packaging, and
|
|
13
|
+
Trusted Publishing workflow.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 aa-srp-access 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,214 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: aa-srp-access
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Restricted, configurable access to Alliance Auth's built-in SRP
|
|
5
|
+
Project-URL: Homepage, https://github.com/thegriffenkd/aa-srp-access
|
|
6
|
+
Project-URL: Changelog, https://github.com/thegriffenkd/aa-srp-access/blob/main/CHANGELOG.md
|
|
7
|
+
Project-URL: Issues, https://github.com/thegriffenkd/aa-srp-access/issues
|
|
8
|
+
Project-URL: Source, https://github.com/thegriffenkd/aa-srp-access
|
|
9
|
+
Author: aa-srp-access contributors
|
|
10
|
+
License: MIT License
|
|
11
|
+
|
|
12
|
+
Copyright (c) 2026 aa-srp-access contributors
|
|
13
|
+
|
|
14
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
15
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
16
|
+
in the Software without restriction, including without limitation the rights
|
|
17
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
18
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
19
|
+
furnished to do so, subject to the following conditions:
|
|
20
|
+
|
|
21
|
+
The above copyright notice and this permission notice shall be included in all
|
|
22
|
+
copies or substantial portions of the Software.
|
|
23
|
+
|
|
24
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
25
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
26
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
27
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
28
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
29
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
30
|
+
SOFTWARE.
|
|
31
|
+
License-File: LICENSE
|
|
32
|
+
Classifier: Development Status :: 3 - Alpha
|
|
33
|
+
Classifier: Environment :: Web Environment
|
|
34
|
+
Classifier: Framework :: Django :: 5.2
|
|
35
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
36
|
+
Classifier: Programming Language :: Python :: 3
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
42
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
43
|
+
Requires-Python: <3.15,>=3.10
|
|
44
|
+
Requires-Dist: allianceauth<5.3,>=5.2
|
|
45
|
+
Requires-Dist: django-solo<3,>=2.5
|
|
46
|
+
Provides-Extra: test
|
|
47
|
+
Requires-Dist: build>=1.2; extra == 'test'
|
|
48
|
+
Requires-Dist: twine>=5; extra == 'test'
|
|
49
|
+
Description-Content-Type: text/markdown
|
|
50
|
+
|
|
51
|
+
# aa-srp-access
|
|
52
|
+
|
|
53
|
+
`aa-srp-access` is a standalone Alliance Auth application that provides a
|
|
54
|
+
restricted frontend for Alliance Auth's built-in Ship Replacement Program
|
|
55
|
+
(SRP). It does not replace the built-in SRP backend or administration.
|
|
56
|
+
|
|
57
|
+
Restricted users can access the frontend only when both conditions are true:
|
|
58
|
+
|
|
59
|
+
- their Alliance Auth State is eligible; and
|
|
60
|
+
- they belong to the configured Django/Alliance Auth Group.
|
|
61
|
+
|
|
62
|
+
They see only built-in SRP fleets explicitly exposed by an administrator.
|
|
63
|
+
Requests are stored as normal built-in `SrpUserRequest` records, so existing
|
|
64
|
+
SRP administrators continue to approve, reject, update, and pay them through
|
|
65
|
+
the normal Alliance Auth SRP interface.
|
|
66
|
+
|
|
67
|
+
## Compatibility
|
|
68
|
+
|
|
69
|
+
- Alliance Auth `5.2.x`
|
|
70
|
+
- Python `3.10` through `3.14`, matching Alliance Auth 5.2 metadata
|
|
71
|
+
- Django `5.2.x`, supplied by Alliance Auth
|
|
72
|
+
|
|
73
|
+
The initial compatibility target is Alliance Auth 5.2.0. Test upgrades before
|
|
74
|
+
changing either the Alliance Auth or app version constraint.
|
|
75
|
+
|
|
76
|
+
## Security model
|
|
77
|
+
|
|
78
|
+
Every plugin view performs server-side authorization. Navigation visibility is
|
|
79
|
+
only a convenience and is not treated as access control. A submitted fleet ID
|
|
80
|
+
is re-queried through the authorized fleet queryset, and an unexposed fleet
|
|
81
|
+
returns a safe 404. Anonymous users are redirected to login; authenticated
|
|
82
|
+
users who fail the State or Group check receive 403.
|
|
83
|
+
|
|
84
|
+
State, Group, and fleet names are never authorization constants. Configuration
|
|
85
|
+
uses database relations to `authentication.State`, `auth.Group`, and the
|
|
86
|
+
built-in `srp.SrpFleetMain` model.
|
|
87
|
+
|
|
88
|
+
## Requirements
|
|
89
|
+
|
|
90
|
+
- A working Alliance Auth 5.2 installation with built-in SRP enabled
|
|
91
|
+
- Django admin access
|
|
92
|
+
- The built-in `auth.srp_management` permission for app configuration
|
|
93
|
+
|
|
94
|
+
## Installation
|
|
95
|
+
|
|
96
|
+
Add a pinned release to the Alliance Auth requirements file:
|
|
97
|
+
|
|
98
|
+
```text
|
|
99
|
+
aa-srp-access==0.1.0
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Add the Python module to local settings:
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
INSTALLED_APPS += [
|
|
106
|
+
"srp_access",
|
|
107
|
+
]
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Rebuild the application image, then run:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
python manage.py migrate srp_access
|
|
114
|
+
python manage.py collectstatic --noinput
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Restart the web, worker, and scheduler processes using the deployment's normal
|
|
118
|
+
procedure. No Alliance Auth core files or core migrations are changed.
|
|
119
|
+
|
|
120
|
+
## Docker installation
|
|
121
|
+
|
|
122
|
+
Service names vary between deployments. From the correct Compose project
|
|
123
|
+
directory, the usual sequence is:
|
|
124
|
+
|
|
125
|
+
1. Add `aa-srp-access==0.1.0` to `conf/requirements.txt`.
|
|
126
|
+
2. Add `srp_access` to `INSTALLED_APPS` in local Django settings.
|
|
127
|
+
3. Rebuild the Alliance Auth image with `docker compose build`.
|
|
128
|
+
4. Run `docker compose run --rm <web-service> python manage.py migrate srp_access`.
|
|
129
|
+
5. Run `docker compose run --rm <web-service> python manage.py collectstatic --noinput`.
|
|
130
|
+
6. Recreate the web, workers, and beat/scheduler services.
|
|
131
|
+
7. Verify container health and both the standard and restricted SRP pages.
|
|
132
|
+
|
|
133
|
+
Back up the database and configuration first. Determine the correct Compose
|
|
134
|
+
project and service names before running commands; do not copy the examples
|
|
135
|
+
blindly into a production deployment.
|
|
136
|
+
|
|
137
|
+
## Initial configuration
|
|
138
|
+
|
|
139
|
+
1. Sign in to Django admin as a staff user with `auth.srp_management`.
|
|
140
|
+
2. Open **Restricted SRP settings**.
|
|
141
|
+
3. Select the required access Group.
|
|
142
|
+
4. Choose State behavior:
|
|
143
|
+
- enable **allow any public state** to require `State.public=True`; or
|
|
144
|
+
- disable it and select one or more specific State objects.
|
|
145
|
+
5. Add **Exposed SRP fleet** rows for existing built-in SRP fleets.
|
|
146
|
+
6. Leave an exposure enabled only while that fleet should be available.
|
|
147
|
+
|
|
148
|
+
An exposed fleet must also be open in built-in SRP: it needs a non-empty SRP
|
|
149
|
+
code and an incomplete status. Disabling or completing it in built-in SRP
|
|
150
|
+
removes it from the restricted list without deleting the exposure mapping.
|
|
151
|
+
|
|
152
|
+
## Permissions and groups
|
|
153
|
+
|
|
154
|
+
The access Group is application data selected in admin; its name is not fixed.
|
|
155
|
+
State eligibility and Group membership are both mandatory. Superuser or staff
|
|
156
|
+
status does not bypass the restricted frontend's State-and-Group rule.
|
|
157
|
+
|
|
158
|
+
Configuration in Django admin is guarded by Alliance Auth's existing
|
|
159
|
+
`auth.srp_management` permission. Normal built-in SRP permissions and pages are
|
|
160
|
+
not modified.
|
|
161
|
+
|
|
162
|
+
## How to expose fleets
|
|
163
|
+
|
|
164
|
+
Create fleets through the normal built-in SRP interface. In Django admin, add
|
|
165
|
+
an **Exposed SRP fleet** mapping and select the existing fleet object. The
|
|
166
|
+
one-to-one relation prevents duplicate mappings. Removing a built-in fleet also
|
|
167
|
+
removes its exposure mapping; it does not affect unrelated SRP data.
|
|
168
|
+
|
|
169
|
+
## Upgrading
|
|
170
|
+
|
|
171
|
+
1. Back up the Alliance Auth database and configuration.
|
|
172
|
+
2. Pin the desired `aa-srp-access` version in requirements.
|
|
173
|
+
3. Rebuild the image.
|
|
174
|
+
4. Run `python manage.py migrate srp_access`.
|
|
175
|
+
5. Run `collectstatic` when release notes require it.
|
|
176
|
+
6. Recreate services and verify both SRP frontends.
|
|
177
|
+
|
|
178
|
+
Test Alliance Auth upgrades on a test server with the currently pinned plugin
|
|
179
|
+
version before upgrading production.
|
|
180
|
+
|
|
181
|
+
## Uninstall considerations
|
|
182
|
+
|
|
183
|
+
Removing the app does not remove built-in SRP fleets or requests. Plugin-owned
|
|
184
|
+
settings and exposure mappings remain in the database unless their tables are
|
|
185
|
+
explicitly removed. Back up first; do not reverse migrations casually on a
|
|
186
|
+
production installation. Remove `srp_access` from `INSTALLED_APPS` only after
|
|
187
|
+
planning whether to retain or remove those plugin tables.
|
|
188
|
+
|
|
189
|
+
## Development and testing
|
|
190
|
+
|
|
191
|
+
Run tests against a Redis instance on localhost database 15:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
python -m django test srp_access.tests --settings=testauth.settings
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Build and validate distributions:
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
python -m pip install --upgrade build twine
|
|
201
|
+
python -m build
|
|
202
|
+
python -m twine check dist/*
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
The test suite uses SQLite and arbitrary fixture names. It covers anonymous,
|
|
206
|
+
State, Group, exposed-fleet, direct URL, submission, built-in SRP regression,
|
|
207
|
+
and built-in administrator behavior.
|
|
208
|
+
|
|
209
|
+
## Release process
|
|
210
|
+
|
|
211
|
+
Update the changelog and version, merge tested changes, and create a deliberate
|
|
212
|
+
GitHub Release. The release workflow builds and validates wheel/sdist artifacts
|
|
213
|
+
before publishing through a PyPI Trusted Publisher and the protected `pypi`
|
|
214
|
+
GitHub environment. Ordinary pushes never publish.
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# aa-srp-access
|
|
2
|
+
|
|
3
|
+
`aa-srp-access` is a standalone Alliance Auth application that provides a
|
|
4
|
+
restricted frontend for Alliance Auth's built-in Ship Replacement Program
|
|
5
|
+
(SRP). It does not replace the built-in SRP backend or administration.
|
|
6
|
+
|
|
7
|
+
Restricted users can access the frontend only when both conditions are true:
|
|
8
|
+
|
|
9
|
+
- their Alliance Auth State is eligible; and
|
|
10
|
+
- they belong to the configured Django/Alliance Auth Group.
|
|
11
|
+
|
|
12
|
+
They see only built-in SRP fleets explicitly exposed by an administrator.
|
|
13
|
+
Requests are stored as normal built-in `SrpUserRequest` records, so existing
|
|
14
|
+
SRP administrators continue to approve, reject, update, and pay them through
|
|
15
|
+
the normal Alliance Auth SRP interface.
|
|
16
|
+
|
|
17
|
+
## Compatibility
|
|
18
|
+
|
|
19
|
+
- Alliance Auth `5.2.x`
|
|
20
|
+
- Python `3.10` through `3.14`, matching Alliance Auth 5.2 metadata
|
|
21
|
+
- Django `5.2.x`, supplied by Alliance Auth
|
|
22
|
+
|
|
23
|
+
The initial compatibility target is Alliance Auth 5.2.0. Test upgrades before
|
|
24
|
+
changing either the Alliance Auth or app version constraint.
|
|
25
|
+
|
|
26
|
+
## Security model
|
|
27
|
+
|
|
28
|
+
Every plugin view performs server-side authorization. Navigation visibility is
|
|
29
|
+
only a convenience and is not treated as access control. A submitted fleet ID
|
|
30
|
+
is re-queried through the authorized fleet queryset, and an unexposed fleet
|
|
31
|
+
returns a safe 404. Anonymous users are redirected to login; authenticated
|
|
32
|
+
users who fail the State or Group check receive 403.
|
|
33
|
+
|
|
34
|
+
State, Group, and fleet names are never authorization constants. Configuration
|
|
35
|
+
uses database relations to `authentication.State`, `auth.Group`, and the
|
|
36
|
+
built-in `srp.SrpFleetMain` model.
|
|
37
|
+
|
|
38
|
+
## Requirements
|
|
39
|
+
|
|
40
|
+
- A working Alliance Auth 5.2 installation with built-in SRP enabled
|
|
41
|
+
- Django admin access
|
|
42
|
+
- The built-in `auth.srp_management` permission for app configuration
|
|
43
|
+
|
|
44
|
+
## Installation
|
|
45
|
+
|
|
46
|
+
Add a pinned release to the Alliance Auth requirements file:
|
|
47
|
+
|
|
48
|
+
```text
|
|
49
|
+
aa-srp-access==0.1.0
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Add the Python module to local settings:
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
INSTALLED_APPS += [
|
|
56
|
+
"srp_access",
|
|
57
|
+
]
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Rebuild the application image, then run:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
python manage.py migrate srp_access
|
|
64
|
+
python manage.py collectstatic --noinput
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Restart the web, worker, and scheduler processes using the deployment's normal
|
|
68
|
+
procedure. No Alliance Auth core files or core migrations are changed.
|
|
69
|
+
|
|
70
|
+
## Docker installation
|
|
71
|
+
|
|
72
|
+
Service names vary between deployments. From the correct Compose project
|
|
73
|
+
directory, the usual sequence is:
|
|
74
|
+
|
|
75
|
+
1. Add `aa-srp-access==0.1.0` to `conf/requirements.txt`.
|
|
76
|
+
2. Add `srp_access` to `INSTALLED_APPS` in local Django settings.
|
|
77
|
+
3. Rebuild the Alliance Auth image with `docker compose build`.
|
|
78
|
+
4. Run `docker compose run --rm <web-service> python manage.py migrate srp_access`.
|
|
79
|
+
5. Run `docker compose run --rm <web-service> python manage.py collectstatic --noinput`.
|
|
80
|
+
6. Recreate the web, workers, and beat/scheduler services.
|
|
81
|
+
7. Verify container health and both the standard and restricted SRP pages.
|
|
82
|
+
|
|
83
|
+
Back up the database and configuration first. Determine the correct Compose
|
|
84
|
+
project and service names before running commands; do not copy the examples
|
|
85
|
+
blindly into a production deployment.
|
|
86
|
+
|
|
87
|
+
## Initial configuration
|
|
88
|
+
|
|
89
|
+
1. Sign in to Django admin as a staff user with `auth.srp_management`.
|
|
90
|
+
2. Open **Restricted SRP settings**.
|
|
91
|
+
3. Select the required access Group.
|
|
92
|
+
4. Choose State behavior:
|
|
93
|
+
- enable **allow any public state** to require `State.public=True`; or
|
|
94
|
+
- disable it and select one or more specific State objects.
|
|
95
|
+
5. Add **Exposed SRP fleet** rows for existing built-in SRP fleets.
|
|
96
|
+
6. Leave an exposure enabled only while that fleet should be available.
|
|
97
|
+
|
|
98
|
+
An exposed fleet must also be open in built-in SRP: it needs a non-empty SRP
|
|
99
|
+
code and an incomplete status. Disabling or completing it in built-in SRP
|
|
100
|
+
removes it from the restricted list without deleting the exposure mapping.
|
|
101
|
+
|
|
102
|
+
## Permissions and groups
|
|
103
|
+
|
|
104
|
+
The access Group is application data selected in admin; its name is not fixed.
|
|
105
|
+
State eligibility and Group membership are both mandatory. Superuser or staff
|
|
106
|
+
status does not bypass the restricted frontend's State-and-Group rule.
|
|
107
|
+
|
|
108
|
+
Configuration in Django admin is guarded by Alliance Auth's existing
|
|
109
|
+
`auth.srp_management` permission. Normal built-in SRP permissions and pages are
|
|
110
|
+
not modified.
|
|
111
|
+
|
|
112
|
+
## How to expose fleets
|
|
113
|
+
|
|
114
|
+
Create fleets through the normal built-in SRP interface. In Django admin, add
|
|
115
|
+
an **Exposed SRP fleet** mapping and select the existing fleet object. The
|
|
116
|
+
one-to-one relation prevents duplicate mappings. Removing a built-in fleet also
|
|
117
|
+
removes its exposure mapping; it does not affect unrelated SRP data.
|
|
118
|
+
|
|
119
|
+
## Upgrading
|
|
120
|
+
|
|
121
|
+
1. Back up the Alliance Auth database and configuration.
|
|
122
|
+
2. Pin the desired `aa-srp-access` version in requirements.
|
|
123
|
+
3. Rebuild the image.
|
|
124
|
+
4. Run `python manage.py migrate srp_access`.
|
|
125
|
+
5. Run `collectstatic` when release notes require it.
|
|
126
|
+
6. Recreate services and verify both SRP frontends.
|
|
127
|
+
|
|
128
|
+
Test Alliance Auth upgrades on a test server with the currently pinned plugin
|
|
129
|
+
version before upgrading production.
|
|
130
|
+
|
|
131
|
+
## Uninstall considerations
|
|
132
|
+
|
|
133
|
+
Removing the app does not remove built-in SRP fleets or requests. Plugin-owned
|
|
134
|
+
settings and exposure mappings remain in the database unless their tables are
|
|
135
|
+
explicitly removed. Back up first; do not reverse migrations casually on a
|
|
136
|
+
production installation. Remove `srp_access` from `INSTALLED_APPS` only after
|
|
137
|
+
planning whether to retain or remove those plugin tables.
|
|
138
|
+
|
|
139
|
+
## Development and testing
|
|
140
|
+
|
|
141
|
+
Run tests against a Redis instance on localhost database 15:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
python -m django test srp_access.tests --settings=testauth.settings
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Build and validate distributions:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
python -m pip install --upgrade build twine
|
|
151
|
+
python -m build
|
|
152
|
+
python -m twine check dist/*
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
The test suite uses SQLite and arbitrary fixture names. It covers anonymous,
|
|
156
|
+
State, Group, exposed-fleet, direct URL, submission, built-in SRP regression,
|
|
157
|
+
and built-in administrator behavior.
|
|
158
|
+
|
|
159
|
+
## Release process
|
|
160
|
+
|
|
161
|
+
Update the changelog and version, merge tested changes, and create a deliberate
|
|
162
|
+
GitHub Release. The release workflow builds and validates wheel/sdist artifacts
|
|
163
|
+
before publishing through a PyPI Trusted Publisher and the protected `pypi`
|
|
164
|
+
GitHub environment. Ordinary pushes never publish.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.27"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "aa-srp-access"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "Restricted, configurable access to Alliance Auth's built-in SRP"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { file = "LICENSE" }
|
|
11
|
+
authors = [{ name = "aa-srp-access contributors" }]
|
|
12
|
+
requires-python = ">=3.10,<3.15"
|
|
13
|
+
dependencies = [
|
|
14
|
+
"allianceauth>=5.2,<5.3",
|
|
15
|
+
"django-solo>=2.5,<3",
|
|
16
|
+
]
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 3 - Alpha",
|
|
19
|
+
"Environment :: Web Environment",
|
|
20
|
+
"Framework :: Django :: 5.2",
|
|
21
|
+
"License :: OSI Approved :: MIT License",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Programming Language :: Python :: 3.13",
|
|
27
|
+
"Programming Language :: Python :: 3.14",
|
|
28
|
+
"Topic :: Internet :: WWW/HTTP",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.optional-dependencies]
|
|
32
|
+
test = [
|
|
33
|
+
"build>=1.2",
|
|
34
|
+
"twine>=5",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[project.urls]
|
|
38
|
+
Homepage = "https://github.com/thegriffenkd/aa-srp-access"
|
|
39
|
+
Changelog = "https://github.com/thegriffenkd/aa-srp-access/blob/main/CHANGELOG.md"
|
|
40
|
+
Issues = "https://github.com/thegriffenkd/aa-srp-access/issues"
|
|
41
|
+
Source = "https://github.com/thegriffenkd/aa-srp-access"
|
|
42
|
+
|
|
43
|
+
[tool.hatch.version]
|
|
44
|
+
path = "srp_access/__init__.py"
|
|
45
|
+
|
|
46
|
+
[tool.hatch.build.targets.wheel]
|
|
47
|
+
packages = ["srp_access"]
|
|
48
|
+
|
|
49
|
+
[tool.hatch.build.targets.sdist]
|
|
50
|
+
include = [
|
|
51
|
+
"/.github",
|
|
52
|
+
"/srp_access",
|
|
53
|
+
"/testauth",
|
|
54
|
+
"/CHANGELOG.md",
|
|
55
|
+
"/LICENSE",
|
|
56
|
+
"/README.md",
|
|
57
|
+
"/pyproject.toml",
|
|
58
|
+
]
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from django.core.exceptions import ObjectDoesNotExist
|
|
2
|
+
|
|
3
|
+
from allianceauth.srp.models import SrpFleetMain
|
|
4
|
+
|
|
5
|
+
from .models import ExposedSrpFleet, SrpAccessSettings
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_access_settings():
|
|
9
|
+
"""Return configured settings without creating database state during requests."""
|
|
10
|
+
return SrpAccessSettings.objects.first()
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def user_has_eligible_state(user, settings=None):
|
|
14
|
+
if not getattr(user, "is_authenticated", False):
|
|
15
|
+
return False
|
|
16
|
+
|
|
17
|
+
try:
|
|
18
|
+
state = user.profile.state
|
|
19
|
+
except ObjectDoesNotExist:
|
|
20
|
+
return False
|
|
21
|
+
|
|
22
|
+
if state is None:
|
|
23
|
+
return False
|
|
24
|
+
|
|
25
|
+
settings = settings or get_access_settings()
|
|
26
|
+
if settings is None:
|
|
27
|
+
return False
|
|
28
|
+
|
|
29
|
+
if settings.allow_any_public_state:
|
|
30
|
+
return bool(state.public)
|
|
31
|
+
|
|
32
|
+
return settings.selected_states.filter(pk=state.pk).exists()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def user_in_required_group(user, settings=None):
|
|
36
|
+
if not getattr(user, "is_authenticated", False):
|
|
37
|
+
return False
|
|
38
|
+
|
|
39
|
+
settings = settings or get_access_settings()
|
|
40
|
+
if settings is None or settings.required_group_id is None:
|
|
41
|
+
return False
|
|
42
|
+
|
|
43
|
+
return user.groups.filter(pk=settings.required_group_id).exists()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def fleet_is_exposed(fleet):
|
|
47
|
+
fleet_id = getattr(fleet, "pk", fleet)
|
|
48
|
+
if fleet_id is None:
|
|
49
|
+
return False
|
|
50
|
+
return ExposedSrpFleet.objects.filter(fleet_id=fleet_id, enabled=True).exists()
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def can_use_restricted_srp(user, fleet=None):
|
|
54
|
+
settings = get_access_settings()
|
|
55
|
+
if settings is None:
|
|
56
|
+
return False
|
|
57
|
+
if not user_has_eligible_state(user, settings):
|
|
58
|
+
return False
|
|
59
|
+
if not user_in_required_group(user, settings):
|
|
60
|
+
return False
|
|
61
|
+
if fleet is not None and not fleet_is_exposed(fleet):
|
|
62
|
+
return False
|
|
63
|
+
return True
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def accessible_fleets_for(user):
|
|
67
|
+
"""Return exposed built-in fleets that currently accept SRP requests."""
|
|
68
|
+
if not can_use_restricted_srp(user):
|
|
69
|
+
return SrpFleetMain.objects.none()
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
SrpFleetMain.objects.select_related("fleet_commander")
|
|
73
|
+
.filter(
|
|
74
|
+
srp_access_exposure__enabled=True,
|
|
75
|
+
fleet_srp_status="",
|
|
76
|
+
)
|
|
77
|
+
.exclude(fleet_srp_code="")
|
|
78
|
+
.order_by("-fleet_time", "-pk")
|
|
79
|
+
)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from django.contrib import admin
|
|
2
|
+
from solo.admin import SingletonModelAdmin
|
|
3
|
+
|
|
4
|
+
from .models import ExposedSrpFleet, SrpAccessSettings
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class SrpManagementPermissionMixin:
|
|
8
|
+
management_permission = "auth.srp_management"
|
|
9
|
+
|
|
10
|
+
def _can_manage(self, request):
|
|
11
|
+
return request.user.has_perm(self.management_permission)
|
|
12
|
+
|
|
13
|
+
def has_module_permission(self, request):
|
|
14
|
+
return self._can_manage(request)
|
|
15
|
+
|
|
16
|
+
def has_view_permission(self, request, obj=None):
|
|
17
|
+
return self._can_manage(request)
|
|
18
|
+
|
|
19
|
+
def has_add_permission(self, request):
|
|
20
|
+
return self._can_manage(request)
|
|
21
|
+
|
|
22
|
+
def has_change_permission(self, request, obj=None):
|
|
23
|
+
return self._can_manage(request)
|
|
24
|
+
|
|
25
|
+
def has_delete_permission(self, request, obj=None):
|
|
26
|
+
return self._can_manage(request)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@admin.register(SrpAccessSettings)
|
|
30
|
+
class SrpAccessSettingsAdmin(SrpManagementPermissionMixin, SingletonModelAdmin):
|
|
31
|
+
filter_horizontal = ("selected_states",)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@admin.register(ExposedSrpFleet)
|
|
35
|
+
class ExposedSrpFleetAdmin(SrpManagementPermissionMixin, admin.ModelAdmin):
|
|
36
|
+
list_display = ("fleet", "enabled")
|
|
37
|
+
list_filter = ("enabled",)
|
|
38
|
+
list_select_related = ("fleet",)
|
|
39
|
+
search_fields = ("fleet__fleet_name", "fleet__fleet_srp_code")
|