mirror of
https://github.com/YunoHost-Apps/pyinventory_ynh.git
synced 2024-09-03 20:16:09 +02:00
Refactor to use django_ynh
This commit is contained in:
parent
cca6eef925
commit
add1026c11
19 changed files with 173 additions and 440 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -6,3 +6,5 @@ __pycache__
|
||||||
secret.txt
|
secret.txt
|
||||||
/local_test/
|
/local_test/
|
||||||
/poetry.lock
|
/poetry.lock
|
||||||
|
/coverage.xml
|
||||||
|
/htmlcov/
|
||||||
|
|
15
Makefile
15
Makefile
|
@ -1,4 +1,5 @@
|
||||||
SHELL := /bin/bash
|
SHELL := /bin/bash
|
||||||
|
MAX_LINE_LENGTH := 119
|
||||||
|
|
||||||
all: help
|
all: help
|
||||||
|
|
||||||
|
@ -27,8 +28,18 @@ update: install-poetry ## update the sources and installation and generate "con
|
||||||
poetry update
|
poetry update
|
||||||
poetry export -f requirements.txt --output conf/requirements.txt
|
poetry export -f requirements.txt --output conf/requirements.txt
|
||||||
|
|
||||||
local-test: check-poetry ## Run local_test.py to run the project locally
|
lint: ## Run code formatters and linter
|
||||||
poetry run ./local_test.py
|
poetry run flynt --fail-on-change --line_length=${MAX_LINE_LENGTH} .
|
||||||
|
poetry run isort --check-only .
|
||||||
|
poetry run flake8 .
|
||||||
|
|
||||||
|
fix-code-style: ## Fix code formatting
|
||||||
|
poetry run flynt --line_length=${MAX_LINE_LENGTH} .
|
||||||
|
poetry run black --verbose --safe --line-length=${MAX_LINE_LENGTH} --skip-string-normalization .
|
||||||
|
poetry run isort .
|
||||||
|
|
||||||
|
local-test: install ## Run local_test.py to run the project locally
|
||||||
|
poetry run python3 ./local_test.py
|
||||||
|
|
||||||
local-diff-settings: ## Run "manage.py diffsettings" with local test
|
local-diff-settings: ## Run "manage.py diffsettings" with local test
|
||||||
poetry run python3 local_test/opt_yunohost/manage.py diffsettings
|
poetry run python3 local_test/opt_yunohost/manage.py diffsettings
|
||||||
|
|
|
@ -21,7 +21,7 @@ Pull requests welcome ;)
|
||||||
|
|
||||||
## Settings and upgrades
|
## Settings and upgrades
|
||||||
|
|
||||||
Almost everything related to PyInventory's configuration is handled in a `"../conf/ynh_pyinventory_settings.py"` file.
|
Almost everything related to PyInventory's configuration is handled in a `"../conf/settings.py"` file.
|
||||||
You can edit the file `$final_path/local_settings.py` to enable or disable features.
|
You can edit the file `$final_path/local_settings.py` to enable or disable features.
|
||||||
|
|
||||||
# Miscellaneous
|
# Miscellaneous
|
||||||
|
@ -100,13 +100,13 @@ drwxr-xr-x 3 root root 3 Dec 8 08:36 ..
|
||||||
-rw-r--r-- 1 pyinventory pyinventory 171 Dec 8 08:39 secret.txt
|
-rw-r--r-- 1 pyinventory pyinventory 171 Dec 8 08:39 secret.txt
|
||||||
drwxr-xr-x 6 pyinventory pyinventory 6 Dec 8 08:37 venv
|
drwxr-xr-x 6 pyinventory pyinventory 6 Dec 8 08:37 venv
|
||||||
-rw-r--r-- 1 pyinventory pyinventory 115 Dec 8 08:39 wsgi.py
|
-rw-r--r-- 1 pyinventory pyinventory 115 Dec 8 08:39 wsgi.py
|
||||||
-rw-r--r-- 1 pyinventory pyinventory 4737 Dec 8 08:39 ynh_pyinventory_settings.py
|
-rw-r--r-- 1 pyinventory pyinventory 4737 Dec 8 08:39 settings.py
|
||||||
|
|
||||||
root@yunohost:~# cd /opt/yunohost/pyinventory/
|
root@yunohost:~# cd /opt/yunohost/pyinventory/
|
||||||
root@yunohost:/opt/yunohost/pyinventory# source venv/bin/activate
|
root@yunohost:/opt/yunohost/pyinventory# source venv/bin/activate
|
||||||
(venv) root@yunohost:/opt/yunohost/pyinventory# ./manage.py check
|
(venv) root@yunohost:/opt/yunohost/pyinventory# ./manage.py check
|
||||||
PyInventory v0.8.2 (Django v2.2.17)
|
PyInventory v0.8.2 (Django v2.2.17)
|
||||||
DJANGO_SETTINGS_MODULE='ynh_pyinventory_settings'
|
DJANGO_SETTINGS_MODULE='settings'
|
||||||
PROJECT_PATH:/opt/yunohost/pyinventory/venv/lib/python3.7/site-packages
|
PROJECT_PATH:/opt/yunohost/pyinventory/venv/lib/python3.7/site-packages
|
||||||
BASE_PATH:/opt/yunohost/pyinventory
|
BASE_PATH:/opt/yunohost/pyinventory
|
||||||
System check identified no issues (0 silenced).
|
System check identified no issues (0 silenced).
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import argparse
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'ynh_pyinventory_settings'
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(
|
|
||||||
description='Create or update Django super user.'
|
|
||||||
)
|
|
||||||
parser.add_argument('--username')
|
|
||||||
parser.add_argument('--email')
|
|
||||||
parser.add_argument('--password')
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
username = args.username
|
|
||||||
email = args.email or ''
|
|
||||||
password = args.password
|
|
||||||
|
|
||||||
import django
|
|
||||||
django.setup()
|
|
||||||
|
|
||||||
from django.contrib.auth import get_user_model
|
|
||||||
User = get_user_model()
|
|
||||||
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(
|
|
||||||
username=username,
|
|
||||||
email=email,
|
|
||||||
password=password
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -3,6 +3,7 @@
|
||||||
"""
|
"""
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
|
|
||||||
|
|
||||||
bind = '127.0.0.1:__PORT__'
|
bind = '127.0.0.1:__PORT__'
|
||||||
|
|
||||||
# https://docs.gunicorn.org/en/latest/settings.html#workers
|
# https://docs.gunicorn.org/en/latest/settings.html#workers
|
||||||
|
|
|
@ -7,6 +7,7 @@ import sys
|
||||||
def main():
|
def main():
|
||||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
|
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
|
||||||
from django.core.management import execute_from_command_line
|
from django.core.management import execute_from_command_line
|
||||||
|
|
||||||
execute_from_command_line(sys.argv)
|
execute_from_command_line(sys.argv)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
bleach==3.2.1; python_version >= "3.7" and python_full_version < "3.0.0" or python_version >= "3.7" and python_full_version < "4.0.0" and python_full_version >= "3.5.0" \
|
bleach==3.2.1; python_version >= "3.7" and python_full_version < "3.0.0" or python_version >= "3.7" and python_full_version < "4.0.0" and python_full_version >= "3.5.0" \
|
||||||
--hash=sha256:9f8ccbeb6183c6e6cddea37592dfb0167485c1e3b13b3363bc325aa8bda3adbd \
|
--hash=sha256:9f8ccbeb6183c6e6cddea37592dfb0167485c1e3b13b3363bc325aa8bda3adbd \
|
||||||
--hash=sha256:52b5919b81842b1854196eaae5ca29679a2f2e378905c346d3ca8227c2c66080
|
--hash=sha256:52b5919b81842b1854196eaae5ca29679a2f2e378905c346d3ca8227c2c66080
|
||||||
bx-py-utils==18; python_version >= "3.7" and python_full_version < "4.0.0" \
|
bx-py-utils==18; python_version >= "3.6" and python_full_version < "4.0.0" \
|
||||||
--hash=sha256:72a6090822544603e3a7547ce07f0120ae67940ca2ec4590ac907b3b09ad70ca \
|
--hash=sha256:72a6090822544603e3a7547ce07f0120ae67940ca2ec4590ac907b3b09ad70ca \
|
||||||
--hash=sha256:195ea1b3d5d277354ea33e34ec3ebd4fc2a6e8d94d646ede902f80527f06ec75
|
--hash=sha256:195ea1b3d5d277354ea33e34ec3ebd4fc2a6e8d94d646ede902f80527f06ec75
|
||||||
certifi==2020.12.5; python_version >= "3.7" and python_full_version < "3.0.0" or python_version >= "3.7" and python_full_version < "4.0.0" and python_full_version >= "3.5.0" \
|
certifi==2020.12.5; python_version >= "3.7" and python_full_version < "3.0.0" or python_version >= "3.7" and python_full_version < "4.0.0" and python_full_version >= "3.5.0" \
|
||||||
|
@ -61,9 +61,9 @@ django-tagulous==1.1.0; python_version >= "3.7" and python_full_version < "4.0.0
|
||||||
django-tools==0.48.3; python_version >= "3.7" and python_full_version < "4.0.0" \
|
django-tools==0.48.3; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||||
--hash=sha256:08ed2ae606067f49c2c3949055227a826c8b880e5816114925eca386cf1823af \
|
--hash=sha256:08ed2ae606067f49c2c3949055227a826c8b880e5816114925eca386cf1823af \
|
||||||
--hash=sha256:40444fa16b703b7c6960a800ba76aad42472c9aa70040d549a4d91dbb47a5ddb
|
--hash=sha256:40444fa16b703b7c6960a800ba76aad42472c9aa70040d549a4d91dbb47a5ddb
|
||||||
django-ynh==0.1.0; python_version >= "3.7" and python_full_version < "4.0.0" \
|
django-ynh==0.1.2; python_version >= "3.7" and python_full_version < "4.0.0" \
|
||||||
--hash=sha256:db75d5d9f0b1744187168a1b815272cd8c86c9ecb0fd77c58517e82a2cd9b09b \
|
--hash=sha256:2efa30444f67252bbb7601e1b5631ce93ddf72a70b2216bb61363990de78ad4f \
|
||||||
--hash=sha256:955dc29f55c449e116876c7c920dc8451157bae2a246b1375822f5e47d4c6fd4
|
--hash=sha256:711b0f9ac183b2507a58cf644081aafefdc025ce585f6a8dad427ca3baf55a19
|
||||||
django==2.2.17; python_version >= "3.7" and python_full_version < "4.0.0" and python_version < "4.0" \
|
django==2.2.17; python_version >= "3.7" and python_full_version < "4.0.0" and python_version < "4.0" \
|
||||||
--hash=sha256:558cb27930defd9a6042133258caf797b2d1dee233959f537e3dc475cb49bd7c \
|
--hash=sha256:558cb27930defd9a6042133258caf797b2d1dee233959f537e3dc475cb49bd7c \
|
||||||
--hash=sha256:cf5370a4d7765a9dd6d42a7b96b53c74f9446cd38209211304b210fe0404b861
|
--hash=sha256:cf5370a4d7765a9dd6d42a7b96b53c74f9446cd38209211304b210fe0404b861
|
||||||
|
|
|
@ -11,9 +11,11 @@
|
||||||
|
|
||||||
from pathlib import Path as __Path
|
from pathlib import Path as __Path
|
||||||
|
|
||||||
|
from django_ynh.secret_key import get_or_create_secret as __get_or_create_secret
|
||||||
from inventory_project.settings.base import * # noqa
|
from inventory_project.settings.base import * # noqa
|
||||||
|
|
||||||
DEBUG = False
|
|
||||||
|
DEBUG = False # Don't turn DEBUG on in production!
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -31,40 +33,41 @@ PATH_URL = PATH_URL.strip('/')
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
ROOT_URLCONF = 'ynh_urls' # /opt/yunohost/pyinventory/ynh_urls.py
|
ROOT_URLCONF = 'urls' # /opt/yunohost/pyinventory/ynh_urls.py
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# Function that will be called to finalize a user profile:
|
||||||
|
YNH_SETUP_USER = 'setup_user.setup_project_user'
|
||||||
|
|
||||||
|
SECRET_KEY = __get_or_create_secret(FINAL_HOME_PATH / 'secret.txt') # /opt/yunohost/$app/secret.txt
|
||||||
|
|
||||||
|
INSTALLED_APPS.append('django_ynh')
|
||||||
|
|
||||||
|
MIDDLEWARE.insert(
|
||||||
|
MIDDLEWARE.index('django.contrib.auth.middleware.AuthenticationMiddleware') + 1,
|
||||||
|
# login a user via HTTP_REMOTE_USER header from SSOwat:
|
||||||
|
'django_ynh.sso_auth.auth_middleware.SSOwatRemoteUserMiddleware',
|
||||||
|
)
|
||||||
|
|
||||||
# Keep ModelBackend around for per-user permissions and superuser
|
# Keep ModelBackend around for per-user permissions and superuser
|
||||||
AUTHENTICATION_BACKENDS = (
|
AUTHENTICATION_BACKENDS = (
|
||||||
'axes.backends.AxesBackend', # AxesBackend should be the first backend!
|
'axes.backends.AxesBackend', # AxesBackend should be the first backend!
|
||||||
|
#
|
||||||
# Authenticate via SSO and nginx 'HTTP_REMOTE_USER' header:
|
# Authenticate via SSO and nginx 'HTTP_REMOTE_USER' header:
|
||||||
'ynh_authenticate.RemoteUserBackend',
|
'django_ynh.sso_auth.auth_backend.SSOwatUserBackend',
|
||||||
|
#
|
||||||
# Fallback to normal Django model backend:
|
# Fallback to normal Django model backend:
|
||||||
'django.contrib.auth.backends.ModelBackend',
|
'django.contrib.auth.backends.ModelBackend',
|
||||||
)
|
)
|
||||||
|
|
||||||
LOGIN_REDIRECT_URL = None
|
LOGIN_REDIRECT_URL = None
|
||||||
LOGIN_URL = '/yunohost/sso/'
|
LOGIN_URL = '/yunohost/sso/'
|
||||||
LOGOUT_REDIRECT_URL = '/yunohost/sso/'
|
LOGOUT_REDIRECT_URL = '/yunohost/sso/'
|
||||||
# /yunohost/sso/?action=logout
|
# /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',
|
|
||||||
)
|
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
ADMINS = (
|
ADMINS = (('__ADMIN__', '__ADMINMAIL__'),)
|
||||||
('__ADMIN__', '__ADMINMAIL__'),
|
|
||||||
)
|
|
||||||
|
|
||||||
MANAGERS = ADMINS
|
MANAGERS = ADMINS
|
||||||
|
|
||||||
|
@ -170,6 +173,7 @@ LOGGING = {
|
||||||
'django': {'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},
|
'axes': {'handlers': ['log_file', 'mail_admins'], 'level': 'WARNING', 'propagate': False},
|
||||||
'django_tools': {'handlers': ['log_file', 'mail_admins'], 'level': 'INFO', 'propagate': False},
|
'django_tools': {'handlers': ['log_file', 'mail_admins'], 'level': 'INFO', 'propagate': False},
|
||||||
|
'django_ynh': {'handlers': ['log_file', 'mail_admins'], 'level': 'INFO', 'propagate': False},
|
||||||
'inventory': {'handlers': ['log_file', 'mail_admins'], 'level': 'INFO', 'propagate': False},
|
'inventory': {'handlers': ['log_file', 'mail_admins'], 'level': 'INFO', 'propagate': False},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
8
conf/setup_user.py
Normal file
8
conf/setup_user.py
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
def setup_project_user(user):
|
||||||
|
"""
|
||||||
|
All users used the Django admin, so we need to set the "staff" user flag.
|
||||||
|
Called from django_ynh.sso_auth
|
||||||
|
"""
|
||||||
|
user.is_staff = True
|
||||||
|
user.save()
|
||||||
|
return user
|
|
@ -23,9 +23,7 @@ if settings.PATH_URL:
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# path(f'{settings.PATH_URL}/debug/', debug_view),
|
# path(f'{settings.PATH_URL}/debug/', debug_view),
|
||||||
path(f'{settings.PATH_URL}/', admin.site.urls),
|
path(f'{settings.PATH_URL}/', admin.site.urls),
|
||||||
|
|
||||||
path(f'{settings.PATH_URL}/ckeditor/', include('ckeditor_uploader.urls')),
|
path(f'{settings.PATH_URL}/ckeditor/', include('ckeditor_uploader.urls')),
|
||||||
|
|
||||||
# MEDIA_URL contains the "PATH_URL" already:
|
# MEDIA_URL contains the "PATH_URL" already:
|
||||||
path(settings.MEDIA_URL.lstrip('/'), include('django_tools.serve_media_app.urls')),
|
path(settings.MEDIA_URL.lstrip('/'), include('django_tools.serve_media_app.urls')),
|
||||||
]
|
]
|
||||||
|
|
|
@ -2,7 +2,11 @@
|
||||||
WSGI config
|
WSGI config
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
|
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
|
||||||
|
|
||||||
from django.core.wsgi import get_wsgi_application
|
from django.core.wsgi import get_wsgi_application # noqa
|
||||||
|
|
||||||
|
|
||||||
application = get_wsgi_application()
|
application = get_wsgi_application()
|
||||||
|
|
|
@ -1,185 +0,0 @@
|
||||||
"""
|
|
||||||
* 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
|
|
149
local_test.py
Executable file → Normal file
149
local_test.py
Executable file → Normal file
|
@ -1,154 +1,29 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Start PyInventory in YunoHost setup locally.
|
Build a "local_test" YunoHost installation and start the Django dev. server against it.
|
||||||
Note:
|
|
||||||
You can only run this script, if you are in a activated PyInventory venv!
|
Run via:
|
||||||
|
make local-test
|
||||||
|
|
||||||
see README for details ;)
|
see README for details ;)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
|
||||||
import shlex
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'ynh_pyinventory_settings'
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import inventory_project # noqa
|
from django_ynh.local_test import create_local_test
|
||||||
except ImportError as err:
|
except ImportError as err:
|
||||||
raise ImportError(
|
raise ImportError('Did you forget to activate a virtual environment?') from err
|
||||||
'Couldn\'t import PyInventory. Did you '
|
|
||||||
'forget to activate a virtual environment?'
|
|
||||||
) from err
|
|
||||||
|
|
||||||
|
BASE_PATH = Path(__file__).parent
|
||||||
BASE_PATH = Path(__file__).parent.absolute()
|
|
||||||
TEST_PATH = BASE_PATH / 'local_test'
|
|
||||||
CONF_PATH = BASE_PATH / 'conf'
|
|
||||||
|
|
||||||
FINAL_HOME_PATH = TEST_PATH / 'opt_yunohost'
|
|
||||||
FINAL_WWW_PATH = TEST_PATH / 'var_www'
|
|
||||||
LOG_FILE = TEST_PATH / 'var_log_pyinventory.log'
|
|
||||||
|
|
||||||
MANAGE_PY_FILE = CONF_PATH / 'manage.py'
|
|
||||||
CREATE_SUPERUSER_FILE = CONF_PATH / 'create_superuser.py'
|
|
||||||
SETTINGS_FILE = CONF_PATH / 'ynh_pyinventory_settings.py'
|
|
||||||
URLS_FILE = CONF_PATH / 'ynh_urls.py'
|
|
||||||
|
|
||||||
REPLACES = {
|
|
||||||
'__FINAL_HOME_PATH__': str(FINAL_HOME_PATH),
|
|
||||||
'__FINAL_WWW_PATH__': str(FINAL_WWW_PATH),
|
|
||||||
'__LOG_FILE__': str(TEST_PATH / 'var_log_pyinventory.log'),
|
|
||||||
|
|
||||||
'__PATH_URL__': 'app_path',
|
|
||||||
'__DOMAIN__': '127.0.0.1',
|
|
||||||
|
|
||||||
'django.db.backends.postgresql': 'django.db.backends.sqlite3',
|
|
||||||
"'NAME': '__APP__',": f"'NAME': '{TEST_PATH / 'test_db.sqlite'}',",
|
|
||||||
|
|
||||||
'django_redis.cache.RedisCache': 'django.core.cache.backends.dummy.DummyCache',
|
|
||||||
|
|
||||||
'DEBUG = False': 'DEBUG = True',
|
|
||||||
|
|
||||||
# Just use the default logging setup from PyInventory project:
|
|
||||||
'LOGGING = {': 'HACKED_DEACTIVATED_LOGGING = {',
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def verbose_check_call(command, verbose=True, **kwargs):
|
|
||||||
""" 'verbose' version of subprocess.check_call() """
|
|
||||||
if verbose:
|
|
||||||
print('_' * 100)
|
|
||||||
msg = f'Call: {command!r}'
|
|
||||||
verbose_kwargs = ', '.join(f'{k}={v!r}' for k, v in sorted(kwargs.items()))
|
|
||||||
if verbose_kwargs:
|
|
||||||
msg += f' (kwargs: {verbose_kwargs})'
|
|
||||||
print(f'{msg}\n', flush=True)
|
|
||||||
|
|
||||||
env = os.environ.copy()
|
|
||||||
env['PYTHONUNBUFFERED'] = '1'
|
|
||||||
|
|
||||||
popenargs = shlex.split(command)
|
|
||||||
subprocess.check_call(
|
|
||||||
popenargs,
|
|
||||||
universal_newlines=True,
|
|
||||||
env=env,
|
|
||||||
**kwargs
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def call_manage_py(args):
|
|
||||||
verbose_check_call(
|
|
||||||
command=f'{sys.executable} manage.py {args}',
|
|
||||||
cwd=FINAL_HOME_PATH,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def copy_patch(src_file, replaces=None):
|
|
||||||
dst_file = FINAL_HOME_PATH / src_file.name
|
|
||||||
print(f'{src_file.relative_to(BASE_PATH)} -> {dst_file.relative_to(BASE_PATH)}')
|
|
||||||
|
|
||||||
with src_file.open('r') as f:
|
|
||||||
content = f.read()
|
|
||||||
|
|
||||||
if replaces:
|
|
||||||
for old, new in replaces.items():
|
|
||||||
content = content.replace(old, new)
|
|
||||||
|
|
||||||
with dst_file.open('w') as f:
|
|
||||||
f.write(content)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
print('-' * 100)
|
create_local_test(
|
||||||
|
django_settings_path=BASE_PATH / 'conf' / 'settings.py',
|
||||||
assert BASE_PATH.is_dir()
|
destination=BASE_PATH / 'local_test',
|
||||||
assert CONF_PATH.is_dir()
|
runserver=True,
|
||||||
assert SETTINGS_FILE.is_file()
|
|
||||||
assert URLS_FILE.is_file()
|
|
||||||
|
|
||||||
for p in (TEST_PATH, FINAL_HOME_PATH, FINAL_WWW_PATH):
|
|
||||||
if p.is_dir():
|
|
||||||
print(f'Already exists: "{p.relative_to(BASE_PATH)}", ok.')
|
|
||||||
else:
|
|
||||||
print(f'Create: "{p.relative_to(BASE_PATH)}"')
|
|
||||||
p.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
LOG_FILE.touch(exist_ok=True)
|
|
||||||
|
|
||||||
# conf/manage.py -> local_test/manage.py
|
|
||||||
copy_patch(src_file=MANAGE_PY_FILE)
|
|
||||||
|
|
||||||
# conf/create_superuser.py -> local_test/opt_yunohost/create_superuser.py
|
|
||||||
copy_patch(src_file=CREATE_SUPERUSER_FILE)
|
|
||||||
|
|
||||||
# conf/ynh_pyinventory_settings.py -> local_test/ynh_pyinventory_settings.py
|
|
||||||
copy_patch(src_file=SETTINGS_FILE, replaces=REPLACES)
|
|
||||||
|
|
||||||
# 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/inventory_project/urls.py\n')
|
|
||||||
|
|
||||||
# call "local_test/manage.py" via subprocess:
|
|
||||||
call_manage_py('check --deploy')
|
|
||||||
call_manage_py('migrate --no-input')
|
|
||||||
call_manage_py('collectstatic --no-input')
|
|
||||||
|
|
||||||
verbose_check_call(
|
|
||||||
command=f'{sys.executable} create_superuser.py --username="test" --password="test"',
|
|
||||||
cwd=FINAL_HOME_PATH,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
|
||||||
call_manage_py('runserver --nostatic')
|
|
||||||
except KeyboardInterrupt:
|
|
||||||
print('\nBye ;)')
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
"description": {
|
"description": {
|
||||||
"en": "Web based management to catalog things including state and location etc."
|
"en": "Web based management to catalog things including state and location etc."
|
||||||
},
|
},
|
||||||
"version": "0.8.2~ynh4",
|
"version": "0.8.2~ynh5",
|
||||||
"url": "https://github.com/jedie/PyInventory",
|
"url": "https://github.com/jedie/PyInventory",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"maintainer": {
|
"maintainer": {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "pyinventory_ynh"
|
name = "pyinventory_ynh"
|
||||||
version = "0.8.2~ynh4"
|
version = "0.8.2~ynh5"
|
||||||
description = "Test pyinventory_ynh via local_test.py"
|
description = "Test pyinventory_ynh via local_test.py"
|
||||||
authors = ["JensDiemer <git@jensdiemer.de>"]
|
authors = ["JensDiemer <git@jensdiemer.de>"]
|
||||||
license = "GPL"
|
license = "GPL"
|
||||||
|
@ -11,7 +11,72 @@ pyinventory = "*"
|
||||||
django_ynh = "*"
|
django_ynh = "*"
|
||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
|
bx_py_utils = "*"
|
||||||
|
isort = "*"
|
||||||
|
flake8 = "*"
|
||||||
|
flynt = "*"
|
||||||
|
black = "*"
|
||||||
|
pyupgrade = "*"
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core>=1.0.0"]
|
requires = ["poetry-core>=1.0.0"]
|
||||||
build-backend = "poetry.core.masonry.api"
|
build-backend = "poetry.core.masonry.api"
|
||||||
|
|
||||||
|
|
||||||
|
[tool.isort]
|
||||||
|
# https://pycqa.github.io/isort/docs/configuration/config_files/#pyprojecttoml-preferred-format
|
||||||
|
atomic=true
|
||||||
|
line_length=120
|
||||||
|
case_sensitive=false
|
||||||
|
skip_glob=["*/htmlcov/*","*/migrations/*"]
|
||||||
|
multi_line_output=3
|
||||||
|
include_trailing_comma=true
|
||||||
|
known_first_party=["inventory"]
|
||||||
|
no_lines_before="LOCALFOLDER"
|
||||||
|
default_section="THIRDPARTY"
|
||||||
|
sections=["FUTURE","STDLIB","THIRDPARTY","FIRSTPARTY","LOCALFOLDER"]
|
||||||
|
lines_after_imports=2
|
||||||
|
|
||||||
|
|
||||||
|
[tool.pytest.ini_options]
|
||||||
|
# https://docs.pytest.org/en/latest/customize.html#pyproject-toml
|
||||||
|
minversion = "6.0"
|
||||||
|
norecursedirs = ".* .git __pycache__ conf coverage* dist htmlcov"
|
||||||
|
# sometimes helpfull "addopts" arguments:
|
||||||
|
# -vv
|
||||||
|
# --verbose
|
||||||
|
# --capture=no
|
||||||
|
# --trace-config
|
||||||
|
# --full-trace
|
||||||
|
# -p no:warnings
|
||||||
|
addopts = """
|
||||||
|
--import-mode=importlib
|
||||||
|
--reuse-db
|
||||||
|
--nomigrations
|
||||||
|
--cov=.
|
||||||
|
--cov-report term-missing
|
||||||
|
--cov-report html
|
||||||
|
--cov-report xml
|
||||||
|
--no-cov-on-fail
|
||||||
|
--showlocals
|
||||||
|
--doctest-modules
|
||||||
|
--failed-first
|
||||||
|
--last-failed-no-failures all
|
||||||
|
--new-first
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
[tool.tox]
|
||||||
|
# https://tox.readthedocs.io/en/latest/example/basic.html#pyproject-toml-tox-legacy-ini
|
||||||
|
legacy_tox_ini = """
|
||||||
|
[tox]
|
||||||
|
isolated_build = True
|
||||||
|
envlist = py39,py38,py37
|
||||||
|
skip_missing_interpreters = True
|
||||||
|
|
||||||
|
[testenv]
|
||||||
|
passenv = *
|
||||||
|
whitelist_externals = make
|
||||||
|
commands =
|
||||||
|
make pytest
|
||||||
|
"""
|
||||||
|
|
|
@ -27,9 +27,6 @@ log_file="${log_path}/pyinventory.log"
|
||||||
# dependencies used by the app
|
# dependencies used by the app
|
||||||
pkg_dependencies="build-essential python3-dev python3-pip python3-venv git postgresql postgresql-contrib"
|
pkg_dependencies="build-essential python3-dev python3-pip python3-venv git postgresql postgresql-contrib"
|
||||||
|
|
||||||
# PyInventory's version for PIP and settings file
|
|
||||||
pyinventory_version="0.8.2"
|
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# Redis HELPERS
|
# Redis HELPERS
|
||||||
#=================================================
|
#=================================================
|
||||||
|
|
|
@ -116,10 +116,10 @@ fi
|
||||||
ynh_script_progression --message="Modify PyInventory's config file..."
|
ynh_script_progression --message="Modify PyInventory's config file..."
|
||||||
|
|
||||||
# save old settings file
|
# save old settings file
|
||||||
settings="$final_path/ynh_pyinventory_settings.py"
|
settings="$final_path/settings.py"
|
||||||
ynh_backup_if_checksum_is_different --file="$settings"
|
ynh_backup_if_checksum_is_different --file="$settings"
|
||||||
|
|
||||||
cp "../conf/ynh_pyinventory_settings.py" "$settings"
|
cp "../conf/settings.py" "$settings"
|
||||||
|
|
||||||
ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_file="$settings"
|
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="__DB_PWD__" --replace_string="$db_pwd" --target_file="$settings"
|
||||||
|
|
|
@ -101,7 +101,7 @@ ynh_system_user_create --username="$app" --home_dir="$final_path" --use_shell
|
||||||
#=================================================
|
#=================================================
|
||||||
# PIP INSTALLATION
|
# PIP INSTALLATION
|
||||||
#=================================================
|
#=================================================
|
||||||
ynh_script_progression --message="Install PyInventory using PIP..." --weight=80
|
ynh_script_progression --message="Install project via pip..." --weight=80
|
||||||
|
|
||||||
python3 -m venv "${final_path}/venv"
|
python3 -m venv "${final_path}/venv"
|
||||||
cp ../conf/requirements.txt "$final_path/requirements.txt"
|
cp ../conf/requirements.txt "$final_path/requirements.txt"
|
||||||
|
@ -119,10 +119,7 @@ chown -R "$app" "$final_path"
|
||||||
#=================================================
|
#=================================================
|
||||||
# copy config files
|
# copy config files
|
||||||
# ================================================
|
# ================================================
|
||||||
ynh_script_progression --message="Create pyinventory configuration file..."
|
ynh_script_progression --message="Create project configuration files..."
|
||||||
|
|
||||||
cp ../conf/create_superuser.py "$final_path/create_superuser.py"
|
|
||||||
chmod +x "$final_path/create_superuser.py"
|
|
||||||
|
|
||||||
gunicorn_conf="$final_path/gunicorn.conf.py"
|
gunicorn_conf="$final_path/gunicorn.conf.py"
|
||||||
cp "../conf/gunicorn.conf.py" "$gunicorn_conf"
|
cp "../conf/gunicorn.conf.py" "$gunicorn_conf"
|
||||||
|
@ -134,10 +131,8 @@ ynh_store_file_checksum --file="$gunicorn_conf"
|
||||||
cp ../conf/manage.py "$final_path/manage.py"
|
cp ../conf/manage.py "$final_path/manage.py"
|
||||||
chmod +x "$final_path/manage.py"
|
chmod +x "$final_path/manage.py"
|
||||||
|
|
||||||
cp ../conf/wsgi.py "$final_path/wsgi.py"
|
settings="$final_path/settings.py"
|
||||||
|
cp "../conf/settings.py" "$settings"
|
||||||
settings="$final_path/ynh_pyinventory_settings.py"
|
|
||||||
cp "../conf/ynh_pyinventory_settings.py" "$settings"
|
|
||||||
|
|
||||||
ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_file="$settings"
|
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="__DB_PWD__" --replace_string="$db_pwd" --target_file="$settings"
|
||||||
|
@ -156,10 +151,11 @@ ynh_store_file_checksum --file="$settings"
|
||||||
|
|
||||||
ynh_app_setting_set --app="$app" --key=redis_db --value="$redis_db"
|
ynh_app_setting_set --app="$app" --key=redis_db --value="$redis_db"
|
||||||
|
|
||||||
touch "$final_path/local_settings.py"
|
cp ../conf/setup_user.py "$final_path/setup_user.py"
|
||||||
|
cp ../conf/urls.py "$final_path/urls.py"
|
||||||
|
cp ../conf/wsgi.py "$final_path/wsgi.py"
|
||||||
|
|
||||||
cp "../conf/ynh_authenticate.py" "$final_path/ynh_authenticate.py"
|
touch "$final_path/local_settings.py"
|
||||||
cp "../conf/ynh_urls.py" "$final_path/ynh_urls.py"
|
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# MIGRATE / COLLECTSTATIC / CREATEADMIN
|
# MIGRATE / COLLECTSTATIC / CREATEADMIN
|
||||||
|
@ -177,7 +173,9 @@ ynh_script_progression --message="migrate/collectstatic/createadmin..." --weight
|
||||||
|
|
||||||
./manage.py migrate --no-input
|
./manage.py migrate --no-input
|
||||||
./manage.py collectstatic --no-input
|
./manage.py collectstatic --no-input
|
||||||
./create_superuser.py --username="$admin" --email="$admin_mail" --password="pyinventory"
|
|
||||||
|
# Create/update Django superuser (set unusable password, because auth done via SSOwat):
|
||||||
|
./manage.py create_superuser --username="$admin" --email="$admin_mail"
|
||||||
|
|
||||||
# Check the configuration
|
# Check the configuration
|
||||||
# This may fail in some cases with errors, etc., but the app works and the user can fix issues later.
|
# This may fail in some cases with errors, etc., but the app works and the user can fix issues later.
|
||||||
|
|
|
@ -83,10 +83,9 @@ ynh_script_progression --message="Configuring a systemd service..."
|
||||||
ynh_add_systemd_config --service="$app" --template="pyinventory.service"
|
ynh_add_systemd_config --service="$app" --template="pyinventory.service"
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# UPGRADE PYINVENTORY
|
# UPGRADE VENV
|
||||||
#=================================================
|
#=================================================
|
||||||
|
ynh_script_progression --message="Upgrade project via pip..." --weight=80
|
||||||
ynh_script_progression --message="Install pyinventory using PIP..." --weight=15
|
|
||||||
|
|
||||||
python3 -m venv "${final_path}/venv"
|
python3 -m venv "${final_path}/venv"
|
||||||
cp ../conf/requirements.txt "$final_path/requirements.txt"
|
cp ../conf/requirements.txt "$final_path/requirements.txt"
|
||||||
|
@ -94,21 +93,17 @@ chown -R "$app" "$final_path"
|
||||||
|
|
||||||
#run source in a 'sub shell'
|
#run source in a 'sub shell'
|
||||||
(
|
(
|
||||||
set +o nounset
|
set +o nounset
|
||||||
source "${final_path}/venv/bin/activate"
|
source "${final_path}/venv/bin/activate"
|
||||||
set -o nounset
|
set -o nounset
|
||||||
ynh_exec_as $app $final_path/venv/bin/pip install --upgrade pip
|
ynh_exec_as $app $final_path/venv/bin/pip install --upgrade pip
|
||||||
ynh_exec_as $app $final_path/venv/bin/pip install -r "$final_path/requirements.txt"
|
ynh_exec_as $app $final_path/venv/bin/pip install -r "$final_path/requirements.txt"
|
||||||
)
|
)
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# copy config files
|
# copy config files
|
||||||
# ================================================
|
# ================================================
|
||||||
ynh_script_progression --message="Create pyinventory configuration file..."
|
ynh_script_progression --message="Create project configuration files..."
|
||||||
|
|
||||||
ynh_backup_if_checksum_is_different --file="$final_path/create_superuser.py"
|
|
||||||
cp ../conf/create_superuser.py "$final_path/create_superuser.py"
|
|
||||||
chmod +x "$final_path/create_superuser.py"
|
|
||||||
|
|
||||||
gunicorn_conf="$final_path/gunicorn.conf.py"
|
gunicorn_conf="$final_path/gunicorn.conf.py"
|
||||||
ynh_backup_if_checksum_is_different --file="$gunicorn_conf"
|
ynh_backup_if_checksum_is_different --file="$gunicorn_conf"
|
||||||
|
@ -122,14 +117,11 @@ ynh_backup_if_checksum_is_different --file="$final_path/manage.py"
|
||||||
cp ../conf/manage.py "$final_path/manage.py"
|
cp ../conf/manage.py "$final_path/manage.py"
|
||||||
chmod +x "$final_path/manage.py"
|
chmod +x "$final_path/manage.py"
|
||||||
|
|
||||||
ynh_backup_if_checksum_is_different --file="$final_path/wsgi.py"
|
|
||||||
cp ../conf/wsgi.py "$final_path/wsgi.py"
|
|
||||||
|
|
||||||
# save old settings file
|
# save old settings file
|
||||||
settings="$final_path/ynh_pyinventory_settings.py"
|
settings="$final_path/settings.py"
|
||||||
ynh_backup_if_checksum_is_different --file="$settings"
|
ynh_backup_if_checksum_is_different --file="$settings"
|
||||||
|
|
||||||
cp "../conf/ynh_pyinventory_settings.py" "$settings"
|
cp "../conf/settings.py" "$settings"
|
||||||
|
|
||||||
ynh_replace_string --match_string="__APP__" --replace_string="$app" --target_file="$settings"
|
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="__DB_PWD__" --replace_string="$db_pwd" --target_file="$settings"
|
||||||
|
@ -146,10 +138,16 @@ ynh_replace_string --match_string="__PATH_URL__" --replace_string="$path_url" --
|
||||||
# Recalculate and store the config file checksum into the app settings
|
# Recalculate and store the config file checksum into the app settings
|
||||||
ynh_store_file_checksum --file="$settings"
|
ynh_store_file_checksum --file="$settings"
|
||||||
|
|
||||||
touch "$final_path/local_settings.py"
|
ynh_backup_if_checksum_is_different --file="$final_path/setup_user.py"
|
||||||
|
cp ../conf/setup_user.py "$final_path/setup_user.py"
|
||||||
|
|
||||||
cp "../conf/ynh_authenticate.py" "$final_path/ynh_authenticate.py"
|
ynh_backup_if_checksum_is_different --file="$final_path/urls.py"
|
||||||
cp "../conf/ynh_urls.py" "$final_path/ynh_urls.py"
|
cp ../conf/urls.py "$final_path/urls.py"
|
||||||
|
|
||||||
|
ynh_backup_if_checksum_is_different --file="$final_path/wsgi.py"
|
||||||
|
cp ../conf/wsgi.py "$final_path/wsgi.py"
|
||||||
|
|
||||||
|
touch "$final_path/local_settings.py"
|
||||||
|
|
||||||
#=================================================
|
#=================================================
|
||||||
# MIGRATE PYINVENTORY
|
# MIGRATE PYINVENTORY
|
||||||
|
@ -167,7 +165,9 @@ ynh_script_progression --message="migrate/collectstatic/createadmin..." --weight
|
||||||
|
|
||||||
./manage.py migrate --no-input
|
./manage.py migrate --no-input
|
||||||
./manage.py collectstatic --no-input
|
./manage.py collectstatic --no-input
|
||||||
./create_superuser.py --username="$admin" --email="$admin_mail" --password="pyinventory"
|
|
||||||
|
# Create/update Django superuser (set unusable password, because auth done via SSOwat):
|
||||||
|
./manage.py create_superuser --username="$admin" --email="$admin_mail"
|
||||||
|
|
||||||
# Check the configuration
|
# Check the configuration
|
||||||
# This may fail in some cases with errors, etc., but the app works and the user can fix issues later.
|
# This may fail in some cases with errors, etc., but the app works and the user can fix issues later.
|
||||||
|
|
Loading…
Reference in a new issue