mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-05-27 10:44:33 +00:00
firstboot: Indentation & styling fixes
pycodestyle version used is 2.1.0 with default arguments.
This commit is contained in:
parent
a2d4719685
commit
c37aa0fbd5
@ -22,12 +22,16 @@ Plinth module for first boot wizard
|
||||
version = 1
|
||||
|
||||
is_essential = True
|
||||
first_boot_steps = [{'id': 'firstboot_state0',
|
||||
'url': 'first_boot:state0',
|
||||
'order': 0
|
||||
},
|
||||
{'id': 'firstboot_state10',
|
||||
'url': 'first_boot:state10',
|
||||
'order': 10
|
||||
}
|
||||
]
|
||||
|
||||
first_boot_steps = [
|
||||
{
|
||||
'id': 'firstboot_state0',
|
||||
'url': 'first_boot:state0',
|
||||
'order': 0
|
||||
},
|
||||
{
|
||||
'id': 'firstboot_state10',
|
||||
'url': 'first_boot:state10',
|
||||
'order': 10
|
||||
}
|
||||
]
|
||||
|
||||
@ -1,196 +0,0 @@
|
||||
#
|
||||
# This file is part of Plinth.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
"""
|
||||
Forms for first boot module.
|
||||
"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
import requests
|
||||
|
||||
from django import forms
|
||||
from django.contrib import auth
|
||||
from django.contrib import messages
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
|
||||
from plinth import actions
|
||||
from plinth import cfg
|
||||
from plinth.errors import ActionError, DomainRegistrationError
|
||||
from plinth.modules.pagekite.utils import PREDEFINED_SERVICES, run
|
||||
from plinth.modules.security import set_restricted_access
|
||||
from plinth.modules.users.forms import GROUP_CHOICES, ValidNewUsernameCheckMixin
|
||||
from plinth.utils import format_lazy
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class State1Form(ValidNewUsernameCheckMixin, auth.forms.UserCreationForm):
|
||||
"""Firstboot state 1: create a new user."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.request = kwargs.pop('request')
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def save(self, commit=True):
|
||||
"""Create and log the user in."""
|
||||
user = super().save(commit=commit)
|
||||
if commit:
|
||||
try:
|
||||
actions.superuser_run(
|
||||
'ldap',
|
||||
['create-user', user.get_username()],
|
||||
input=self.cleaned_data['password1'].encode())
|
||||
except ActionError:
|
||||
messages.error(self.request,
|
||||
_('Creating LDAP user failed.'))
|
||||
|
||||
try:
|
||||
actions.superuser_run(
|
||||
'ldap',
|
||||
['add-user-to-group', user.get_username(), 'admin'])
|
||||
except ActionError:
|
||||
messages.error(self.request,
|
||||
_('Failed to add new user to admin group.'))
|
||||
|
||||
# Create initial Django groups
|
||||
for group_choice in GROUP_CHOICES:
|
||||
auth.models.Group.objects.get_or_create(name=group_choice[0])
|
||||
|
||||
admin_group = auth.models.Group.objects.get(name='admin')
|
||||
admin_group.user_set.add(user)
|
||||
|
||||
self.login_user(self.cleaned_data['username'],
|
||||
self.cleaned_data['password1'])
|
||||
|
||||
# Restrict console login to users in admin or sudo group
|
||||
try:
|
||||
set_restricted_access(True)
|
||||
message = _('Console login access restricted to users in '
|
||||
'"admin" group. This can be configured in '
|
||||
'security settings.')
|
||||
messages.success(self.request, message)
|
||||
except Exception:
|
||||
messages.error(self.request,
|
||||
_('Failed to restrict console access.'))
|
||||
|
||||
return user
|
||||
|
||||
def login_user(self, username, password):
|
||||
"""Try to login the user with the credentials provided"""
|
||||
try:
|
||||
user = auth.authenticate(username=username, password=password)
|
||||
auth.login(self.request, user)
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
message = _('User account created, you are now logged in')
|
||||
messages.success(self.request, message)
|
||||
|
||||
|
||||
class State5Form(forms.Form):
|
||||
"""Set up freedombox.me pagekite subdomain"""
|
||||
DOMAIN_APPENDIX = '.freedombox.me'
|
||||
# Webservice url for domain validation and registration
|
||||
service_url = 'http://freedombox.me/cgi-bin/freedomkite.pl'
|
||||
|
||||
code_help_text = format_lazy(
|
||||
ugettext_lazy('The voucher you received with your {box_name} Danube '
|
||||
'Edition'), box_name=ugettext_lazy(cfg.box_name))
|
||||
|
||||
code = forms.CharField(help_text=code_help_text)
|
||||
|
||||
domain = forms.SlugField(label=_('Subdomain'),
|
||||
widget=SubdomainWidget(domain=DOMAIN_APPENDIX),
|
||||
help_text=_('The subdomain you want to register'))
|
||||
|
||||
def clean_domain(self):
|
||||
"""Append the domain to the users' subdomain"""
|
||||
return self.cleaned_data['domain'] + self.DOMAIN_APPENDIX
|
||||
|
||||
def clean(self):
|
||||
"""Validate user input (subdomain and code)"""
|
||||
cleaned_data = super().clean()
|
||||
|
||||
# If the subdomain is wrong, don't look if the domain is
|
||||
# available
|
||||
if self.errors:
|
||||
return cleaned_data
|
||||
|
||||
self.domain_already_registered = False
|
||||
code = cleaned_data.get('code')
|
||||
domain = cleaned_data.get('domain')
|
||||
|
||||
response = requests.get(self.service_url, params={'code': code}).json()
|
||||
|
||||
# 1. Code is invalid: {}
|
||||
if 'domain' not in response:
|
||||
raise ValidationError(_('This code is not valid'), code='invalid')
|
||||
# 2. Code is valid, domain registered: {'domain': 'xx.freedombox.me'}
|
||||
elif response['domain']:
|
||||
if response['domain'] == domain:
|
||||
self.domain_already_registered = True
|
||||
else:
|
||||
message = _('This code is bound to the domain {domain}.') \
|
||||
.format(domain=response['domain'])
|
||||
raise ValidationError(message, code='invalid')
|
||||
# 3. Code is valid, no domain registered: {'domain': None}
|
||||
elif response['domain'] is None:
|
||||
# Make sure that the desired domain is available
|
||||
data = {'domain': domain}
|
||||
domain_response = requests.get(self.service_url, params=data)
|
||||
registered_domain = domain_response.json()['domain']
|
||||
if registered_domain is not None:
|
||||
message = _('The requested domain is already registered.')
|
||||
raise ValidationError(message, code='invalid')
|
||||
|
||||
return cleaned_data
|
||||
|
||||
def register_domain(self):
|
||||
"""Register a domain (only if it's not already registered)"""
|
||||
if self.domain_already_registered:
|
||||
return
|
||||
|
||||
data = {'domain': self.cleaned_data['domain'],
|
||||
'code': self.cleaned_data['code']}
|
||||
response = requests.post(self.service_url, data)
|
||||
if not response.ok:
|
||||
message = _('Domain registration failed: {response}.').format(
|
||||
response=response.text)
|
||||
logger.error(message)
|
||||
raise DomainRegistrationError(message)
|
||||
|
||||
def setup_pagekite(self):
|
||||
"""Configure and enable PageKite service."""
|
||||
# Set kite name and secret
|
||||
run(['set-kite', '--kite-name', self.cleaned_data['domain']],
|
||||
input=self.cleaned_data['code'].encode())
|
||||
|
||||
# Set frontend
|
||||
run(['set-frontend', '%s:80' % self.cleaned_data['domain']])
|
||||
|
||||
# Enable PageKite HTTP + HTTPS service
|
||||
for service_name in ['http', 'https']:
|
||||
service = PREDEFINED_SERVICES[service_name]['params']
|
||||
try:
|
||||
run(['add-service', '--service', json.dumps(service)])
|
||||
except ActionError as err:
|
||||
if 'already exists' not in str(err):
|
||||
raise
|
||||
|
||||
run(['start-and-enable'])
|
||||
@ -43,8 +43,10 @@ class FirstBootMiddleware(object):
|
||||
if state == 0 and old_state == 10:
|
||||
state = 1
|
||||
kvstore.set('setup_state', 1)
|
||||
|
||||
user_requests_firstboot = is_firstboot(request.path)
|
||||
user_requests_login = request.path.startswith(reverse(settings.LOGIN_URL))
|
||||
user_requests_login = request.path.startswith(
|
||||
reverse(settings.LOGIN_URL))
|
||||
help_index_url = reverse('help:index')
|
||||
user_requests_help = request.path.startswith(help_index_url)
|
||||
if not user_requests_login and not user_requests_help:
|
||||
@ -65,6 +67,7 @@ def is_firstboot(path):
|
||||
for step in steps:
|
||||
if reverse(step.get('url')) == path:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
@ -76,6 +79,7 @@ def get_firstboot_steps():
|
||||
if getattr(module_object, 'first_boot_steps', None):
|
||||
for step in module_object.first_boot_steps:
|
||||
steps.append(step)
|
||||
|
||||
steps = sorted(steps, key=itemgetter('order'))
|
||||
return steps
|
||||
|
||||
@ -85,6 +89,7 @@ def next_step():
|
||||
global firstboot_steps
|
||||
if len(firstboot_steps) == 0:
|
||||
firstboot_steps = get_firstboot_steps()
|
||||
|
||||
for step in firstboot_steps:
|
||||
done = kvstore.get_default(step.get('id'), 0)
|
||||
if done == 0:
|
||||
@ -100,11 +105,13 @@ def mark_step_done(id):
|
||||
global firstboot_steps
|
||||
if len(firstboot_steps) == 0:
|
||||
firstboot_steps = get_firstboot_steps()
|
||||
|
||||
setup_done = True
|
||||
for step in firstboot_steps:
|
||||
done = kvstore.get_default(step.get('id'), 0)
|
||||
if done == 0:
|
||||
setup_done = False
|
||||
break
|
||||
|
||||
if setup_done:
|
||||
kvstore.set('setup_state', 1)
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
from django.contrib.auth.models import User
|
||||
from django.shortcuts import render
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.views.generic import CreateView, FormView, TemplateView
|
||||
from django.views.generic import TemplateView
|
||||
from plinth import network
|
||||
from .middleware import mark_step_done, next_step
|
||||
|
||||
@ -29,7 +29,7 @@ class State0View(TemplateView):
|
||||
template_name = 'firstboot_state0.html'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
"""Returns the context data"""
|
||||
"""Returns the context data for the template."""
|
||||
context = super(State0View, self).get_context_data(**kwargs)
|
||||
mark_step_done('firstboot_state0')
|
||||
context['next_url'] = next_step()
|
||||
|
||||
@ -31,11 +31,13 @@ depends = ['system', 'names']
|
||||
|
||||
managed_packages = ['pagekite']
|
||||
|
||||
first_boot_steps = [{'id': 'pagekite_firstboot',
|
||||
'url': 'pagekite:firstboot',
|
||||
'order': 5,
|
||||
},
|
||||
]
|
||||
first_boot_steps = [
|
||||
{
|
||||
'id': 'pagekite_firstboot',
|
||||
'url': 'pagekite:firstboot',
|
||||
'order': 5,
|
||||
},
|
||||
]
|
||||
|
||||
title = _('Public Visibility (PageKite)')
|
||||
|
||||
|
||||
@ -25,13 +25,12 @@ from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
import json
|
||||
import logging
|
||||
|
||||
from . import utils
|
||||
from plinth import cfg
|
||||
from plinth.errors import ActionError, DomainRegistrationError
|
||||
from plinth.modules.pagekite.utils import PREDEFINED_SERVICES, run
|
||||
from plinth.utils import format_lazy
|
||||
|
||||
from . import utils
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -71,9 +70,9 @@ class ConfigurationForm(forms.Form):
|
||||
|
||||
server_domain = forms.CharField(
|
||||
label=ugettext_lazy('Server domain'), required=False,
|
||||
help_text= \
|
||||
ugettext_lazy('Select your pagekite server. Set "pagekite.net" to use '
|
||||
'the default pagekite.net server.'),
|
||||
help_text=ugettext_lazy(
|
||||
'Select your pagekite server. Set "pagekite.net" to use '
|
||||
'the default pagekite.net server.'),
|
||||
widget=forms.TextInput())
|
||||
server_port = forms.IntegerField(
|
||||
label=ugettext_lazy('Server port'), required=False,
|
||||
@ -87,9 +86,9 @@ class ConfigurationForm(forms.Form):
|
||||
|
||||
kite_secret = TrimmedCharField(
|
||||
label=ugettext_lazy('Kite secret'),
|
||||
help_text= \
|
||||
ugettext_lazy('A secret associated with the kite or the default secret '
|
||||
'for your account if no secret is set on the kite.'))
|
||||
help_text=ugettext_lazy(
|
||||
'A secret associated with the kite or the default secret '
|
||||
'for your account if no secret is set on the kite.'))
|
||||
|
||||
def save(self, request):
|
||||
"""Save the form on submission after validation."""
|
||||
@ -101,14 +100,14 @@ class ConfigurationForm(forms.Form):
|
||||
config_changed = False
|
||||
|
||||
if old['kite_name'] != new['kite_name'] or \
|
||||
old['kite_secret'] != new['kite_secret']:
|
||||
old['kite_secret'] != new['kite_secret']:
|
||||
utils.run(['set-kite', '--kite-name', new['kite_name']],
|
||||
input=new['kite_secret'].encode())
|
||||
messages.success(request, _('Kite details set'))
|
||||
config_changed = True
|
||||
|
||||
if old['server_domain'] != new['server_domain'] or \
|
||||
old['server_port'] != new['server_port']:
|
||||
old['server_port'] != new['server_port']:
|
||||
server = "%s:%s" % (new['server_domain'], new['server_port'])
|
||||
utils.run(['set-frontend', server])
|
||||
messages.success(request, _('Pagekite server set'))
|
||||
@ -208,6 +207,8 @@ class BaseCustomServiceForm(forms.Form):
|
||||
|
||||
|
||||
class DeleteCustomServiceForm(BaseCustomServiceForm):
|
||||
"""Form to remove custom service."""
|
||||
|
||||
def delete(self, request):
|
||||
service = self.convert_formdata_to_service(self.cleaned_data)
|
||||
utils.run(['remove-service', '--service', json.dumps(service)])
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
from django.contrib import messages
|
||||
from django.http.response import HttpResponseRedirect
|
||||
from django.template.response import TemplateResponse
|
||||
@ -21,11 +22,11 @@ from django.urls import reverse, reverse_lazy
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.views.generic import View, TemplateView
|
||||
from django.views.generic.edit import FormView
|
||||
from plinth.errors import DomainRegistrationError
|
||||
|
||||
from . import utils
|
||||
from .forms import ConfigurationForm, StandardServiceForm, \
|
||||
AddCustomServiceForm, DeleteCustomServiceForm, State5Form
|
||||
from plinth.errors import DomainRegistrationError
|
||||
from plinth.modules import pagekite
|
||||
from plinth.modules.first_boot.middleware import mark_step_done
|
||||
|
||||
|
||||
@ -34,11 +34,15 @@ depends = ['system']
|
||||
|
||||
managed_packages = ['ldapscripts', 'ldap-utils', 'libnss-ldapd',
|
||||
'libpam-ldapd', 'nslcd', 'slapd']
|
||||
first_boot_steps = [{'id': 'users_firstboot',
|
||||
'url': 'users:firstboot',
|
||||
'order': 1
|
||||
},
|
||||
]
|
||||
|
||||
first_boot_steps = [
|
||||
{
|
||||
'id': 'users_firstboot',
|
||||
'url': 'users:firstboot',
|
||||
'order': 1
|
||||
},
|
||||
]
|
||||
|
||||
title = _('Users and Groups')
|
||||
|
||||
|
||||
@ -80,4 +84,4 @@ def _diagnose_ldap_entry(search_item):
|
||||
pass
|
||||
|
||||
return [_('Check LDAP entry "{search_item}"')
|
||||
.format(search_item=search_item), result]
|
||||
.format(search_item=search_item), result]
|
||||
|
||||
@ -27,11 +27,9 @@ from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
|
||||
from plinth import actions
|
||||
from plinth.errors import ActionError
|
||||
|
||||
from plinth.modules.security import set_restricted_access
|
||||
|
||||
# Usernames used by optional services (that might not be installed yet).
|
||||
|
||||
RESERVED_USERNAMES = [
|
||||
'debian-deluged',
|
||||
'Debian-minetest',
|
||||
@ -95,14 +93,14 @@ class CreateUserForm(ValidNewUsernameCheckMixin, UserCreationForm):
|
||||
label=ugettext_lazy('Groups'),
|
||||
required=False,
|
||||
widget=forms.CheckboxSelectMultiple,
|
||||
help_text= \
|
||||
ugettext_lazy('Select which services should be available to the new '
|
||||
'user. The user will be able to log in to services that '
|
||||
'support single sign-on through LDAP, if they are in the '
|
||||
'appropriate group.<br /><br />Users in the admin group '
|
||||
'will be able to log in to all services. They can also '
|
||||
'log in to the system through SSH and have '
|
||||
'administrative privileges (sudo).'))
|
||||
help_text=ugettext_lazy(
|
||||
'Select which services should be available to the new '
|
||||
'user. The user will be able to log in to services that '
|
||||
'support single sign-on through LDAP, if they are in the '
|
||||
'appropriate group.<br /><br />Users in the admin group '
|
||||
'will be able to log in to all services. They can also '
|
||||
'log in to the system through SSH and have '
|
||||
'administrative privileges (sudo).'))
|
||||
|
||||
def __init__(self, request, *args, **kwargs):
|
||||
"""Initialize the form with extra request argument."""
|
||||
@ -132,7 +130,7 @@ class CreateUserForm(ValidNewUsernameCheckMixin, UserCreationForm):
|
||||
messages.error(
|
||||
self.request,
|
||||
_('Failed to add new user to {group} group.')
|
||||
.format(group=group))
|
||||
.format(group=group))
|
||||
|
||||
group_object, created = Group.objects.get_or_create(name=group)
|
||||
group_object.user_set.add(user)
|
||||
@ -146,12 +144,12 @@ class UserUpdateForm(ValidNewUsernameCheckMixin, forms.ModelForm):
|
||||
label=ugettext_lazy('SSH Keys'),
|
||||
required=False,
|
||||
widget=forms.Textarea,
|
||||
help_text= \
|
||||
ugettext_lazy('Setting an SSH public key will allow this user to '
|
||||
'securely log in to the system without using a '
|
||||
'password. You may enter multiple keys, one on each '
|
||||
'line. Blank lines and lines starting with # will be '
|
||||
'ignored.'))
|
||||
help_text=ugettext_lazy(
|
||||
'Setting an SSH public key will allow this user to '
|
||||
'securely log in to the system without using a '
|
||||
'password. You may enter multiple keys, one on each '
|
||||
'line. Blank lines and lines starting with # will be '
|
||||
'ignored.'))
|
||||
|
||||
class Meta:
|
||||
"""Metadata to control automatic form building."""
|
||||
|
||||
@ -22,13 +22,13 @@ from django.contrib.messages.views import SuccessMessageMixin
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.views.generic.edit import (CreateView, DeleteView, UpdateView,
|
||||
FormView)
|
||||
from django.views.generic import ListView, CreateView as CV
|
||||
import django.views.generic
|
||||
from django.utils.translation import ugettext as _, ugettext_lazy
|
||||
from plinth import cfg
|
||||
|
||||
from .forms import CreateUserForm, UserChangePasswordForm, UserUpdateForm, State1Form
|
||||
|
||||
from .forms import CreateUserForm, UserChangePasswordForm, UserUpdateForm, \
|
||||
State1Form
|
||||
from plinth import actions
|
||||
from plinth import cfg
|
||||
from plinth.errors import ActionError
|
||||
from plinth.modules.first_boot.middleware import mark_step_done, next_step
|
||||
|
||||
@ -65,7 +65,7 @@ class UserCreate(ContextMixin, SuccessMessageMixin, CreateView):
|
||||
return kwargs
|
||||
|
||||
|
||||
class UserList(ContextMixin, ListView):
|
||||
class UserList(ContextMixin, django.views.generic.ListView):
|
||||
"""View to list users."""
|
||||
model = User
|
||||
template_name = 'users_list.html'
|
||||
@ -168,7 +168,7 @@ class UserChangePassword(ContextMixin, SuccessMessageMixin, FormView):
|
||||
return super(UserChangePassword, self).form_valid(form)
|
||||
|
||||
|
||||
class State1View(CV):
|
||||
class State1View(django.views.generic.CreateView):
|
||||
"""Create user account and log the user in."""
|
||||
template_name = 'firstboot_state1.html'
|
||||
form_class = State1Form
|
||||
@ -178,6 +178,7 @@ class State1View(CV):
|
||||
"""Initialize the view object."""
|
||||
if not cfg.danube_edition:
|
||||
mark_step_done('pagekite_firstboot')
|
||||
|
||||
mark_step_done('users_firstboot')
|
||||
self.success_url = next_step()
|
||||
return super(State1View, self).__init__(*args, **kwargs)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user