Compare commits
13 Commits
d6754bac58
...
a28af6567f
Author | SHA1 | Date |
---|---|---|
Lauréline Guérin | a28af6567f | |
Lauréline Guérin | 2a2641f792 | |
Lauréline Guérin | e3b9b65544 | |
Benjamin Dauvergne | 6835120e65 | |
Benjamin Dauvergne | 00172e0673 | |
Benjamin Dauvergne | 645d6566f1 | |
Benjamin Dauvergne | ea8a633d29 | |
Valentin Deniaud | c04fb9ab39 | |
Valentin Deniaud | c766be2305 | |
Frédéric Péters | 6ed101d94e | |
Paul Marillonnet | 111591a0b0 | |
Paul Marillonnet | 5956ce4036 | |
Emmanuel Cazenave | 92f827d9f6 |
|
@ -172,23 +172,34 @@ class Command(BaseCommand):
|
|||
def create_site(self, klass, base_url, title, slug, template_name, variables):
|
||||
if slug is None:
|
||||
slug = klass.Extra.service_default_slug
|
||||
obj, must_save = klass.objects.get_or_create(
|
||||
slug=slug, defaults={'title': title, 'base_url': base_url, 'template_name': template_name}
|
||||
)
|
||||
|
||||
try:
|
||||
obj = klass.objects.get(slug=slug)
|
||||
must_save = False
|
||||
except klass.DoesNotExist:
|
||||
obj = klass(slug=slug)
|
||||
must_save = True
|
||||
|
||||
for attr in ('title', 'base_url', 'template_name'):
|
||||
if getattr(obj, attr) != locals().get(attr):
|
||||
setattr(obj, attr, locals().get(attr))
|
||||
must_save = True
|
||||
if must_save:
|
||||
try:
|
||||
obj.full_clean(
|
||||
exclude=['last_operational_success_timestamp', 'last_operational_check_timestamp']
|
||||
)
|
||||
except ValidationError as e:
|
||||
raise CommandError(str(e))
|
||||
|
||||
try:
|
||||
obj.full_clean(
|
||||
exclude=[
|
||||
'secret_key',
|
||||
'last_operational_success_timestamp',
|
||||
'last_operational_check_timestamp',
|
||||
]
|
||||
)
|
||||
except ValidationError as e:
|
||||
raise CommandError(str(e))
|
||||
|
||||
if must_save:
|
||||
obj.save()
|
||||
self.must_notify = True
|
||||
|
||||
variables = variables or {}
|
||||
obj_type = ContentType.objects.get_for_model(klass)
|
||||
for variable_name in variables.keys():
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
# Generated by Django 3.2.18 on 2023-03-14 17:32
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('environment', '0028_clean_internal_ips'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='authentic',
|
||||
name='slug',
|
||||
field=models.SlugField(max_length=200, unique=True, verbose_name='Slug'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='bijoe',
|
||||
name='slug',
|
||||
field=models.SlugField(max_length=200, unique=True, verbose_name='Slug'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='chrono',
|
||||
name='slug',
|
||||
field=models.SlugField(max_length=200, unique=True, verbose_name='Slug'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='combo',
|
||||
name='slug',
|
||||
field=models.SlugField(max_length=200, unique=True, verbose_name='Slug'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='fargo',
|
||||
name='slug',
|
||||
field=models.SlugField(max_length=200, unique=True, verbose_name='Slug'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='hobo',
|
||||
name='slug',
|
||||
field=models.SlugField(max_length=200, unique=True, verbose_name='Slug'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='lingo',
|
||||
name='slug',
|
||||
field=models.SlugField(max_length=200, unique=True, verbose_name='Slug'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='passerelle',
|
||||
name='slug',
|
||||
field=models.SlugField(max_length=200, unique=True, verbose_name='Slug'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='wcs',
|
||||
name='slug',
|
||||
field=models.SlugField(max_length=200, unique=True, verbose_name='Slug'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='welco',
|
||||
name='slug',
|
||||
field=models.SlugField(max_length=200, unique=True, verbose_name='Slug'),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='authentic',
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(('secondary', False)),
|
||||
fields=('title',),
|
||||
name='environment_authentic_title_idx',
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='bijoe',
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(('secondary', False)),
|
||||
fields=('title',),
|
||||
name='environment_bijoe_title_idx',
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='chrono',
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(('secondary', False)),
|
||||
fields=('title',),
|
||||
name='environment_chrono_title_idx',
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='combo',
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(('secondary', False)),
|
||||
fields=('title',),
|
||||
name='environment_combo_title_idx',
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='fargo',
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(('secondary', False)),
|
||||
fields=('title',),
|
||||
name='environment_fargo_title_idx',
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='hobo',
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(('local', True)), fields=('local',), name='environment_hobo_local_true_idx'
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='hobo',
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(('secondary', False)), fields=('title',), name='environment_hobo_title_idx'
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='lingo',
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(('secondary', False)),
|
||||
fields=('title',),
|
||||
name='environment_lingo_title_idx',
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='passerelle',
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(('secondary', False)),
|
||||
fields=('title',),
|
||||
name='environment_passerelle_title_idx',
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='wcs',
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(('secondary', False)), fields=('title',), name='environment_wcs_title_idx'
|
||||
),
|
||||
),
|
||||
migrations.AddConstraint(
|
||||
model_name='welco',
|
||||
constraint=models.UniqueConstraint(
|
||||
condition=models.Q(('secondary', False)),
|
||||
fields=('title',),
|
||||
name='environment_welco_title_idx',
|
||||
),
|
||||
),
|
||||
]
|
|
@ -123,9 +123,16 @@ def has_valid_certificate(url):
|
|||
class ServiceBase(models.Model):
|
||||
class Meta:
|
||||
abstract = True
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=['title'],
|
||||
condition=models.Q(secondary=False),
|
||||
name='%(app_label)s_%(class)s_title_idx',
|
||||
),
|
||||
]
|
||||
|
||||
title = models.CharField(_('Title'), max_length=50)
|
||||
slug = models.SlugField(_('Slug'), max_length=200)
|
||||
slug = models.SlugField(_('Slug'), max_length=200, unique=True)
|
||||
base_url = models.CharField(_('Base URL'), max_length=200, validators=[URLValidator()])
|
||||
legacy_urls = JSONField(null=True, default=list, blank=True)
|
||||
secret_key = models.CharField(_('Secret Key'), max_length=60)
|
||||
|
@ -218,6 +225,9 @@ class ServiceBase(models.Model):
|
|||
else:
|
||||
self.secret_key = get_random_string(50, SECRET_CHARS)
|
||||
|
||||
if not self.title and self.slug:
|
||||
self.title = self.slug
|
||||
|
||||
is_new = self.id is None
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
|
@ -332,11 +342,13 @@ class Authentic(ServiceBase):
|
|||
verbose_name = _('Authentic Identity Provider')
|
||||
verbose_name_plural = _('Authentic Identity Providers')
|
||||
ordering = ['title']
|
||||
constraints = ServiceBase.Meta.constraints
|
||||
|
||||
class Extra:
|
||||
service_id = 'authentic'
|
||||
service_label = _('Authentic')
|
||||
service_default_slug = 'idp'
|
||||
constraints = ServiceBase.Meta.constraints
|
||||
|
||||
def get_admin_zones(self):
|
||||
return [
|
||||
|
@ -359,6 +371,7 @@ class Wcs(ServiceBase):
|
|||
verbose_name = _('w.c.s. Web Forms')
|
||||
verbose_name_plural = _('w.c.s. Web Forms')
|
||||
ordering = ['title']
|
||||
constraints = ServiceBase.Meta.constraints
|
||||
|
||||
class Extra:
|
||||
service_id = 'wcs'
|
||||
|
@ -382,6 +395,7 @@ class Passerelle(ServiceBase):
|
|||
verbose_name = _('Passerelle')
|
||||
verbose_name_plural = _('Passerelle')
|
||||
ordering = ['title']
|
||||
constraints = ServiceBase.Meta.constraints
|
||||
|
||||
class Extra:
|
||||
service_id = 'passerelle'
|
||||
|
@ -403,6 +417,7 @@ class Combo(ServiceBase):
|
|||
verbose_name = _('Combo Portal')
|
||||
verbose_name_plural = _('Combo Portals')
|
||||
ordering = ['title']
|
||||
constraints = ServiceBase.Meta.constraints
|
||||
|
||||
class Extra:
|
||||
service_id = 'combo'
|
||||
|
@ -424,6 +439,7 @@ class Fargo(ServiceBase):
|
|||
verbose_name = _('Fargo document box')
|
||||
verbose_name_plural = _('Fargo document box')
|
||||
ordering = ['title']
|
||||
constraints = ServiceBase.Meta.constraints
|
||||
|
||||
class Extra:
|
||||
service_id = 'fargo'
|
||||
|
@ -441,6 +457,7 @@ class Welco(ServiceBase):
|
|||
class Meta:
|
||||
verbose_name = _('Welco Mail Channel')
|
||||
ordering = ['title']
|
||||
constraints = ServiceBase.Meta.constraints
|
||||
|
||||
class Extra:
|
||||
service_id = 'welco'
|
||||
|
@ -462,6 +479,7 @@ class Chrono(ServiceBase):
|
|||
verbose_name = _('Chrono Agendas')
|
||||
verbose_name_plural = _('Chrono Agendas')
|
||||
ordering = ['title']
|
||||
constraints = ServiceBase.Meta.constraints
|
||||
|
||||
class Extra:
|
||||
service_id = 'chrono'
|
||||
|
@ -483,6 +501,13 @@ class Hobo(ServiceBase):
|
|||
verbose_name = _('Hobo Deployment Server')
|
||||
verbose_name_plural = _('Hobo Deployment Servers')
|
||||
ordering = ['title']
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
fields=['local'],
|
||||
condition=models.Q(local=True),
|
||||
name='%(app_label)s_%(class)s_local_true_idx',
|
||||
),
|
||||
] + ServiceBase.Meta.constraints
|
||||
|
||||
class Extra:
|
||||
service_id = 'hobo'
|
||||
|
@ -521,6 +546,7 @@ class BiJoe(ServiceBase):
|
|||
verbose_name = _('Statistics')
|
||||
verbose_name_plural = _('Statistics')
|
||||
ordering = ['title']
|
||||
constraints = ServiceBase.Meta.constraints
|
||||
|
||||
class Extra:
|
||||
service_id = 'bijoe'
|
||||
|
@ -542,6 +568,7 @@ class Lingo(ServiceBase):
|
|||
verbose_name = _('Lingo Billing and Payment')
|
||||
verbose_name_plural = _('Lingo Billing and Payment')
|
||||
ordering = ['title']
|
||||
constraints = ServiceBase.Meta.constraints
|
||||
|
||||
class Extra:
|
||||
service_id = 'lingo'
|
||||
|
|
|
@ -70,13 +70,15 @@ def get_or_create_local_hobo():
|
|||
if not build_absolute_uri:
|
||||
return None
|
||||
|
||||
hobo = Hobo.objects.create(
|
||||
secret_key=get_local_key(build_absolute_uri('/')),
|
||||
title='Hobo',
|
||||
slug='hobo',
|
||||
base_url=build_absolute_uri(reverse('home')),
|
||||
secondary=False,
|
||||
hobo, _ = Hobo.objects.get_or_create(
|
||||
local=True,
|
||||
defaults={
|
||||
'secret_key': get_local_key(build_absolute_uri('/')),
|
||||
'title': 'Hobo',
|
||||
'slug': 'hobo',
|
||||
'base_url': build_absolute_uri(reverse('home')),
|
||||
'secondary': False,
|
||||
},
|
||||
)
|
||||
|
||||
return hobo
|
||||
|
|
|
@ -7,8 +7,8 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: hobo 0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-02-10 11:06+0100\n"
|
||||
"PO-Revision-Date: 2023-02-10 11:07+0100\n"
|
||||
"POT-Creation-Date: 2023-03-01 08:14+0000\n"
|
||||
"PO-Revision-Date: 2023-03-01 09:16+0100\n"
|
||||
"Last-Translator: Frederic Peters <fpeters@entrouvert.com>\n"
|
||||
"Language: French\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -144,6 +144,7 @@ msgstr "Ajouter"
|
|||
#: hobo/matomo/templates/hobo/matomo_enable_auto.html
|
||||
#: hobo/matomo/templates/hobo/matomo_enable_manual.html
|
||||
#: hobo/profile/templates/profile/attributedefinition_form.html
|
||||
#: hobo/profile/templates/profile/edit_full_name_template.html
|
||||
#: hobo/seo/templates/hobo/robots_txt.html
|
||||
#: hobo/theme/templates/hobo/theme_options.html
|
||||
msgid "Cancel"
|
||||
|
@ -340,6 +341,7 @@ msgstr "Débogage"
|
|||
#: hobo/debug/templates/hobo/debug_home.html
|
||||
#: hobo/matomo/templates/hobo/matomo_home.html
|
||||
#: hobo/profile/templates/profile/attributedefinition_form.html
|
||||
#: hobo/profile/templates/profile/edit_full_name_template.html
|
||||
#: hobo/seo/templates/hobo/robots_txt.html
|
||||
#: hobo/seo/templates/hobo/seo_home.html
|
||||
msgid "Save"
|
||||
|
@ -593,6 +595,10 @@ msgstr "Non respect des droits des usagers."
|
|||
msgid "URL must end with a slash."
|
||||
msgstr "L’URL doit comporter un slash final."
|
||||
|
||||
#: hobo/profile/forms.py
|
||||
msgid "User full name template (Django)"
|
||||
msgstr "Gabarit (Django) pour le nom de l’utilisateur"
|
||||
|
||||
#: hobo/profile/models.py
|
||||
msgid ""
|
||||
"Enter valid variable name starting with a letter and consisting of letters, "
|
||||
|
@ -702,6 +708,10 @@ msgstr "Adresse électronique"
|
|||
msgid "User Profile"
|
||||
msgstr "Profil usager"
|
||||
|
||||
#: hobo/profile/templates/profile/attributedefinition_list.html
|
||||
msgid "User full name template"
|
||||
msgstr "Gabarit pour le nom de l’utilisateur"
|
||||
|
||||
#: hobo/profile/templates/profile/attributedefinition_list.html
|
||||
msgid "New attribute"
|
||||
msgstr "Nouvel attribut"
|
||||
|
@ -715,6 +725,10 @@ msgstr ""
|
|||
msgid "options"
|
||||
msgstr "options"
|
||||
|
||||
#: hobo/profile/views.py
|
||||
msgid "User full name template has been updated."
|
||||
msgstr "Le gabarit pour le nom de l’utilisateur a été mis à jour."
|
||||
|
||||
#: hobo/seo/forms.py
|
||||
msgid "Content of robots.txt file"
|
||||
msgstr "Contenu du fichier robots.txt"
|
||||
|
|
|
@ -40,6 +40,7 @@ class MigrateSchemasCommand(SyncCommon):
|
|||
parser.set_defaults(verbosity=0)
|
||||
|
||||
def handle(self, *args, **options):
|
||||
options['skip_checks'] = True
|
||||
super().handle(*args, **options)
|
||||
if self.domain:
|
||||
try:
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
# hobo - portal to configure and deploy applications
|
||||
# Copyright (C) 2015-2023 Entr'ouvert
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
class EditFullNameTemplateForm(forms.Form):
|
||||
user_full_name_template = forms.CharField(
|
||||
label=_('User full name template (Django)'),
|
||||
widget=forms.Textarea,
|
||||
required=False,
|
||||
)
|
|
@ -9,6 +9,7 @@
|
|||
{% block appbar %}
|
||||
<h2>{% trans 'User Profile' %}</h2>
|
||||
<span class="actions">
|
||||
<a rel="popup" href="{% url 'profile-edit-user-full-name-template' %}">{% trans 'User full name template' %}</a>
|
||||
<a rel="popup" href="{% url 'profile-add-attribute' %}">{% trans 'New attribute' %}</a>
|
||||
</span>
|
||||
{% endblock %}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
{% extends "hobo/base.html" %}
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
<div id="profile-full-name-template-form">
|
||||
{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
</div>
|
||||
{% block buttons %}
|
||||
<div class="buttons">
|
||||
<button class="submit-button">{% trans 'Save' %}</button>
|
||||
<a class="cancel" href="{% url 'profile-home' %}">{% trans 'Cancel' %}</a>
|
||||
</div>
|
||||
{% endblock %}
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
|
@ -23,4 +23,9 @@ urlpatterns = [
|
|||
re_path(r'(?P<name>[\w-]+)/options', views.options, name='profile-attribute-options'),
|
||||
path('reorder', views.reorder, name='profile-reorder'),
|
||||
path('add-attribute', views.add_attribute, name='profile-add-attribute'),
|
||||
path(
|
||||
'edit-user-full-name-template',
|
||||
views.edit_user_full_name_template,
|
||||
name='profile-edit-user-full-name-template',
|
||||
),
|
||||
]
|
||||
|
|
|
@ -16,10 +16,13 @@
|
|||
|
||||
from django.shortcuts import redirect
|
||||
from django.urls import reverse, reverse_lazy
|
||||
from django.views.generic import CreateView, ListView, RedirectView, UpdateView
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.views.generic import CreateView, ListView, RedirectView, TemplateView, UpdateView
|
||||
|
||||
from hobo.deploy.signals import notify_agents
|
||||
from hobo.environment.forms import VariablesFormMixin
|
||||
|
||||
from .forms import EditFullNameTemplateForm
|
||||
from .models import AttributeDefinition
|
||||
|
||||
|
||||
|
@ -72,6 +75,16 @@ class OptionsView(UpdateView):
|
|||
options = OptionsView.as_view()
|
||||
|
||||
|
||||
class EditFullNameTemplateView(VariablesFormMixin, TemplateView):
|
||||
template_name = 'profile/edit_full_name_template.html'
|
||||
form_class = EditFullNameTemplateForm
|
||||
variables = ['user_full_name_template']
|
||||
success_message = _('User full name template has been updated.')
|
||||
|
||||
|
||||
edit_user_full_name_template = EditFullNameTemplateView.as_view()
|
||||
|
||||
|
||||
def reorder(request):
|
||||
new_order_list = [int(x) for x in request.GET['new-order'].split(',')]
|
||||
for attribute in AttributeDefinition.objects.all():
|
||||
|
|
|
@ -27,7 +27,7 @@ class SMSForm(forms.Form):
|
|||
label=_('Sender'),
|
||||
max_length=11,
|
||||
validators=[
|
||||
RegexValidator('^[A-Za-z0-9 ]{0,11}$', _('Only alphanumeric characters and spaces are allowed.'))
|
||||
RegexValidator('^[A-Za-z0-9_ ]{0,11}$', _('Only alphanumeric characters and spaces are allowed.'))
|
||||
],
|
||||
help_text=_(
|
||||
'Sender name or phone number. It must neither exceed 11 characters nor contain special characters.'
|
||||
|
|
|
@ -17,7 +17,7 @@ def get_full_name(user):
|
|||
context = {}
|
||||
context['user'] = user
|
||||
template_vars = getattr(settings, 'TEMPLATE_VARS', {})
|
||||
if 'user_full_name_template' in template_vars:
|
||||
if template_vars.get('user_full_name_template'):
|
||||
try:
|
||||
template = engines['django'].from_string(template_vars['user_full_name_template'])
|
||||
return template.render(context)
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
|
||||
import pytest
|
||||
|
||||
from hobo.environment.models import Authentic
|
||||
from hobo.environment.models import Authentic, Variable
|
||||
from hobo.environment.utils import get_variable
|
||||
from hobo.profile import models
|
||||
from hobo.profile.models import AttributeDefinition
|
||||
|
||||
|
@ -78,13 +79,39 @@ def test_add_attribute(logged_app, admin_user, kind):
|
|||
assert models.AttributeDefinition.objects.filter(kind=kind).filter(name='test').count() == 1
|
||||
|
||||
|
||||
def test_edit_user_full_name_template(logged_app, admin_user, settings):
|
||||
app = logged_app
|
||||
value = '{{ user.first_name }}'
|
||||
assert not Variable.objects.filter(name='user_full_name_template')
|
||||
page = app.get('/profile/edit-user-full-name-template', status=200)
|
||||
page.form['user_full_name_template'] = value
|
||||
page.form.submit()
|
||||
assert Variable.objects.get(name='user_full_name_template').value == value
|
||||
|
||||
value = '{{ user.last_name }} etc.'
|
||||
page = app.get('/profile/edit-user-full-name-template', status=200)
|
||||
page.form['user_full_name_template'] = value
|
||||
page.form.submit()
|
||||
assert Variable.objects.get(name='user_full_name_template').value == value
|
||||
|
||||
page = app.get('/profile/edit-user-full-name-template', status=200)
|
||||
page.form['user_full_name_template'] = 'whatever'
|
||||
page.click('Cancel')
|
||||
assert Variable.objects.get(name='user_full_name_template').value == value
|
||||
|
||||
page = app.get('/profile/edit-user-full-name-template', status=200)
|
||||
page.form['user_full_name_template'] = ''
|
||||
page.form.submit()
|
||||
assert Variable.objects.get(name='user_full_name_template').value == ''
|
||||
|
||||
|
||||
def test_attribute_kind_not_restricted_at_model_level(db):
|
||||
assert models.AttributeDefinition.objects.create(label='test', kind='somestring')
|
||||
|
||||
|
||||
def test_profile_home_view(logged_app):
|
||||
resp = logged_app.get('/profile/', status=200)
|
||||
assert [x['href'] for x in resp.html.findAll('a', {'rel': 'popup'})][1:4] == [
|
||||
assert [x['href'] for x in resp.html.findAll('a', {'rel': 'popup'})][2:5] == [
|
||||
'/profile/title/options',
|
||||
'/profile/first_name/options',
|
||||
'/profile/last_name/options',
|
||||
|
@ -98,7 +125,7 @@ def test_reorder_view(logged_app):
|
|||
assert resp.location == '/profile/'
|
||||
assert AttributeDefinition.objects.filter(name='last_name')[0].order == 1
|
||||
resp = resp.follow()
|
||||
assert [x['href'] for x in resp.html.findAll('a', {'rel': 'popup'})][1:4] == [
|
||||
assert [x['href'] for x in resp.html.findAll('a', {'rel': 'popup'})][2:5] == [
|
||||
'/profile/last_name/options',
|
||||
'/profile/first_name/options',
|
||||
'/profile/title/options',
|
||||
|
@ -156,3 +183,18 @@ def test_debug_home(logged_app):
|
|||
page = page.form.submit()
|
||||
assert 'Enter a valid IPv4 or IPv6 address' in page.text
|
||||
assert page.form['debug_ips']._value == 'not_an_IP' # get 'n o t _ a n _ I P'
|
||||
|
||||
|
||||
def test_sms(logged_app):
|
||||
resp = logged_app.get('/sms/')
|
||||
resp.form['sms_sender'] = 'foo'
|
||||
resp.form['sms_url'] = 'https://foo.invalid'
|
||||
resp = resp.form.submit().follow()
|
||||
assert get_variable('sms_sender').value == 'foo'
|
||||
assert get_variable('sms_url').value == 'https://foo.invalid'
|
||||
|
||||
resp.form['sms_sender'] = 'foo_bar'
|
||||
resp.form['sms_url'] = 'https://foo.invalid'
|
||||
resp = resp.form.submit()
|
||||
assert get_variable('sms_sender').value == 'foo_bar'
|
||||
assert get_variable('sms_url').value == 'https://foo.invalid'
|
||||
|
|
|
@ -231,12 +231,18 @@ def test_get_variable_value():
|
|||
|
||||
|
||||
def test_get_tenant_name_and_public_urls():
|
||||
Combo.objects.create(base_url='https://combo.dev.publik.love', template_name='...portal-user...')
|
||||
Combo.objects.create(base_url='https://agent-combo.dev.publik.love', template_name='...portal-agent...')
|
||||
Combo.objects.create(base_url='https://no-template-combo.dev.publik.love')
|
||||
Wcs.objects.create(base_url='https://wcs.dev.publik.love')
|
||||
Fargo.objects.create(base_url='https://fargo.dev.publik.love')
|
||||
Hobo.objects.create(base_url='https://hobo.dev.publik.love')
|
||||
Combo.objects.create(
|
||||
slug='portal', base_url='https://combo.dev.publik.love', template_name='...portal-user...'
|
||||
)
|
||||
Combo.objects.create(
|
||||
slug='portal-agent',
|
||||
base_url='https://agent-combo.dev.publik.love',
|
||||
template_name='...portal-agent...',
|
||||
)
|
||||
Combo.objects.create(slug='portal-no-template', base_url='https://no-template-combo.dev.publik.love')
|
||||
Wcs.objects.create(slug='wcs', base_url='https://wcs.dev.publik.love')
|
||||
Fargo.objects.create(slug='fargo', base_url='https://fargo.dev.publik.love')
|
||||
Hobo.objects.create(slug='hobo', base_url='https://hobo.dev.publik.love')
|
||||
tenant_name, site_urls = get_tenant_name_and_public_urls()
|
||||
assert tenant_name == 'combo.dev.publik.love'
|
||||
assert site_urls == [
|
||||
|
|
|
@ -36,9 +36,15 @@ def test_user_get_full_name_from_template(user):
|
|||
):
|
||||
assert get_full_name(user) == 'Jane bar'
|
||||
|
||||
with override_settings(TEMPLATE_VARS={'user_full_name_template': ''}):
|
||||
assert get_full_name(user) == 'Jane Doe'
|
||||
|
||||
|
||||
def test_user_get_full_name(user):
|
||||
with override_settings(
|
||||
TEMPLATE_VARS={'user_full_name_template': '{{ user.first_name }} {{ user.attributes.foo }}'}
|
||||
):
|
||||
assert user.get_full_name() == 'Jane bar'
|
||||
|
||||
with override_settings(TEMPLATE_VARS={'user_full_name_template': ''}):
|
||||
assert user.get_full_name() == 'Jane Doe'
|
||||
|
|
|
@ -49,6 +49,9 @@ def test_get_full_name_from_template_utils_from_multiple_attrs(db, tenant, setti
|
|||
):
|
||||
assert get_full_name(user) == 'Jane Milly Minnie'
|
||||
|
||||
with override_settings(TEMPLATE_VARS={'user_full_name_template': ''}):
|
||||
assert get_full_name(user) == 'Jane Doe'
|
||||
|
||||
|
||||
def test_get_full_name_from_template_accessor_from_multiple_attrs(db, tenant, settings):
|
||||
with tenant_context(tenant):
|
||||
|
@ -90,3 +93,6 @@ def test_get_full_name_from_template_accessor_from_multiple_attrs(db, tenant, se
|
|||
}
|
||||
):
|
||||
assert user.get_full_name() == 'Jane Milly Minnie'
|
||||
|
||||
with override_settings(TEMPLATE_VARS={'user_full_name_template': ''}):
|
||||
assert user.get_full_name() == 'Jane Doe'
|
||||
|
|
4
tox.ini
4
tox.ini
|
@ -6,7 +6,6 @@
|
|||
min_version = 4
|
||||
toxworkdir = {env:TMPDIR:/tmp}/tox-{env:USER}/hobo/{env:BRANCH_NAME:}
|
||||
envlist =
|
||||
py3-django22-{hobo,authentic,multipublik,multitenant,schemas,passerelle}
|
||||
py3-django32-{hobo,authentic,multipublik,multitenant,schemas,passerelle}
|
||||
code-style
|
||||
|
||||
|
@ -45,9 +44,6 @@ setenv =
|
|||
authentic: TEST_DIRECTORY=tests_authentic/
|
||||
passerelle: TEST_DIRECTORY=tests_passerelle/
|
||||
deps:
|
||||
django22: django>=2.2,<2.3
|
||||
django22: psycopg2-binary<2.9
|
||||
django22: psycopg2<2.9
|
||||
django32: django>=3.2,<3.3
|
||||
django32: psycopg2-binary
|
||||
django32: psycopg
|
||||
|
|
Loading…
Reference in New Issue