mirror of
https://github.com/sissbruecker/linkding
synced 2024-11-10 06:04:15 +00:00
Add option to create initial superuser (#323)
* Add option to create initial superuser * Update .env.sample
This commit is contained in:
parent
5841ba0f4c
commit
f88cc30b48
5 changed files with 112 additions and 0 deletions
12
.env.sample
12
.env.sample
|
@ -8,7 +8,19 @@ LD_HOST_DATA_DIR=./data
|
|||
# Must end with a slash `/`
|
||||
LD_CONTEXT_PATH=
|
||||
|
||||
# Username of the initial superuser to create, leave empty to not create one
|
||||
LD_SUPERUSER_NAME=
|
||||
# Password for the initial superuser, leave empty to disable credentials authentication and rely on proxy authentication instead
|
||||
LD_SUPERUSER_PASSWORD=
|
||||
# Option to disable background tasks
|
||||
LD_DISABLE_BACKGROUND_TASKS=False
|
||||
# Option to disable URL validation for bookmarks completely
|
||||
LD_DISABLE_URL_VALIDATION=False
|
||||
# Enables support for authentication proxies such as Authelia
|
||||
LD_ENABLE_AUTH_PROXY=False
|
||||
# Name of the request header that the auth proxy passes to the application to identify the user
|
||||
# See docs/Options.md for more details
|
||||
LD_AUTH_PROXY_USERNAME_HEADER=
|
||||
# The URL that linkding should redirect to after a logout, when using an auth proxy
|
||||
# See docs/Options.md for more details
|
||||
LD_AUTH_PROXY_LOGOUT_URL=
|
||||
|
|
37
bookmarks/management/commands/create_initial_superuser.py
Normal file
37
bookmarks/management/commands/create_initial_superuser.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
import os
|
||||
import logging
|
||||
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Creates an initial superuser for a deployment using env variables"
|
||||
|
||||
def handle(self, *args, **options):
|
||||
User = get_user_model()
|
||||
superuser_name = os.getenv('LD_SUPERUSER_NAME', None)
|
||||
superuser_password = os.getenv('LD_SUPERUSER_PASSWORD', None)
|
||||
|
||||
# Skip if option is undefined
|
||||
if not superuser_name:
|
||||
logger.info('Skip creating initial superuser, LD_SUPERUSER_NAME option is not defined')
|
||||
return
|
||||
|
||||
# Skip if user already exists
|
||||
user_exists = User.objects.filter(username=superuser_name).exists()
|
||||
if user_exists:
|
||||
logger.info('Skip creating initial superuser, user already exists')
|
||||
return
|
||||
|
||||
user = User(username=superuser_name, is_superuser=True, is_staff=True)
|
||||
|
||||
if superuser_password:
|
||||
user.set_password(superuser_password)
|
||||
else:
|
||||
user.set_unusable_password()
|
||||
|
||||
user.save()
|
||||
logger.info('Created initial superuser')
|
45
bookmarks/tests/test_create_initial_superuser_command.py
Normal file
45
bookmarks/tests/test_create_initial_superuser_command.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
import os
|
||||
from unittest import mock
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
from bookmarks.models import User
|
||||
from bookmarks.management.commands.create_initial_superuser import Command
|
||||
|
||||
|
||||
class TestCreateInitialSuperuserCommand(TestCase):
|
||||
|
||||
@mock.patch.dict(os.environ, {'LD_SUPERUSER_NAME': 'john', 'LD_SUPERUSER_PASSWORD': 'password123'})
|
||||
def test_create_with_password(self):
|
||||
Command().handle()
|
||||
|
||||
self.assertEqual(1, User.objects.count())
|
||||
|
||||
user = User.objects.first()
|
||||
self.assertEqual('john', user.username)
|
||||
self.assertTrue(user.has_usable_password())
|
||||
self.assertTrue(user.check_password('password123'))
|
||||
|
||||
@mock.patch.dict(os.environ, {'LD_SUPERUSER_NAME': 'john'})
|
||||
def test_create_without_password(self):
|
||||
Command().handle()
|
||||
|
||||
self.assertEqual(1, User.objects.count())
|
||||
|
||||
user = User.objects.first()
|
||||
self.assertEqual('john', user.username)
|
||||
self.assertFalse(user.has_usable_password())
|
||||
|
||||
def test_create_without_options(self):
|
||||
Command().handle()
|
||||
|
||||
self.assertEqual(0, User.objects.count())
|
||||
|
||||
@mock.patch.dict(os.environ, {'LD_SUPERUSER_NAME': 'john', 'LD_SUPERUSER_PASSWORD': 'password123'})
|
||||
def test_create_multiple_times(self):
|
||||
Command().handle()
|
||||
Command().handle()
|
||||
Command().handle()
|
||||
|
||||
self.assertEqual(1, User.objects.count())
|
||||
|
|
@ -10,6 +10,8 @@ mkdir -p data
|
|||
python manage.py migrate
|
||||
# Generate secret key file if it does not exist
|
||||
python manage.py generate_secret_key
|
||||
# Create initial superuser if defined in options / environment variables
|
||||
python manage.py create_initial_superuser
|
||||
|
||||
# Ensure the DB folder is owned by the right user
|
||||
chown -R www-data: /etc/linkding/data
|
||||
|
|
|
@ -25,6 +25,22 @@ All options need to be defined as environment variables in the environment that
|
|||
|
||||
## List of options
|
||||
|
||||
### `LD_SUPERUSER_NAME`
|
||||
|
||||
Values: `String` | Default = None
|
||||
|
||||
When set, creates an initial superuser with the specified username when starting the container.
|
||||
Does nothing if the user already exists.
|
||||
|
||||
See [`LD_SUPERUSER_PASSWORD`](#ld_superuser_password) on how to configure the respective password.
|
||||
|
||||
### `LD_SUPERUSER_PASSWORD`
|
||||
|
||||
Values: `String` | Default = None
|
||||
|
||||
The password for the initial superuser.
|
||||
When left undefined, the superuser will be created without a usable password, which means the user can not authenticate using credentials / through the login form, and can only be authenticated using proxy authentication (see [`LD_ENABLE_AUTH_PROXY`](#ld_enable_auth_proxy)).
|
||||
|
||||
### `LD_DISABLE_BACKGROUND_TASKS`
|
||||
|
||||
Values: `True`, `False` | Default = `False`
|
||||
|
|
Loading…
Reference in a new issue