mirror of
https://github.com/YunoHost-Apps/django-for-runners_ynh.git
synced 2024-09-03 18:26:16 +02:00
commit
7262b73c49
18 changed files with 418 additions and 145 deletions
20
.editorconfig
Normal file
20
.editorconfig
Normal file
|
@ -0,0 +1,20 @@
|
|||
# see http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.py]
|
||||
line_length = 119
|
||||
|
||||
[{Makefile,**.mk}]
|
||||
indent_style = tab
|
||||
insert_final_newline = false
|
||||
|
||||
[*.yml]
|
||||
indent_style = tab
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,6 +1,8 @@
|
|||
.*
|
||||
!.github
|
||||
!.editorconfig
|
||||
!.gitignore
|
||||
__pycache__
|
||||
secret.txt
|
||||
/local_test/
|
||||
/poetry.lock
|
||||
|
|
36
Makefile
Normal file
36
Makefile
Normal file
|
@ -0,0 +1,36 @@
|
|||
SHELL := /bin/bash
|
||||
|
||||
all: help
|
||||
|
||||
help:
|
||||
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z0-9 -]+:.*?## / {printf "\033[36m%-22s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
|
||||
|
||||
check-poetry:
|
||||
@if [[ "$(shell poetry --version 2>/dev/null)" == *"Poetry"* ]] ; \
|
||||
then \
|
||||
echo "Poetry found, ok." ; \
|
||||
else \
|
||||
echo 'Please install poetry first, with e.g.:' ; \
|
||||
echo 'make install-poetry' ; \
|
||||
exit 1 ; \
|
||||
fi
|
||||
|
||||
install-poetry: ## install or update poetry
|
||||
pip3 install -U poetry
|
||||
|
||||
install: check-poetry ## install project via poetry
|
||||
poetry install
|
||||
|
||||
update: install-poetry ## update the sources and installation
|
||||
poetry update
|
||||
|
||||
local-test: check-poetry ## Run local_test.py to run the project locally
|
||||
poetry run ./local_test.py
|
||||
|
||||
local-diff-settings: ## Run "manage.py diffsettings" with local test
|
||||
poetry run python3 local_test/opt_yunohost/manage.py diffsettings
|
||||
|
||||
|
||||
##############################################################################
|
||||
|
||||
.PHONY: help check-poetry install-poetry install update local-test
|
39
README.md
39
README.md
|
@ -1,9 +1,9 @@
|
|||
# Django-For-Runners for YunoHost
|
||||
|
||||
[![Integration level](https://dash.yunohost.org/integration/django-for-runners.svg)](https://dash.yunohost.org/appci/app/django-for-runners) ![](https://ci-apps.yunohost.org/ci/badges/django-for-runners.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/django-for-runners.maintain.svg)
|
||||
[![Integration level](https://dash.yunohost.org/integration/django-for-runners.svg)](https://dash.yunohost.org/appci/app/django-for-runners) ![](https://ci-apps.yunohost.org/ci/badges/django-for-runners.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/django-for-runners.maintain.svg)
|
||||
[![Install Django-For-Runners with YunoHost](https://install-app.yunohost.org/install-with-yunohost.png)](https://install-app.yunohost.org/?app=django-for-runners)
|
||||
|
||||
> *This package allows you to install Django-For-Runners quickly and simply on a YunoHost server.
|
||||
> *This package allows you to install Django-For-Runners quickly and simply on a YunoHost server.
|
||||
If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/install) to learn how to install it.*
|
||||
|
||||
Current status is pre-alpha: This app doesn't work, yet ;)
|
||||
|
@ -31,9 +31,16 @@ You can edit the file `$final_path/local_settings.py` to enable or disable featu
|
|||
|
||||
# Miscellaneous
|
||||
|
||||
## LDAP connection
|
||||
|
||||
Supported by https://github.com/django-auth-ldap/django-auth-ldap
|
||||
## SSO authentication
|
||||
|
||||
[SSOwat](https://github.com/YunoHost/SSOwat) is fully supported:
|
||||
|
||||
* First user (`$YNH_APP_ARG_ADMIN`) will be created as Django's super user
|
||||
* All new users will be created as normal users
|
||||
* Login via SSO is fully supported
|
||||
* User Email, First / Last name will be updated from SSO data
|
||||
|
||||
|
||||
## Links
|
||||
|
||||
|
@ -111,24 +118,24 @@ For quicker developing of Django-For-Runners in the context of YunoHost app,
|
|||
it's possible to run the Django developer server with the settings
|
||||
and urls made for YunoHost installation.
|
||||
|
||||
For this, just run `local_test.py` in a Django-For-Runners virtualenv.
|
||||
|
||||
e.g.:
|
||||
```bash
|
||||
~$ git clone https://github.com/jedie/Django-For-Runners.git
|
||||
~$ git clone https://github.com/YunoHost-Apps/django-for-runners_ynh.git
|
||||
~$ cd Django-For-Runners/
|
||||
~/Django-For-Runners$ make install
|
||||
~/Django-For-Runners$ poetry shell
|
||||
(django-for-runners-yd_5sxYx-py3.8) ~/Django-For-Runners$ cd ../django-for-runners_ynh/
|
||||
(django-for-runners-yd_5sxYx-py3.8) ~/django-for-runners_ynh$ ./local_test.py
|
||||
...
|
||||
Django version 2.2.17, using settings 'ynh_django-for-runners_settings'
|
||||
Starting development server at http://127.0.0.1:8000/
|
||||
~$ cd django-for-runners_ynh/
|
||||
~/django-for-runners_ynh$ make
|
||||
install-poetry install or update poetry
|
||||
install install project via poetry
|
||||
update update the sources and installation
|
||||
local-test Run local_test.py to run the project locally
|
||||
local-diff-settings Run "manage.py diffsettings" with local test
|
||||
|
||||
~/django-for-runners_ynh$ make install-poetry
|
||||
~/django-for-runners_ynh$ make install
|
||||
~/django-for-runners_ynh$ make local-test
|
||||
```
|
||||
|
||||
Notes:
|
||||
|
||||
* SQlite database will be used
|
||||
* A super user with username `test` and password `test` is created
|
||||
* The page is available under `http://127.0.0.1:8000/app_path/`
|
||||
* The page is available under `http://127.0.0.1:8000/app_path/`
|
||||
|
|
|
@ -24,12 +24,15 @@ def main():
|
|||
|
||||
from django.contrib.auth import get_user_model
|
||||
User = get_user_model()
|
||||
super_user = User.objects.filter(username=username).first()
|
||||
if super_user:
|
||||
print('Update existing super user and set his password.', file=sys.stderr)
|
||||
super_user.set_password(password)
|
||||
super_user.email=email
|
||||
super_user.save()
|
||||
user = User.objects.filter(username=username).first()
|
||||
if user:
|
||||
print('Update existing user and set his password.', file=sys.stderr)
|
||||
user.is_active = True
|
||||
user.is_staff = True
|
||||
user.is_superuser = True
|
||||
user.set_password(password)
|
||||
user.email = email
|
||||
user.save()
|
||||
else:
|
||||
print('Create new super user', file=sys.stderr)
|
||||
User.objects.create_superuser(
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
|
||||
location __PATH__/static/ {
|
||||
# Django static files
|
||||
alias __PUBLIC_PATH__/static/;
|
||||
expires 30d;
|
||||
# Django static files
|
||||
alias __PUBLIC_PATH__/static/;
|
||||
expires 30d;
|
||||
}
|
||||
|
||||
# TODO: django-sendfile2:
|
||||
|
@ -12,26 +12,23 @@ location __PATH__/static/ {
|
|||
# expires 30d;
|
||||
#}
|
||||
|
||||
location __PATH__/ {
|
||||
# https://github.com/benoitc/gunicorn/blob/master/examples/nginx.conf
|
||||
location / {
|
||||
# https://github.com/benoitc/gunicorn/blob/master/examples/nginx.conf
|
||||
|
||||
# this is needed if you have file import via upload enabled
|
||||
client_max_body_size 100M;
|
||||
# this is needed if you have file import via upload enabled
|
||||
client_max_body_size 100M;
|
||||
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Protocol $scheme;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Scheme $scheme;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Protocol $scheme;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Scheme $scheme;
|
||||
|
||||
proxy_read_timeout 30;
|
||||
proxy_send_timeout 30;
|
||||
proxy_connect_timeout 30;
|
||||
proxy_redirect off;
|
||||
proxy_read_timeout 30;
|
||||
proxy_send_timeout 30;
|
||||
proxy_connect_timeout 30;
|
||||
proxy_redirect off;
|
||||
|
||||
proxy_pass http://127.0.0.1:__PORT__/;
|
||||
|
||||
# Include SSOWAT user panel.
|
||||
#include conf.d/yunohost_panel.conf.inc;
|
||||
proxy_pass http://127.0.0.1:__PORT__/;
|
||||
}
|
||||
|
|
185
conf/ynh_authenticate.py
Normal file
185
conf/ynh_authenticate.py
Normal file
|
@ -0,0 +1,185 @@
|
|||
"""
|
||||
* remote user authentication backend
|
||||
* remote user middleware
|
||||
|
||||
Note: SSOwat/nginx add authentication headers:
|
||||
|
||||
'HTTP_AUTHORIZATION': 'Basic XXXXXXXXXXXXXXXX='
|
||||
'HTTP_AUTH_USER': 'username'
|
||||
'HTTP_REMOTE_USER': 'username'
|
||||
|
||||
Basic auth contains "{username}:{plaintext-password}"
|
||||
|
||||
and we get SSOwat cookies like:
|
||||
|
||||
'HTTP_COOKIE': 'SSOwAuthUser=username; '
|
||||
'SSOwAuthHash=593876aa66...99e69f88af1e; '
|
||||
'SSOwAuthExpire=1609227697.998; '
|
||||
|
||||
* Login a user via HTTP_REMOTE_USER header, but check also username in:
|
||||
* SSOwAuthUser
|
||||
* HTTP_AUTH_USER
|
||||
* HTTP_AUTHORIZATION (Basic auth)
|
||||
* Create new users
|
||||
* Update Email, First / Last name for existing users
|
||||
"""
|
||||
import base64
|
||||
import logging
|
||||
|
||||
from axes.exceptions import AxesBackendPermissionDenied
|
||||
from django.contrib.auth.backends import RemoteUserBackend as OriginRemoteUserBackend
|
||||
from django.contrib.auth.middleware import RemoteUserMiddleware as OriginRemoteUserMiddleware
|
||||
from django.core.exceptions import ValidationError
|
||||
from inventory.permissions import get_or_create_normal_user_group
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def update_user_profile(request):
|
||||
"""
|
||||
Update existing user information:
|
||||
* Email
|
||||
* First / Last name
|
||||
"""
|
||||
user = request.user
|
||||
assert user.is_authenticated
|
||||
|
||||
update_fields = []
|
||||
|
||||
if not user.password:
|
||||
# Empty password is not valid, so we can't save the model, because of full_clean() call
|
||||
logger.info('Set unusable password for user: %s', user)
|
||||
user.set_unusable_password()
|
||||
update_fields.append('password')
|
||||
|
||||
email = request.META.get('HTTP_EMAIL')
|
||||
if email and user.email != email:
|
||||
logger.info('Update email: %r -> %r', user.email, email)
|
||||
user.email = email
|
||||
update_fields.append('email')
|
||||
|
||||
raw_username = request.META.get('HTTP_NAME')
|
||||
if raw_username:
|
||||
if ' ' in raw_username:
|
||||
first_name, last_name = raw_username.split(' ', 1)
|
||||
else:
|
||||
first_name = ''
|
||||
last_name = raw_username
|
||||
|
||||
if user.first_name != first_name:
|
||||
logger.info('Update first name: %r -> %r', user.first_name, first_name)
|
||||
user.first_name = first_name
|
||||
update_fields.append('first_name')
|
||||
|
||||
if user.last_name != last_name:
|
||||
logger.info('Update last name: %r -> %r', user.last_name, last_name)
|
||||
user.last_name = last_name
|
||||
update_fields.append('last_name')
|
||||
|
||||
if update_fields:
|
||||
try:
|
||||
user.full_clean()
|
||||
except ValidationError:
|
||||
logger.exception('Can not update user: %s', user)
|
||||
else:
|
||||
user.save(update_fields=update_fields)
|
||||
|
||||
|
||||
class RemoteUserMiddleware(OriginRemoteUserMiddleware):
|
||||
"""
|
||||
Middleware to login a user HTTP_REMOTE_USER header.
|
||||
Use Django Axes if something is wrong.
|
||||
Update exising user informations.
|
||||
"""
|
||||
header = 'HTTP_REMOTE_USER'
|
||||
force_logout_if_no_header = True
|
||||
|
||||
def process_request(self, request):
|
||||
# Keep the information if the user is already logged in
|
||||
was_authenticated = request.user.is_authenticated
|
||||
|
||||
super().process_request(request) # login remote user
|
||||
|
||||
if not request.user.is_authenticated:
|
||||
# Not logged in -> nothing to verify here
|
||||
return
|
||||
|
||||
# Check SSOwat cookie informations:
|
||||
try:
|
||||
username = request.COOKIES['SSOwAuthUser']
|
||||
except KeyError:
|
||||
logger.error('SSOwAuthUser cookie missing!')
|
||||
|
||||
# emits a signal indicating user login failed, which is processed by
|
||||
# axes.signals.log_user_login_failed which logs and flags the failed request.
|
||||
raise AxesBackendPermissionDenied('Cookie missing')
|
||||
|
||||
logger.info('SSOwat username from cookies: %r', username)
|
||||
if username != request.user.username:
|
||||
raise AxesBackendPermissionDenied('Wrong username')
|
||||
|
||||
# Compare with HTTP_AUTH_USER
|
||||
try:
|
||||
username = request.META['HTTP_AUTH_USER']
|
||||
except KeyError:
|
||||
logger.error('HTTP_AUTH_USER missing!')
|
||||
raise AxesBackendPermissionDenied('No HTTP_AUTH_USER')
|
||||
|
||||
if username != request.user.username:
|
||||
raise AxesBackendPermissionDenied('Wrong HTTP_AUTH_USER username')
|
||||
|
||||
# Also check 'HTTP_AUTHORIZATION', but only the username ;)
|
||||
try:
|
||||
auth = request.META['HTTP_AUTHORIZATION']
|
||||
except KeyError:
|
||||
logger.error('HTTP_AUTHORIZATION missing!')
|
||||
raise AxesBackendPermissionDenied('No HTTP_AUTHORIZATION')
|
||||
|
||||
scheme, creds = auth.split(' ', 1)
|
||||
if scheme.lower() != 'basic':
|
||||
logger.error('HTTP_AUTHORIZATION with %r not supported', scheme)
|
||||
raise AxesBackendPermissionDenied('HTTP_AUTHORIZATION scheme not supported')
|
||||
|
||||
creds = str(base64.b64decode(creds), encoding='utf-8')
|
||||
username = creds.split(':', 1)[0]
|
||||
if username != request.user.username:
|
||||
raise AxesBackendPermissionDenied('Wrong HTTP_AUTHORIZATION username')
|
||||
|
||||
if not was_authenticated:
|
||||
# First request, after login -> update user informations
|
||||
logger.info('Remote used was logged in')
|
||||
update_user_profile(request)
|
||||
|
||||
|
||||
class RemoteUserBackend(OriginRemoteUserBackend):
|
||||
"""
|
||||
Authentication backend via SSO/nginx header
|
||||
"""
|
||||
create_unknown_user = True
|
||||
|
||||
def authenticate(self, request, remote_user):
|
||||
logger.info('Remote user authenticate: %r', remote_user)
|
||||
return super().authenticate(request, remote_user)
|
||||
|
||||
def configure_user(self, request, user):
|
||||
"""
|
||||
Configure a user after creation and return the updated user.
|
||||
Setup a normal, non-superuser
|
||||
"""
|
||||
logger.warning('Configure user %s', user)
|
||||
|
||||
user.set_unusable_password() # Always login via SSO
|
||||
user.is_staff = True
|
||||
user.is_superuser = False
|
||||
user.save()
|
||||
|
||||
pyinventory_user_group = get_or_create_normal_user_group()[0]
|
||||
user.groups.set([pyinventory_user_group])
|
||||
|
||||
update_user_profile(request)
|
||||
|
||||
return user
|
||||
|
||||
def user_can_authenticate(self, user):
|
||||
logger.warning('Remote user login: %s', user)
|
||||
return True
|
|
@ -11,8 +11,6 @@
|
|||
|
||||
from pathlib import Path as __Path
|
||||
|
||||
import ldap
|
||||
from django_auth_ldap.config import LDAPSearch
|
||||
from for_runners_project.settings.base import * # noqa
|
||||
|
||||
DEBUG = False
|
||||
|
@ -36,44 +34,30 @@ PATH_URL = PATH_URL.strip('/')
|
|||
ROOT_URLCONF = 'ynh_urls' # /opt/yunohost/django-for-runners/ynh_urls.py
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# https://github.com/django-auth-ldap/django-auth-ldap
|
||||
|
||||
LDAP_SERVER_URI = 'ldap://localhost:389'
|
||||
LDAP_START_TLS = True
|
||||
|
||||
# enable anonymous searches
|
||||
# https://django-auth-ldap.readthedocs.io/en/latest/authentication.html?highlight=anonymous#search-bind
|
||||
LDAP_BIND_DN = ''
|
||||
LDAP_BIND_PASSWORD = ''
|
||||
|
||||
LDAP_ROOT_DN = 'ou=users,dc=yunohost,dc=org'
|
||||
|
||||
AUTH_LDAP_USER_SEARCH = LDAPSearch(LDAP_ROOT_DN, ldap.SCOPE_SUBTREE, '(uid=%(user)s)')
|
||||
|
||||
# Populate the Django user from the LDAP directory.
|
||||
AUTH_LDAP_USER_ATTR_MAP = {
|
||||
'username': 'uid',
|
||||
'first_name': 'givenName',
|
||||
'last_name': 'sn',
|
||||
'email': 'mail',
|
||||
}
|
||||
|
||||
AUTH_LDAP_ALWAYS_UPDATE_USER = True
|
||||
|
||||
# Don't use LDAP group membership to calculate group permissions
|
||||
AUTH_LDAP_FIND_GROUP_PERMS = False
|
||||
|
||||
# TODO:
|
||||
# AUTH_LDAP_GROUP_TYPE = 'normal user' # Same as: inventory.permissions.NORMAL_USER_GROUP_NAME
|
||||
|
||||
# Cache distinguished names and group memberships for an hour to minimize LDAP traffic
|
||||
AUTH_LDAP_CACHE_TIMEOUT = 3600
|
||||
|
||||
# Keep ModelBackend around for per-user permissions and superuser
|
||||
AUTHENTICATION_BACKENDS = (
|
||||
'django_auth_ldap.backend.LDAPBackend',
|
||||
'axes.backends.AxesBackend', # AxesBackend should be the first backend!
|
||||
|
||||
# Authenticate via SSO and nginx 'HTTP_REMOTE_USER' header:
|
||||
'ynh_authenticate.RemoteUserBackend',
|
||||
|
||||
# Fallback to normal Django model backend:
|
||||
'django.contrib.auth.backends.ModelBackend',
|
||||
)
|
||||
LOGIN_REDIRECT_URL = None
|
||||
LOGIN_URL = '/yunohost/sso/'
|
||||
LOGOUT_REDIRECT_URL = '/yunohost/sso/'
|
||||
# /yunohost/sso/?action=logout
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# https://docs.djangoproject.com/en/2.2/howto/auth-remote-user/
|
||||
# Add RemoteUserMiddleware after AuthenticationMiddleware
|
||||
|
||||
MIDDLEWARE.insert(
|
||||
MIDDLEWARE.index('django.contrib.auth.middleware.AuthenticationMiddleware') + 1,
|
||||
'ynh_authenticate.RemoteUserMiddleware',
|
||||
)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
|
@ -165,7 +149,7 @@ LOGGING = {
|
|||
'class': 'django.utils.log.AdminEmailHandler',
|
||||
'include_html': True,
|
||||
},
|
||||
'syslog': {
|
||||
'log_file': {
|
||||
'level': 'DEBUG',
|
||||
'class': 'logging.handlers.WatchedFileHandler',
|
||||
'formatter': 'verbose',
|
||||
|
@ -173,18 +157,17 @@ LOGGING = {
|
|||
},
|
||||
},
|
||||
'loggers': {
|
||||
'': {'handlers': ['syslog', 'mail_admins'], 'level': 'INFO', 'propagate': False},
|
||||
'django': {'handlers': ['syslog', 'mail_admins'], 'level': 'INFO', 'propagate': False},
|
||||
'axes': {'handlers': ['syslog', 'mail_admins'], 'level': 'WARNING', 'propagate': False},
|
||||
'django_tools': {'handlers': ['syslog', 'mail_admins'], 'level': 'INFO', 'propagate': False},
|
||||
'django_auth_ldap': {'handlers': ['syslog', 'mail_admins'], 'level': 'DEBUG', 'propagate': False},
|
||||
'inventory': {'handlers': ['syslog', 'mail_admins'], 'level': 'INFO', 'propagate': False},
|
||||
'': {'handlers': ['log_file', 'mail_admins'], 'level': 'INFO', 'propagate': False},
|
||||
'django': {'handlers': ['log_file', 'mail_admins'], 'level': 'INFO', 'propagate': False},
|
||||
'axes': {'handlers': ['log_file', 'mail_admins'], 'level': 'WARNING', 'propagate': False},
|
||||
'django_tools': {'handlers': ['log_file', 'mail_admins'], 'level': 'INFO', 'propagate': False},
|
||||
'for_runners': {'handlers': ['log_file', 'mail_admins'], 'level': 'INFO', 'propagate': False},
|
||||
},
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
try:
|
||||
from .local_settings import * # noqa
|
||||
from local_settings import * # noqa
|
||||
except ImportError:
|
||||
pass
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
from django.conf import settings
|
||||
from django.contrib import admin
|
||||
from django.urls import path
|
||||
from django.views.generic import RedirectView
|
||||
|
||||
# def debug_view(request):
|
||||
# """ debug request.META """
|
||||
# if not request.user.is_authenticated:
|
||||
# from django.shortcuts import redirect
|
||||
# return redirect('admin:index')
|
||||
#
|
||||
# import pprint
|
||||
# meta = pprint.pformat(request.META)
|
||||
# html = f'<html><body>request.META: <pre>{meta}</pre></body></html>'
|
||||
# from django.http import HttpResponse
|
||||
# return HttpResponse(html)
|
||||
|
||||
|
||||
# settings.PATH_URL is the $YNH_APP_ARG_PATH
|
||||
if settings.PATH_URL:
|
||||
admin.autodiscover()
|
||||
admin.autodiscover()
|
||||
|
||||
urlpatterns = [
|
||||
# TODO:
|
||||
# XXX: Hack - the MEDIA_URL contains the "PATH_URL" already:
|
||||
# path(settings.MEDIA_URL.lstrip('/'), include('django_tools.serve_media_app.urls')),
|
||||
|
||||
path(f'{settings.PATH_URL}/admin/', admin.site.urls),
|
||||
path('', RedirectView.as_view(pattern_name='admin:index')),
|
||||
]
|
||||
else:
|
||||
# Installed to domain root, without a path prefix?
|
||||
from inventory_project.urls import urlpatterns # noqa
|
||||
urlpatterns = [
|
||||
# path(f'{settings.PATH_URL}/debug/', debug_view),
|
||||
path(f'{settings.PATH_URL}/', admin.site.urls),
|
||||
]
|
||||
|
|
|
@ -130,6 +130,10 @@ def main():
|
|||
# conf/ynh_urls.py -> local_test/ynh_urls.py
|
||||
copy_patch(src_file=URLS_FILE, replaces=REPLACES)
|
||||
|
||||
with Path(FINAL_HOME_PATH / 'local_settings.py').open('w') as f:
|
||||
f.write('# Only for local test run\n')
|
||||
f.write('SERVE_FILES=True # used in src/for_runners_project/urls.py\n')
|
||||
|
||||
# call "local_test/manage.py" via subprocess:
|
||||
call_manage_py('check --deploy')
|
||||
call_manage_py('migrate --no-input')
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"description": {
|
||||
"en": "Store your GPX tracks of your running (or other sports activity)"
|
||||
},
|
||||
"version": "0.12.0rc2~ynh1",
|
||||
"version": "0.12.0rc2~ynh2",
|
||||
"url": "https://github.com/jedie/django-for-runners",
|
||||
"license": "GPL-3.0",
|
||||
"maintainer": {
|
||||
|
|
16
pyproject.toml
Normal file
16
pyproject.toml
Normal file
|
@ -0,0 +1,16 @@
|
|||
[tool.poetry]
|
||||
name = "django-for-runners_ynh"
|
||||
version = "0.12.0rc2~ynh2"
|
||||
description = "Test django-for-runners_ynh via local_test.py"
|
||||
authors = ["JensDiemer <git@jensdiemer.de>"]
|
||||
license = "GPL"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = ">=3.7,<4.0.0"
|
||||
django-for-runners = "*"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core>=1.0.0"]
|
||||
build-backend = "poetry.core.masonry.api"
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
domain=$YNH_APP_ARG_DOMAIN
|
||||
path_url=$YNH_APP_ARG_PATH
|
||||
|
||||
admin=$YNH_APP_ARG_ADMIN
|
||||
is_public=$YNH_APP_ARG_IS_PUBLIC
|
||||
app=$YNH_APP_INSTANCE_NAME
|
||||
|
@ -24,14 +25,14 @@ log_file="${log_path}/django-for-runners.log"
|
|||
#=================================================
|
||||
|
||||
# dependencies used by the app
|
||||
pkg_dependencies="build-essential python3-dev python3-pip python3-virtualenv git \
|
||||
postgresql postgresql-contrib python3-ldap libldap2-dev libsasl2-dev"
|
||||
pkg_dependencies="build-essential python3-dev python3-pip python3-venv git \
|
||||
postgresql postgresql-contrib"
|
||||
|
||||
# Django-For-Runners's version for PIP and settings file
|
||||
for_runners_version="0.12.0rc2"
|
||||
|
||||
# Extra python packages:
|
||||
pypi_extras="django-redis django-auth-ldap"
|
||||
pypi_extras="django-redis"
|
||||
|
||||
#=================================================
|
||||
# Redis HELPERS
|
||||
|
|
|
@ -18,10 +18,12 @@ ynh_print_info --message="Loading installation settings..."
|
|||
|
||||
app=$YNH_APP_INSTANCE_NAME
|
||||
|
||||
public_path=$(ynh_app_setting_get --app="$app" --key=public_path)
|
||||
final_path=$(ynh_app_setting_get --app="$app" --key=final_path)
|
||||
domain=$(ynh_app_setting_get --app="$app" --key=domain)
|
||||
db_name=$(ynh_app_setting_get --app="$app" --key=db_name)
|
||||
|
||||
domain=$(ynh_app_setting_get --app="$app" --key=domain)
|
||||
|
||||
#=================================================
|
||||
# DECLARE DATA AND CONF FILES TO BACKUP
|
||||
#=================================================
|
||||
|
@ -32,6 +34,7 @@ ynh_print_info --message="Declaring files to be backed up..."
|
|||
#=================================================
|
||||
|
||||
ynh_backup --src_path="$final_path"
|
||||
ynh_backup --src_path="$public_path"
|
||||
|
||||
#=================================================
|
||||
# BACKUP THE NGINX CONFIGURATION
|
||||
|
|
|
@ -24,10 +24,16 @@ new_path=$YNH_APP_NEW_PATH
|
|||
#=================================================
|
||||
ynh_script_progression --message="Loading installation settings..."
|
||||
|
||||
admin=$(ynh_app_setting_get --app="$app" --key=admin)
|
||||
is_public=$(ynh_app_setting_get --app="$app" --key=is_public)
|
||||
public_path=$(ynh_app_setting_get --app="$app" --key=public_path)
|
||||
final_path=$(ynh_app_setting_get --app="$app" --key=final_path)
|
||||
is_public=$(ynh_app_setting_get --app="$app" --key=is_public)
|
||||
log_path=$(ynh_app_setting_get --app="$app" --key=log_path)
|
||||
|
||||
port=$(ynh_app_setting_get --app="$app" --key=port)
|
||||
db_pwd=$(ynh_app_setting_get --app="$app" --key=psqlpwd)
|
||||
admin_mail=$(ynh_user_get_info "$admin" mail)
|
||||
redis_db=$(ynh_app_setting_get --app="$app" --key=redis_db)
|
||||
|
||||
#=================================================
|
||||
# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP
|
||||
|
@ -89,7 +95,7 @@ then
|
|||
domain="$old_domain"
|
||||
path_url="$new_path"
|
||||
# Create a dedicated nginx config
|
||||
ynh_add_nginx_config
|
||||
ynh_add_nginx_config "public_path" "port"
|
||||
fi
|
||||
|
||||
# Change the domain for nginx
|
||||
|
@ -109,26 +115,26 @@ fi
|
|||
#=================================================
|
||||
ynh_script_progression --message="Modify Django-For-Runners's config file..."
|
||||
|
||||
# save old settings file
|
||||
settings="$final_path/ynh_for_runners_settings.py"
|
||||
ynh_backup_if_checksum_is_different --file="$settings"
|
||||
|
||||
# Change the path in the nginx config file
|
||||
if [ $change_path -eq 1 ]
|
||||
then
|
||||
ynh_replace_string --match_string="URL_PREFIX = \"${old_path%/}\"" --replace_string="URL_PREFIX = \"${new_path%/}\"" --target_file="$settings"
|
||||
fi
|
||||
cp "../conf/ynh_for_runners_settings.py" "$settings"
|
||||
|
||||
# Change the domain for nginx
|
||||
if [ $change_domain -eq 1 ]
|
||||
then
|
||||
# replace SERVER_EMAIL
|
||||
ynh_replace_string --match_string="noreply@$old_domain" --replace_string="noreply@$new_domain" --target_file="$settings"
|
||||
# replace SITE_DOMAIN
|
||||
ynh_replace_string --match_string="SITE_DOMAIN = \"$old_domain\"" --replace_string="SITE_DOMAIN = \"$new_domain\"" --target_file="$settings"
|
||||
# replace ALLOWED_HOSTS
|
||||
ynh_replace_string --match_string="ALLOWED_HOSTS = \[\"$old_domain\"\]" --replace_string="ALLOWED_HOSTS = \[\"$new_domain\"\]" --target_file="$settings"
|
||||
fi
|
||||
ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__DB_PWD__" --replace_string="$db_pwd" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__ADMIN__" --replace_string="$admin" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__ADMINMAIL__" --replace_string="$admin_mail" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__FINAL_HOME_PATH__" --replace_string="$final_path" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__FINAL_WWW_PATH__" --replace_string="$public_path" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__LOG_FILE__" --replace_string="$log_file" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__REDIS_DB__" --replace_string="$redis_db" --target_file="$settings"
|
||||
|
||||
# Difference to install/upgrade scripts: Use $new_domain and $new_path here:
|
||||
ynh_replace_string --match_string="__DOMAIN__" --replace_string="$new_domain" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__PATH_URL__" --replace_string="$new_path" --target_file="$settings"
|
||||
|
||||
# Recalculate and store the config file checksum into the app settings
|
||||
ynh_store_file_checksum --file="$settings"
|
||||
|
||||
#=================================================
|
||||
|
|
|
@ -39,14 +39,15 @@ touch "${log_file}"
|
|||
#=================================================
|
||||
ynh_script_progression --message="Storing installation settings..."
|
||||
|
||||
ynh_app_setting_set --app="$app" --key=domain --value="$domain"
|
||||
ynh_app_setting_set --app="$app" --key=path --value="$path_url"
|
||||
ynh_app_setting_set --app="$app" --key=admin --value="$admin"
|
||||
ynh_app_setting_set --app="$app" --key=is_public --value="$is_public"
|
||||
ynh_app_setting_set --app="$app" --key=public_path --value="$public_path"
|
||||
ynh_app_setting_set --app="$app" --key=final_path --value="$final_path"
|
||||
ynh_app_setting_set --app="$app" --key=log_path --value="$log_file"
|
||||
|
||||
ynh_app_setting_set --app="$app" --key=domain --value="$domain"
|
||||
ynh_app_setting_set --app="$app" --key=path --value="$path_url"
|
||||
|
||||
# Find a free port
|
||||
port=$(ynh_find_port --port=8000)
|
||||
# Set port as application setting
|
||||
|
@ -143,13 +144,14 @@ ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_fil
|
|||
ynh_replace_string --match_string="__DB_PWD__" --replace_string="$db_pwd" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__ADMIN__" --replace_string="$admin" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__ADMINMAIL__" --replace_string="$admin_mail" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__FINAL_HOME_PATH__" --replace_string="$final_path" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__FINAL_WWW_PATH__" --replace_string="$public_path" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__PATH_URL__" --replace_string="$path_url" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__LOG_FILE__" --replace_string="$log_file" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__REDIS_DB__" --replace_string="$redis_db" --target_file="$settings"
|
||||
|
||||
ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__PATH_URL__" --replace_string="$path_url" --target_file="$settings"
|
||||
|
||||
# Calculate and store the config file checksum into the app settings
|
||||
ynh_store_file_checksum --file="$settings"
|
||||
|
||||
|
@ -157,6 +159,7 @@ ynh_app_setting_set --app="$app" --key=redis_db --value="$redis_db"
|
|||
|
||||
touch "$final_path/local_settings.py"
|
||||
|
||||
cp "../conf/ynh_authenticate.py" "$final_path/ynh_authenticate.py"
|
||||
cp "../conf/ynh_urls.py" "$final_path/ynh_urls.py"
|
||||
|
||||
#=================================================
|
||||
|
@ -165,21 +168,21 @@ cp "../conf/ynh_urls.py" "$final_path/ynh_urls.py"
|
|||
ynh_script_progression --message="migrate/collectstatic/createadmin..." --weight=10
|
||||
|
||||
(
|
||||
set +o nounset
|
||||
source "${final_path}/venv/bin/activate"
|
||||
set -o nounset
|
||||
cd "${final_path}"
|
||||
set +o nounset
|
||||
source "${final_path}/venv/bin/activate"
|
||||
set -o nounset
|
||||
cd "${final_path}"
|
||||
|
||||
# Just for debugging:
|
||||
./manage.py diffsettings
|
||||
# Just for debugging:
|
||||
./manage.py diffsettings
|
||||
|
||||
./manage.py migrate --no-input
|
||||
./manage.py collectstatic --no-input
|
||||
./create_superuser.py --username="$admin" --email="$admin_mail" --password="django-for-runners"
|
||||
./manage.py migrate --no-input
|
||||
./manage.py collectstatic --no-input
|
||||
./create_superuser.py --username="$admin" --email="$admin_mail" --password="django-for-runners"
|
||||
|
||||
# Check the configuration
|
||||
# This may fail in some cases with errors, etc., but the app works and the user can fix issues later.
|
||||
./manage.py check --deploy || true
|
||||
# Check the configuration
|
||||
# This may fail in some cases with errors, etc., but the app works and the user can fix issues later.
|
||||
./manage.py check --deploy || true
|
||||
)
|
||||
|
||||
#=================================================
|
||||
|
|
|
@ -20,14 +20,15 @@ ynh_abort_if_errors
|
|||
#=================================================
|
||||
ynh_script_progression --message="Loading settings..."
|
||||
|
||||
domain=$(ynh_app_setting_get --app="$app" --key=domain)
|
||||
path_url=$(ynh_app_setting_get --app="$app" --key=path)
|
||||
public_path=$(ynh_app_setting_get --app="$app" --key=public_path)
|
||||
final_path=$(ynh_app_setting_get --app="$app" --key=final_path)
|
||||
db_name=$(ynh_app_setting_get --app="$app" --key=db_name)
|
||||
db_user=$db_name
|
||||
db_pwd=$(ynh_app_setting_get --app="$app" --key=psqlpwd)
|
||||
|
||||
domain=$(ynh_app_setting_get --app="$app" --key=domain)
|
||||
path_url=$(ynh_app_setting_get --app="$app" --key=path)
|
||||
|
||||
#=================================================
|
||||
# CHECK IF THE APP CAN BE RESTORED
|
||||
#=================================================
|
||||
|
@ -51,6 +52,7 @@ ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf"
|
|||
#=================================================
|
||||
ynh_script_progression --message="Restoring the app main directory..."
|
||||
|
||||
ynh_restore_file --origin_path="$public_path"
|
||||
ynh_restore_file --origin_path="$final_path"
|
||||
|
||||
touch "$final_path/local_settings.py"
|
||||
|
|
|
@ -12,14 +12,15 @@ source /usr/share/yunohost/helpers
|
|||
#=================================================
|
||||
ynh_script_progression --message="Loading installation settings..."
|
||||
|
||||
domain=$(ynh_app_setting_get --app="$app" --key=domain)
|
||||
path_url=$(ynh_app_setting_get --app="$app" --key=path)
|
||||
admin=$(ynh_app_setting_get --app="$app" --key=admin)
|
||||
is_public=$(ynh_app_setting_get --app="$app" --key=is_public)
|
||||
public_path=$(ynh_app_setting_get --app="$app" --key=public_path)
|
||||
final_path=$(ynh_app_setting_get --app="$app" --key=final_path)
|
||||
log_path=$(ynh_app_setting_get --app="$app" --key=log_path)
|
||||
|
||||
domain=$(ynh_app_setting_get --app="$app" --key=domain)
|
||||
path_url=$(ynh_app_setting_get --app="$app" --key=path)
|
||||
|
||||
port=$(ynh_app_setting_get --app="$app" --key=port)
|
||||
db_pwd=$(ynh_app_setting_get --app="$app" --key=psqlpwd)
|
||||
admin_mail=$(ynh_user_get_info "$admin" mail)
|
||||
|
@ -135,18 +136,20 @@ ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_fil
|
|||
ynh_replace_string --match_string="__DB_PWD__" --replace_string="$db_pwd" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__ADMIN__" --replace_string="$admin" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__ADMINMAIL__" --replace_string="$admin_mail" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__FINAL_HOME_PATH__" --replace_string="$final_path" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__FINAL_WWW_PATH__" --replace_string="$public_path" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__PATH_URL__" --replace_string="$path_url" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__LOG_FILE__" --replace_string="$log_file" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__REDIS_DB__" --replace_string="$redis_db" --target_file="$settings"
|
||||
|
||||
ynh_replace_string --match_string="__DOMAIN__" --replace_string="$domain" --target_file="$settings"
|
||||
ynh_replace_string --match_string="__PATH_URL__" --replace_string="$path_url" --target_file="$settings"
|
||||
|
||||
# Recalculate and store the config file checksum into the app settings
|
||||
ynh_store_file_checksum --file="$settings"
|
||||
|
||||
touch "$final_path/local_settings.py"
|
||||
|
||||
cp "../conf/ynh_authenticate.py" "$final_path/ynh_authenticate.py"
|
||||
cp "../conf/ynh_urls.py" "$final_path/ynh_urls.py"
|
||||
|
||||
#=================================================
|
||||
|
|
Loading…
Reference in a new issue