From 0f73921205032d886e532221e4977efbbba10235 Mon Sep 17 00:00:00 2001 From: zhengxie Date: Mon, 18 Jul 2016 13:04:05 +0800 Subject: [PATCH] Update T&C Conflicts: seahub/templates/js/sysadmin-templates.html seahub/templates/sysadmin/base.html seahub/urls.py seahub/views/sysadmin.py --- seahub/forms.py | 8 + seahub/settings.py | 2 + seahub/templates/js/sysadmin-templates.html | 3 + seahub/templates/sysadmin/base.html | 3 + .../templates/sysadmin/sys_terms_admin.html | 151 ++++++++++++++++++ .../termsandconditions/tc_accept_terms.html | 29 ++++ seahub/urls.py | 5 +- seahub/views/sysadmin.py | 58 ++++++- thirdpart/termsandconditions/forms.py | 2 +- thirdpart/termsandconditions/middleware.py | 4 +- .../migrations/0001_initial.py | 15 +- .../0002_termsandconditions_info.py | 22 --- thirdpart/termsandconditions/models.py | 10 +- thirdpart/termsandconditions/urls.py | 24 +-- thirdpart/termsandconditions/views.py | 7 +- 15 files changed, 286 insertions(+), 57 deletions(-) create mode 100644 seahub/templates/sysadmin/sys_terms_admin.html create mode 100644 seahub/templates/termsandconditions/tc_accept_terms.html delete mode 100644 thirdpart/termsandconditions/migrations/0002_termsandconditions_info.py diff --git a/seahub/forms.py b/seahub/forms.py index 838521e5c9..0787db06d7 100644 --- a/seahub/forms.py +++ b/seahub/forms.py @@ -158,3 +158,11 @@ class BatchAddUserForm(forms.Form): Form for importing users from CSV file. """ file = forms.FileField() + + +class TermsAndConditionsForm(forms.Form): + """Form to save T&C. + """ + name = forms.CharField(error_messages={'required': _('Name is required')}) + version_number = forms.DecimalField(required=True, error_messages={'invalid': _('Please enter a valid number')}) + text = forms.CharField(error_messages={'required': _('Text is required')}) diff --git a/seahub/settings.py b/seahub/settings.py index 9e28a83bfa..9375e7e172 100644 --- a/seahub/settings.py +++ b/seahub/settings.py @@ -117,6 +117,7 @@ MIDDLEWARE_CLASSES = ( 'seahub.base.middleware.InfobarMiddleware', 'seahub.password_session.middleware.CheckPasswordHash', 'seahub.base.middleware.ForcePasswdChangeMiddleware', + 'termsandconditions.middleware.TermsAndConditionsRedirectMiddleware', ) SITE_ROOT_URLCONF = 'seahub.urls' @@ -194,6 +195,7 @@ INSTALLED_APPS = ( 'constance', 'constance.backends.database', 'post_office', + 'termsandconditions', 'seahub.api2', 'seahub.avatar', diff --git a/seahub/templates/js/sysadmin-templates.html b/seahub/templates/js/sysadmin-templates.html index 50d80a9587..8e3fca5948 100644 --- a/seahub/templates/js/sysadmin-templates.html +++ b/seahub/templates/js/sysadmin-templates.html @@ -61,6 +61,9 @@ {% trans "Invitations" %} {% endif %} +
  • + {% trans "Terms and Conditions" %} +
  • <% if (cur_tab == 'libraries') { %> <% if (option == 'all') { %> diff --git a/seahub/templates/sysadmin/base.html b/seahub/templates/sysadmin/base.html index 9f7f51fba7..6488c4ef02 100644 --- a/seahub/templates/sysadmin/base.html +++ b/seahub/templates/sysadmin/base.html @@ -67,6 +67,9 @@ {% trans "Invitations" %} {% endif %} +
  • + {% trans "Terms and Conditions" %} +
  • {% endblock %} diff --git a/seahub/templates/sysadmin/sys_terms_admin.html b/seahub/templates/sysadmin/sys_terms_admin.html new file mode 100644 index 0000000000..fd827f5152 --- /dev/null +++ b/seahub/templates/sysadmin/sys_terms_admin.html @@ -0,0 +1,151 @@ +{% extends "sysadmin/base.html" %} +{% load i18n seahub_tags %} + +{% block cur_links %}tab-tc{% endblock %} + +{% block right_panel %} +
    + + +
    + +{% if object_list %} + + + + + + + + + + {% for tc in object_list %} + + + + + + + + + {% endfor %} +
    {% trans "Name" %}{% trans "Version number" %}{% trans "Text" %}{% trans "Active date" %}{% trans "Created date" %}{% trans "Operations" %}
    {{ tc.name }}{{ tc.version_number }}{{ tc.text|truncatechars:50 }} + {% if tc.date_active %} + {{ tc.date_active|translate_seahub_time }} + {% else %} + -- + {% endif %} + {{ tc.date_created|translate_seahub_time }}{% trans "Update" %} + {% trans "Delete" %} +
    + +{% else %} +

    {% trans "Empty" %}

    +{% endif %} + +
    {% csrf_token %} + + +

    {% trans "Add Terms and Condistions" %}

    +
    +
    + +
    +
    + +
    +
    + +
    + {% trans "Enabled" %} + {% trans "Disabled" %}
    + +

    + +
    + + + +{% endblock %} + +{% block extra_script %} + +{% endblock %} diff --git a/seahub/templates/termsandconditions/tc_accept_terms.html b/seahub/templates/termsandconditions/tc_accept_terms.html new file mode 100644 index 0000000000..96c111703c --- /dev/null +++ b/seahub/templates/termsandconditions/tc_accept_terms.html @@ -0,0 +1,29 @@ +{% extends "base.html" %} +{% load i18n %} + +{% block main_panel %} +
    +
    +

    {{ form.initial.terms.name|safe }}

    + {{ form.errors }} +
    + {{ form.initial.terms.text|safe|linebreaksbr }} +
    +
    {% csrf_token %} + {{ form.terms }} + {{ form.returnTo }} + + +
    +
    +
    +{% endblock %} + +{% block extra_script %} + +{% endblock %} diff --git a/seahub/urls.py b/seahub/urls.py index e36e26694f..be13d5a0c1 100644 --- a/seahub/urls.py +++ b/seahub/urls.py @@ -224,6 +224,7 @@ urlpatterns = patterns( (r'^thumbnail/', include('seahub.thumbnail.urls')), url(r'^inst/', include('seahub.institutions.urls', app_name='institutions', namespace='institutions')), url(r'^invite/', include('seahub.invitations.urls', app_name='invitations', namespace='invitations')), + url(r'^terms/', include('termsandconditions.urls')), ### system admin ### url(r'^sysadmin/$', sysadmin, name='sysadmin'), @@ -279,9 +280,9 @@ urlpatterns = patterns( url(r'^useradmin/toggle_status/(?P[^/]+)/$', user_toggle_status, name='user_toggle_status'), url(r'^useradmin/toggle_role/(?P[^/]+)/$', user_toggle_role, name='user_toggle_role'), url(r'^useradmin/(?P[^/]+)/set_quota/$', user_set_quota, name='user_set_quota'), - + url(r'^sys/termsadmin/$', sys_terms_admin, name='sys_terms_admin'), + url(r'^sys/termsadmin/delete/(?P[^/]+)/$', sys_delete_terms, name='sys_delete_terms'), url(r'^useradmin/password/reset/(?P[^/]+)/$', user_reset, name='user_reset'), - url(r'^useradmin/batchmakeadmin/$', batch_user_make_admin, name='batch_user_make_admin'), url(r'^useradmin/batchadduser/$', batch_add_user, name='batch_add_user'), diff --git a/seahub/views/sysadmin.py b/seahub/views/sysadmin.py index be2b2c38b7..76935d0808 100644 --- a/seahub/views/sysadmin.py +++ b/seahub/views/sysadmin.py @@ -50,8 +50,8 @@ from seahub.utils.user_permissions import (get_basic_user_roles, get_user_role) from seahub.views.ajax import (get_related_users_by_org_repo, get_related_users_by_repo) -from seahub.views import get_system_default_repo_id -from seahub.forms import SetUserQuotaForm, AddUserForm, BatchAddUserForm +from seahub.forms import SetUserQuotaForm, AddUserForm, BatchAddUserForm, \ + TermsAndConditionsForm from seahub.options.models import UserOptions from seahub.profile.models import Profile, DetailedProfile from seahub.signals import repo_deleted @@ -71,6 +71,7 @@ try: except ImportError: MULTI_TENANCY = False from seahub.utils.two_factor_auth import HAS_TWO_FACTOR_AUTH +from termsandconditions.models import TermsAndConditions logger = logging.getLogger(__name__) @@ -2214,3 +2215,56 @@ def sys_invitation_admin(request): 'page_next': page_next, }, context_instance=RequestContext(request)) + +@login_required +@sys_staff_required +def sys_terms_admin(request): + """List Terms and Conditions""" + if request.method == "POST": + content_type = 'application/json; charset=utf-8' + + form = TermsAndConditionsForm(request.POST) + if form.is_valid(): + name = form.cleaned_data['name'] + version_number = form.cleaned_data['version_number'] + text = form.cleaned_data['text'] + enabled = True if request.POST.get('status', '0') == '1' else False + if enabled: + date_active = timezone.now() + else: + date_active = None + pk = request.POST.get('pk', None) + if not pk: # create + t_c = TermsAndConditions.objects.create( + name=name, version_number=version_number, text=text, + date_active=date_active) + else: # update + t_c = TermsAndConditions.objects.get(pk=pk) + t_c.text = text + t_c.version_number = version_number + t_c.name = name + t_c.date_active = date_active + t_c.save() + + return HttpResponse(json.dumps({'success': True}), + content_type=content_type) + else: + return HttpResponse(json.dumps({ + 'error': str(form.errors.values()[0]) + }), status=400, content_type=content_type) + + tc_list = TermsAndConditions.objects.all().order_by('-date_created') + + return render_to_response('sysadmin/sys_terms_admin.html', { + 'object_list': tc_list, + }, context_instance=RequestContext(request)) + +@login_required +@sys_staff_required +@require_POST +def sys_delete_terms(request, pk): + TermsAndConditions.objects.filter(pk=pk).delete() + messages.success(request, _('Success')) + + return HttpResponseRedirect(reverse('sys_terms_admin')) + diff --git a/thirdpart/termsandconditions/forms.py b/thirdpart/termsandconditions/forms.py index 2bb60c264c..bc7f05c07c 100644 --- a/thirdpart/termsandconditions/forms.py +++ b/thirdpart/termsandconditions/forms.py @@ -14,7 +14,7 @@ class UserTermsAndConditionsModelForm(forms.ModelForm): class Meta(object): """Configuration for this Modelform""" model = UserTermsAndConditions - exclude = ('date_accepted', 'ip_address', 'user') + exclude = ('date_accepted', 'ip_address', 'username') widgets = {'terms': forms.HiddenInput()} diff --git a/thirdpart/termsandconditions/middleware.py b/thirdpart/termsandconditions/middleware.py index 9c0ebac80b..12324c0617 100644 --- a/thirdpart/termsandconditions/middleware.py +++ b/thirdpart/termsandconditions/middleware.py @@ -7,8 +7,8 @@ from .pipeline import redirect_to_terms_accept LOGGER = logging.getLogger(name='termsandconditions') ACCEPT_TERMS_PATH = getattr(settings, 'ACCEPT_TERMS_PATH', '/terms/accept/') -TERMS_EXCLUDE_URL_PREFIX_LIST = getattr(settings, 'TERMS_EXCLUDE_URL_PREFIX_LIST', {'/admin', '/terms'}) -TERMS_EXCLUDE_URL_LIST = getattr(settings, 'TERMS_EXCLUDE_URL_LIST', {'/', '/termsrequired/', '/logout/', '/securetoo/'}) +TERMS_EXCLUDE_URL_PREFIX_LIST = getattr(settings, 'TERMS_EXCLUDE_URL_PREFIX_LIST', {'/admin', '/terms', '/media', '/static', '/api2', '/sysadmin', '/sys'}) +TERMS_EXCLUDE_URL_LIST = getattr(settings, 'TERMS_EXCLUDE_URL_LIST', {'/termsrequired/', '/accounts/logout/', '/securetoo/'}) class TermsAndConditionsRedirectMiddleware(object): diff --git a/thirdpart/termsandconditions/migrations/0001_initial.py b/thirdpart/termsandconditions/migrations/0001_initial.py index f3e2bf1344..95a5eac819 100644 --- a/thirdpart/termsandconditions/migrations/0001_initial.py +++ b/thirdpart/termsandconditions/migrations/0001_initial.py @@ -1,14 +1,13 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from django.db import models, migrations -from django.conf import settings +from django.db import migrations, models +import seahub.base.fields class Migration(migrations.Migration): dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ @@ -20,6 +19,7 @@ class Migration(migrations.Migration): ('name', models.TextField(max_length=255)), ('version_number', models.DecimalField(default=1.0, max_digits=6, decimal_places=2)), ('text', models.TextField(null=True, blank=True)), + ('info', models.TextField(help_text=b"Provide users with some info about what's changed and why", null=True, blank=True)), ('date_active', models.DateTimeField(help_text=b'Leave Null To Never Make Active', null=True, blank=True)), ('date_created', models.DateTimeField(auto_now_add=True)), ], @@ -34,10 +34,10 @@ class Migration(migrations.Migration): name='UserTermsAndConditions', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('username', seahub.base.fields.LowerCaseCharField(max_length=255)), ('ip_address', models.GenericIPAddressField(null=True, verbose_name=b'IP Address', blank=True)), ('date_accepted', models.DateTimeField(auto_now_add=True, verbose_name=b'Date Accepted')), ('terms', models.ForeignKey(related_name='userterms', to='termsandconditions.TermsAndConditions')), - ('user', models.ForeignKey(related_name='userterms', to=settings.AUTH_USER_MODEL)), ], options={ 'get_latest_by': 'date_accepted', @@ -45,13 +45,8 @@ class Migration(migrations.Migration): 'verbose_name_plural': 'User Terms and Conditions', }, ), - migrations.AddField( - model_name='termsandconditions', - name='users', - field=models.ManyToManyField(to=settings.AUTH_USER_MODEL, through='termsandconditions.UserTermsAndConditions', blank=True), - ), migrations.AlterUniqueTogether( name='usertermsandconditions', - unique_together=set([('user', 'terms')]), + unique_together=set([('username', 'terms')]), ), ] diff --git a/thirdpart/termsandconditions/migrations/0002_termsandconditions_info.py b/thirdpart/termsandconditions/migrations/0002_termsandconditions_info.py deleted file mode 100644 index 50bacfc1be..0000000000 --- a/thirdpart/termsandconditions/migrations/0002_termsandconditions_info.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('termsandconditions', '0001_initial'), - ] - - operations = [ - migrations.AddField( - model_name='termsandconditions', - name='info', - field=models.TextField( - help_text=b"Provide users with some info about " - b"what's changed and why", null=True, blank=True), - preserve_default=True, - ), - ] diff --git a/thirdpart/termsandconditions/models.py b/thirdpart/termsandconditions/models.py index 2b636bbd83..f4155dcbc4 100644 --- a/thirdpart/termsandconditions/models.py +++ b/thirdpart/termsandconditions/models.py @@ -9,6 +9,8 @@ from django.http import Http404 from django.utils import timezone import logging +from seahub.base.fields import LowerCaseCharField + LOGGER = logging.getLogger(name='termsandconditions') DEFAULT_TERMS_SLUG = getattr(settings, 'DEFAULT_TERMS_SLUG', 'site-terms') @@ -16,7 +18,7 @@ DEFAULT_TERMS_SLUG = getattr(settings, 'DEFAULT_TERMS_SLUG', 'site-terms') class UserTermsAndConditions(models.Model): """Holds mapping between TermsAndConditions and Users""" - user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="userterms") + username = LowerCaseCharField(max_length=255) terms = models.ForeignKey("TermsAndConditions", related_name="userterms") ip_address = models.GenericIPAddressField(null=True, blank=True, verbose_name='IP Address') date_accepted = models.DateTimeField(auto_now_add=True, verbose_name='Date Accepted') @@ -26,7 +28,7 @@ class UserTermsAndConditions(models.Model): get_latest_by = 'date_accepted' verbose_name = 'User Terms and Conditions' verbose_name_plural = 'User Terms and Conditions' - unique_together = ('user', 'terms',) + unique_together = ('username', 'terms',) class TermsAndConditions(models.Model): @@ -34,7 +36,7 @@ class TermsAndConditions(models.Model): Active one for a given slug is: date_active is not Null and is latest not in future""" slug = models.SlugField(default=DEFAULT_TERMS_SLUG) name = models.TextField(max_length=255) - users = models.ManyToManyField(settings.AUTH_USER_MODEL, through=UserTermsAndConditions, blank=True) + # users = models.ManyToManyField(settings.AUTH_USER_MODEL, through=UserTermsAndConditions, blank=True) version_number = models.DecimalField(default=1.0, decimal_places=2, max_digits=6) text = models.TextField(null=True, blank=True) info = models.TextField(null=True, blank=True, help_text="Provide users with some info about what's changed and why") @@ -104,7 +106,7 @@ class TermsAndConditions(models.Model): """Checks to see if a specified user has agreed to the latest of a particular terms and conditions""" try: - UserTermsAndConditions.objects.get(user=user, terms=TermsAndConditions.get_active(slug)) + UserTermsAndConditions.objects.get(username=user.username, terms=TermsAndConditions.get_active(slug)) return True except UserTermsAndConditions.MultipleObjectsReturned: # pragma: nocover return True diff --git a/thirdpart/termsandconditions/urls.py b/thirdpart/termsandconditions/urls.py index ca2ccc7654..6b640f629a 100644 --- a/thirdpart/termsandconditions/urls.py +++ b/thirdpart/termsandconditions/urls.py @@ -13,17 +13,17 @@ from .models import DEFAULT_TERMS_SLUG admin.autodiscover() urlpatterns = ( - # View Default Terms - url(r'^$', TermsView.as_view(), {"slug": DEFAULT_TERMS_SLUG}, name="tc_view_page"), + # # View Default Terms + # url(r'^$', TermsView.as_view(), {"slug": DEFAULT_TERMS_SLUG}, name="tc_view_page"), - # View Specific Active Terms - url(r'^view/(?P[a-zA-Z0-9_.-]+)/$', TermsView.as_view(), name="tc_view_specific_page"), + # # View Specific Active Terms + # url(r'^view/(?P[a-zA-Z0-9_.-]+)/$', TermsView.as_view(), name="tc_view_specific_page"), - # View Specific Version of Terms - url(r'^view/(?P[a-zA-Z0-9_.-]+)/(?P[0-9.]+)/$', TermsView.as_view(), name="tc_view_specific_version_page"), + # # View Specific Version of Terms + # url(r'^view/(?P[a-zA-Z0-9_.-]+)/(?P[0-9.]+)/$', TermsView.as_view(), name="tc_view_specific_version_page"), - # Print Specific Version of Terms - url(r'^print/(?P[a-zA-Z0-9_.-]+)/(?P[0-9.]+)/$', TermsView.as_view(template_name="termsandconditions/tc_print_terms.html"), name="tc_print_page"), + # # Print Specific Version of Terms + # url(r'^print/(?P[a-zA-Z0-9_.-]+)/(?P[0-9.]+)/$', TermsView.as_view(template_name="termsandconditions/tc_print_terms.html"), name="tc_print_page"), # Accept Terms url(r'^accept/$', AcceptTermsView.as_view(), name="tc_accept_page"), @@ -34,10 +34,10 @@ urlpatterns = ( # Accept Specific Terms Version url(r'^accept/(?P[a-zA-Z0-9_.-]+)/(?P[0-9\.]+)/$', AcceptTermsView.as_view(), name="tc_accept_specific_version_page"), - # Email Terms - url(r'^email/$', EmailTermsView.as_view(), name="tc_email_page"), + # # Email Terms + # url(r'^email/$', EmailTermsView.as_view(), name="tc_email_page"), - # Email Specific Terms Version - url(r'^email/(?P[a-zA-Z0-9_.-]+)/(?P[0-9\.]+)/$', EmailTermsView.as_view(), name="tc_specific_version_page"), + # # Email Specific Terms Version + # url(r'^email/(?P[a-zA-Z0-9_.-]+)/(?P[0-9\.]+)/$', EmailTermsView.as_view(), name="tc_specific_version_page"), ) diff --git a/thirdpart/termsandconditions/views.py b/thirdpart/termsandconditions/views.py index ecb5d614fb..f3728fd8d2 100644 --- a/thirdpart/termsandconditions/views.py +++ b/thirdpart/termsandconditions/views.py @@ -2,7 +2,7 @@ # pylint: disable=E1120,R0901,R0904 -from django.contrib.auth.models import User +# from django.contrib.auth.models import User from .forms import UserTermsAndConditionsModelForm, EmailTermsForm from .models import TermsAndConditions, UserTermsAndConditions, DEFAULT_TERMS_SLUG from django.conf import settings @@ -68,13 +68,16 @@ class AcceptTermsView(CreateView): def form_valid(self, form): """Override of CreateView method, assigns default values based on user situation""" if self.request.user.is_authenticated(): - form.instance.user = self.request.user + form.instance.username = self.request.user.username else: #Get user out of saved pipeline from django-socialauth + # no support for social auth right now. + assert False, 'TODO' if self.request.session.has_key('partial_pipeline'): user_pk = self.request.session['partial_pipeline']['kwargs']['user']['pk'] form.instance.user = User.objects.get(id=user_pk) else: return HttpResponseRedirect('/') + store_ip_address = getattr(settings, 'TERMS_STORE_IP_ADDRESS', True) if store_ip_address: form.instance.ip_address = self.request.META['REMOTE_ADDR']