mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-08-26 12:46:08 +00:00
locale: Adds preferred language for logged in user
- UserProfile model is created, it has one-to-one relationship with User. - Language selection dropdown added to UserCreate and UserUpdate forms. - Adds None to language selection dropdown to explicitly unselect. - LANGUAGE_SESSION_KEY is set to User's preferred language on LogIn activity. - LANGUAGE_SESSION_KEY is deleted on User's LogOut activity. Signed-off-by: Sai Kiran Naragam <saikiran.rguiiit@gmail.com> Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
This commit is contained in:
parent
5cff5629d8
commit
837e0b8384
@ -60,7 +60,7 @@ class LanguageSelectionForm(forms.Form):
|
|||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
supported_languages = []
|
supported_languages = [(None, '-----------')]
|
||||||
for language_code, language_name in settings.LANGUAGES:
|
for language_code, language_name in settings.LANGUAGES:
|
||||||
locale_code = translation.to_locale(language_code)
|
locale_code = translation.to_locale(language_code)
|
||||||
plinth_dir = os.path.dirname(plinth.__file__)
|
plinth_dir = os.path.dirname(plinth.__file__)
|
||||||
@ -70,4 +70,4 @@ class LanguageSelectionForm(forms.Form):
|
|||||||
|
|
||||||
self.fields['language'].choices = supported_languages
|
self.fields['language'].choices = supported_languages
|
||||||
|
|
||||||
language = forms.ChoiceField(label='Language', choices=[])
|
language = forms.ChoiceField(label='Language', choices=[], required=False)
|
||||||
|
|||||||
40
plinth/migrations/0004_userprofile.py
Normal file
40
plinth/migrations/0004_userprofile.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.5 on 2018-01-29 10:21
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
from plinth.models import UserProfile
|
||||||
|
|
||||||
|
|
||||||
|
def insert_users(apps, schema_editor):
|
||||||
|
for user in User.objects.all():
|
||||||
|
UserProfile(user=user).save()
|
||||||
|
|
||||||
|
|
||||||
|
def truncate_user_profile(apps, schema_editor):
|
||||||
|
UserProfile.objects.all().delete()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('plinth', '0003_merge_firstboot_completed_fields'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='UserProfile',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('preferred_language', models.CharField(default=None, max_length=10, null=True)),
|
||||||
|
(
|
||||||
|
'user',
|
||||||
|
models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.RunPython(code=insert_users, reverse_code=truncate_user_profile),
|
||||||
|
|
||||||
|
]
|
||||||
@ -20,6 +20,7 @@ Django models for the main application
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.contrib.auth.models import User
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
|
||||||
@ -43,3 +44,9 @@ class Module(models.Model):
|
|||||||
"""Model to store current setup versions of a module."""
|
"""Model to store current setup versions of a module."""
|
||||||
name = models.TextField(primary_key=True)
|
name = models.TextField(primary_key=True)
|
||||||
setup_version = models.IntegerField()
|
setup_version = models.IntegerField()
|
||||||
|
|
||||||
|
|
||||||
|
class UserProfile(models.Model):
|
||||||
|
"""Model that stores User details that are not related to authentication"""
|
||||||
|
user = models.OneToOneField(User, on_delete=models.CASCADE)
|
||||||
|
preferred_language = models.CharField(max_length=10, null=True, default=None)
|
||||||
|
|||||||
@ -25,6 +25,7 @@ import urllib
|
|||||||
from django.contrib.auth import REDIRECT_FIELD_NAME
|
from django.contrib.auth import REDIRECT_FIELD_NAME
|
||||||
from django.contrib.auth.views import LoginView, LogoutView
|
from django.contrib.auth.views import LoginView, LogoutView
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
|
from django.utils import translation
|
||||||
|
|
||||||
from axes.decorators import axes_form_invalid
|
from axes.decorators import axes_form_invalid
|
||||||
from axes.utils import reset
|
from axes.utils import reset
|
||||||
@ -65,6 +66,7 @@ class SSOLoginView(LoginView):
|
|||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
response = super(SSOLoginView, self).dispatch(request, *args, **kwargs)
|
response = super(SSOLoginView, self).dispatch(request, *args, **kwargs)
|
||||||
if request.user.is_authenticated:
|
if request.user.is_authenticated:
|
||||||
|
request.session[translation.LANGUAGE_SESSION_KEY] = request.user.userprofile.preferred_language
|
||||||
return set_ticket_cookie(request.user, response)
|
return set_ticket_cookie(request.user, response)
|
||||||
else:
|
else:
|
||||||
return response
|
return response
|
||||||
@ -109,6 +111,11 @@ class SSOLogoutView(LogoutView):
|
|||||||
def dispatch(self, request, *args, **kwargs):
|
def dispatch(self, request, *args, **kwargs):
|
||||||
response = super(SSOLogoutView, self).dispatch(request, *args,
|
response = super(SSOLogoutView, self).dispatch(request, *args,
|
||||||
**kwargs)
|
**kwargs)
|
||||||
|
try:
|
||||||
|
del request.session[translation.LANGUAGE_SESSION_KEY]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
response.delete_cookie(SSO_COOKIE_NAME)
|
response.delete_cookie(SSO_COOKIE_NAME)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|||||||
@ -22,14 +22,17 @@ from django.contrib import auth, messages
|
|||||||
from django.contrib.auth.forms import SetPasswordForm, UserCreationForm
|
from django.contrib.auth.forms import SetPasswordForm, UserCreationForm
|
||||||
from django.contrib.auth.models import Group, User
|
from django.contrib.auth.models import Group, User
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
from django.utils import translation
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.utils.translation import ugettext_lazy
|
from django.utils.translation import ugettext_lazy
|
||||||
|
|
||||||
from plinth import actions, module_loader
|
from plinth import actions, module_loader
|
||||||
|
from plinth import forms as plinthForms
|
||||||
from plinth.errors import ActionError
|
from plinth.errors import ActionError
|
||||||
from plinth.modules import first_boot, users
|
from plinth.modules import first_boot, users
|
||||||
from plinth.modules.security import set_restricted_access
|
from plinth.modules.security import set_restricted_access
|
||||||
from plinth.utils import is_user_admin
|
from plinth.utils import is_user_admin
|
||||||
|
from plinth.models import UserProfile
|
||||||
|
|
||||||
|
|
||||||
def get_group_choices():
|
def get_group_choices():
|
||||||
@ -72,7 +75,7 @@ class ValidNewUsernameCheckMixin(object):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class CreateUserForm(ValidNewUsernameCheckMixin, UserCreationForm):
|
class CreateUserForm(ValidNewUsernameCheckMixin, UserCreationForm, plinthForms.LanguageSelectionForm):
|
||||||
"""Custom user create form.
|
"""Custom user create form.
|
||||||
|
|
||||||
Include options to add user to groups.
|
Include options to add user to groups.
|
||||||
@ -89,6 +92,9 @@ class CreateUserForm(ValidNewUsernameCheckMixin, UserCreationForm):
|
|||||||
'log in to the system through SSH and have '
|
'log in to the system through SSH and have '
|
||||||
'administrative privileges (sudo).'))
|
'administrative privileges (sudo).'))
|
||||||
|
|
||||||
|
class Meta(UserCreationForm.Meta):
|
||||||
|
fields = ('username', 'password1', 'password2', 'groups', 'language')
|
||||||
|
|
||||||
def __init__(self, request, *args, **kwargs):
|
def __init__(self, request, *args, **kwargs):
|
||||||
"""Initialize the form with extra request argument."""
|
"""Initialize the form with extra request argument."""
|
||||||
self.request = request
|
self.request = request
|
||||||
@ -98,6 +104,7 @@ class CreateUserForm(ValidNewUsernameCheckMixin, UserCreationForm):
|
|||||||
def save(self, commit=True):
|
def save(self, commit=True):
|
||||||
"""Save the user model and create LDAP user if required."""
|
"""Save the user model and create LDAP user if required."""
|
||||||
user = super(CreateUserForm, self).save(commit)
|
user = super(CreateUserForm, self).save(commit)
|
||||||
|
UserProfile(user=user, preferred_language=self.cleaned_data['language']).save()
|
||||||
|
|
||||||
if commit:
|
if commit:
|
||||||
try:
|
try:
|
||||||
@ -125,7 +132,7 @@ class CreateUserForm(ValidNewUsernameCheckMixin, UserCreationForm):
|
|||||||
return user
|
return user
|
||||||
|
|
||||||
|
|
||||||
class UserUpdateForm(ValidNewUsernameCheckMixin, forms.ModelForm):
|
class UserUpdateForm(ValidNewUsernameCheckMixin, forms.ModelForm, plinthForms.LanguageSelectionForm):
|
||||||
"""When user info is changed, also updates LDAP user."""
|
"""When user info is changed, also updates LDAP user."""
|
||||||
ssh_keys = forms.CharField(
|
ssh_keys = forms.CharField(
|
||||||
label=ugettext_lazy('SSH Keys'),
|
label=ugettext_lazy('SSH Keys'),
|
||||||
@ -138,7 +145,7 @@ class UserUpdateForm(ValidNewUsernameCheckMixin, forms.ModelForm):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
"""Metadata to control automatic form building."""
|
"""Metadata to control automatic form building."""
|
||||||
fields = ('username', 'groups', 'ssh_keys', 'is_active')
|
fields = ('username', 'groups', 'ssh_keys', 'language', 'is_active')
|
||||||
model = User
|
model = User
|
||||||
widgets = {
|
widgets = {
|
||||||
'groups': forms.widgets.CheckboxSelectMultiple(),
|
'groups': forms.widgets.CheckboxSelectMultiple(),
|
||||||
@ -172,7 +179,14 @@ class UserUpdateForm(ValidNewUsernameCheckMixin, forms.ModelForm):
|
|||||||
|
|
||||||
def save(self, commit=True):
|
def save(self, commit=True):
|
||||||
"""Update LDAP user name and groups after saving user model."""
|
"""Update LDAP user name and groups after saving user model."""
|
||||||
user = super(UserUpdateForm, self).save(commit)
|
user = super(UserUpdateForm, self).save(commit=False)
|
||||||
|
user.userprofile.preferred_language = self.cleaned_data['language']
|
||||||
|
user.userprofile.save()
|
||||||
|
user.save()
|
||||||
|
|
||||||
|
# If user is updating their own profile then only translate the pages
|
||||||
|
if self.username == self.request.user.username:
|
||||||
|
self.request.session[translation.LANGUAGE_SESSION_KEY] = user.userprofile.preferred_language
|
||||||
|
|
||||||
if commit:
|
if commit:
|
||||||
output = actions.superuser_run('users',
|
output = actions.superuser_run('users',
|
||||||
@ -259,6 +273,7 @@ class FirstBootForm(ValidNewUsernameCheckMixin, auth.forms.UserCreationForm):
|
|||||||
def save(self, commit=True):
|
def save(self, commit=True):
|
||||||
"""Create and log the user in."""
|
"""Create and log the user in."""
|
||||||
user = super().save(commit=commit)
|
user = super().save(commit=commit)
|
||||||
|
UserProfile(user=user).save()
|
||||||
if commit:
|
if commit:
|
||||||
first_boot.mark_step_done('users_firstboot')
|
first_boot.mark_step_done('users_firstboot')
|
||||||
|
|
||||||
|
|||||||
@ -104,6 +104,8 @@ class UserUpdate(ContextMixin, SuccessMessageMixin, UpdateView):
|
|||||||
ssh_keys = actions.superuser_run(
|
ssh_keys = actions.superuser_run(
|
||||||
'ssh', ['get-keys', '--username', self.object.username])
|
'ssh', ['get-keys', '--username', self.object.username])
|
||||||
initial['ssh_keys'] = ssh_keys.strip()
|
initial['ssh_keys'] = ssh_keys.strip()
|
||||||
|
user_being_edited = User.objects.get(username=self.kwargs['slug'])
|
||||||
|
initial['language'] = user_being_edited.userprofile.preferred_language
|
||||||
except ActionError:
|
except ActionError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@ -82,9 +82,12 @@ class LanguageSelectionView(FormView):
|
|||||||
form = self.form_class(request.POST)
|
form = self.form_class(request.POST)
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
selected_language = form.cleaned_data['language']
|
selected_language = form.cleaned_data['language']
|
||||||
|
if not selected_language:
|
||||||
|
response = HttpResponseRedirect(reverse('language-selection'))
|
||||||
|
response.delete_cookie(settings.LANGUAGE_COOKIE_NAME)
|
||||||
|
return response
|
||||||
|
|
||||||
translation.activate(selected_language)
|
translation.activate(selected_language)
|
||||||
# set selected language in session
|
|
||||||
request.session[translation.LANGUAGE_SESSION_KEY] = selected_language
|
|
||||||
response = HttpResponseRedirect(reverse('language-selection'))
|
response = HttpResponseRedirect(reverse('language-selection'))
|
||||||
# send a cookie for selected language
|
# send a cookie for selected language
|
||||||
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, selected_language)
|
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, selected_language)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user