Commit 2cecd129 authored by Michal Čihař's avatar Michal Čihař

Added support for configurable automatic group assignments

Fixes #852
Signed-off-by: default avatarMichal Čihař <michal@cihar.com>
parent b437d180
......@@ -119,6 +119,19 @@ user management on project page as described in :ref:`manage-acl`.
`Managing users in the Django admin <https://docs.djangoproject.com/en/stable/topics/auth/default/#auth-admin>`_
.. _autogroup:
Automatic group assignments
---------------------------
.. versionadded:: 2.5
You can configure Weblate to automatically add users to groups based on their
email. This automatic assignment happens only at time of account creation.
This can be configured in the Django admin interface (in the
:guilabel:`Accounts` section).
Managing users and groups
-------------------------
......
......@@ -45,6 +45,7 @@ Released on ? 2015.
* Added XLIFF export for dictionary.
* Added XLIFF and Gettext PO export for all translations.
* Documentation improvements.
* Added support for configurable automatic group assignments.
weblate 2.4
-----------
......
......@@ -22,7 +22,7 @@ from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from weblate.accounts.models import Profile, VerifiedEmail
from weblate.accounts.models import Profile, VerifiedEmail, AutoGroup
class ProfileAdmin(admin.ModelAdmin):
......@@ -47,6 +47,12 @@ class VerifiedEmailAdmin(admin.ModelAdmin):
admin.site.register(VerifiedEmail, VerifiedEmailAdmin)
class AutoGroupAdmin(admin.ModelAdmin):
list_display = ('group', 'match')
admin.site.register(AutoGroup, AutoGroupAdmin)
class WeblateUserAdmin(UserAdmin):
'''
Custom UserAdmin to add listing of group membership and whether user is
......
# -*- coding: utf-8 -*-
# Generated by Django 1.9.2 on 2016-03-04 14:18
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import weblate.trans.fields
class Migration(migrations.Migration):
dependencies = [
('auth', '0007_alter_validators_add_error_messages'),
('accounts', '0014_auto_20160302_1025'),
]
operations = [
migrations.CreateModel(
name='AutoGroup',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('match', weblate.trans.fields.RegexField(default='^.*$', help_text='Regular expression which is used to match user email.', max_length=200, verbose_name='Email regular expression')),
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='auth.Group', verbose_name='Group to assign')),
],
options={
'ordering': ('group__name',),
'verbose_name': 'Automatic group assignment',
'verbose_name_plural': 'Automatic group assignments',
},
),
migrations.AlterField(
model_name='profile',
name='subscriptions',
field=models.ManyToManyField(blank=True, help_text='You can receive notifications for subscribed projects and they are shown on dashboard by default.', to='trans.Project', verbose_name='Subscribed projects'),
),
]
......@@ -20,6 +20,7 @@
from __future__ import unicode_literals
import os
import re
import sys
import binascii
from smtplib import SMTPException
......@@ -41,6 +42,7 @@ from social.apps.django_app.default.models import UserSocialAuth
from weblate.lang.models import Language
from weblate.trans.site import get_site_url, get_site_domain
from weblate.trans.fields import RegexField
from weblate.accounts.avatar import get_user_display
from weblate.trans.util import report_error
from weblate.trans.signals import user_pre_delete
......@@ -798,6 +800,30 @@ class Profile(models.Model):
return self.user.first_name
@python_2_unicode_compatible
class AutoGroup(models.Model):
match = RegexField(
verbose_name=_('Email regular expression'),
max_length=200,
default='^.*$',
help_text=_(
'Regular expression which is used to match user email.'
),
)
group = models.ForeignKey(
Group,
verbose_name=_('Group to assign'),
)
class Meta(object):
verbose_name = _('Automatic group assignment')
verbose_name_plural = _('Automatic group assignments')
ordering = ('group__name', )
def __str__(self):
return 'Automatic rule for {0}'.format(self.group)
def set_lang(request, profile):
"""
Sets session language based on user preferences.
......@@ -876,6 +902,9 @@ def create_groups(update):
Permission.objects.get(codename='use_mt'),
)
if not AutoGroup.objects.filter(group=group).exists():
AutoGroup.objects.create(group=group, match='^.*$')
owner_permissions = (
Permission.objects.get(codename='author_translation'),
Permission.objects.get(codename='upload_translation'),
......@@ -999,10 +1028,8 @@ def create_profile_callback(sender, instance, created=False, **kwargs):
'''
Automatically adds user to Users group.
'''
if created:
# Add user to Users group if it exists
try:
group = Group.objects.get(name='Users')
instance.groups.add(group)
except Group.DoesNotExist:
pass
if created and instance.email:
# Add user to automatic groups
for auto in AutoGroup.objects.all():
if re.match(auto.match, instance.email):
instance.groups.add(auto.group)
# -*- coding: utf-8 -*-
#
# Copyright © 2012 - 2016 Michal Čihař <michal@cihar.com>
#
# This file is part of Weblate <https://weblate.org/>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
"""
Tests for user models.
"""
from django.contrib.auth.models import User, Group
from django.test import TestCase
from weblate.accounts.models import AutoGroup
class AutoGroupTest(TestCase):
def create_user(self):
return User.objects.create_user('test1', 'noreply@weblate.org', 'pass')
def test_default(self):
user = self.create_user()
self.assertEquals(user.groups.count(), 1)
def test_none(self):
AutoGroup.objects.all().delete()
user = self.create_user()
self.assertEquals(user.groups.count(), 0)
def test_matching(self):
AutoGroup.objects.create(
match='^.*@weblate.org',
group=Group.objects.get(name='Guests')
)
user = self.create_user()
self.assertEquals(user.groups.count(), 2)
def test_nonmatching(self):
AutoGroup.objects.create(
match='^.*@example.net',
group=Group.objects.get(name='Guests')
)
user = self.create_user()
self.assertEquals(user.groups.count(), 1)
{% extends "admin/change_form.html" %}
{% load i18n %}
{% load translations %}
{% block form_top %}
{% if opts.model_name == 'autogroup' %}
{% doc_url 'admin/access' 'autogroup' as url %}
<p>{% blocktrans %}Required fields are marked as bold, you can find more information in the <a href="{{ url }}">documentation</a>.{% endblocktrans %}</p>
{% endif %}
{% endblock %}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment