1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-19 10:26:17 +00:00

Update T&C

Conflicts:
	seahub/templates/js/sysadmin-templates.html
	seahub/templates/sysadmin/base.html
	seahub/urls.py
	seahub/views/sysadmin.py
This commit is contained in:
zhengxie
2016-07-18 13:04:05 +08:00
parent 41f9a3950c
commit 0f73921205
15 changed files with 286 additions and 57 deletions

View File

@@ -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')})

View File

@@ -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',

View File

@@ -61,6 +61,9 @@
<a href="{{ SITE_ROOT }}sys/invitationadmin/"><span class="sf2-icon-invite"></span>{% trans "Invitations" %}</a>
</li>
{% endif %}
<li class="tab">
<a href="{{ SITE_ROOT }}sys/termsadmin/"><span class="sf2-icon-wiki"></span>{% trans "Terms and Conditions" %}</a>
</li>
</ul>
<% if (cur_tab == 'libraries') { %>
<% if (option == 'all') { %>

View File

@@ -67,6 +67,9 @@
<a href="{{ SITE_ROOT }}sys/invitationadmin/"><span class="sf2-icon-invite"></span>{% trans "Invitations" %}</a>
</li>
{% endif %}
<li class="tab {% block cur_tc %}{% endblock %}">
<a href="{{ SITE_ROOT }}sys/termsadmin/"><span class="sf2-icon-wiki"></span>{% trans "Terms and Conditions" %}</a>
</li>
</ul>
{% endblock %}
</div>

View File

@@ -0,0 +1,151 @@
{% extends "sysadmin/base.html" %}
{% load i18n seahub_tags %}
{% block cur_links %}tab-tc{% endblock %}
{% block right_panel %}
<div class="tabnav ovhd">
<ul class="tabnav-tabs fleft">
<li class="tabnav-tab tabnav-tab-cur">
{% trans "Terms and Conditions" %}
</li>
</ul>
<button id="add-btn" class="fright">{% trans "Add" %}</button>
</div>
{% if object_list %}
<table>
<tr>
<th width="15%">{% trans "Name" %}</th>
<th width="10%">{% trans "Version number" %}</th>
<th width="35%">{% trans "Text" %}</th>
<th width="15%">{% trans "Active date" %}</th>
<th width="15%">{% trans "Created date" %}</th>
<th width="10%">{% trans "Operations" %}</th>
</tr>
{% for tc in object_list %}
<tr>
<td>{{ tc.name }}</td>
<td>{{ tc.version_number }}</td>
<td><a href="#" class="js-text" data-msg="{{ tc.text|linebreaksbr }}">{{ tc.text|truncatechars:50 }}</a></td>
<td>
{% if tc.date_active %}
{{ tc.date_active|translate_seahub_time }}
{% else %}
--
{% endif %}
</td>
<td>{{ tc.date_created|translate_seahub_time }}</td>
<td><a href="#" class="js-update" data-pk="{{ tc.pk}}" data-name="{{ tc.name }}" data-version_number="{{ tc.version_number }}" data-text="{{ tc.text }}">{% trans "Update" %}</a>
<a href="#" class="remove-btn" data-url="{% url "sys_delete_terms" tc.pk %}" data-target="{{ tc.name }}">{% trans "Delete" %}</a>
</td>
</tr>
{% endfor %}
</table>
{% else %}
<p>{% trans "Empty" %}</p>
{% endif %}
<form id="tc-form" action="" method="post" class="hide">{% csrf_token %}
<input type="hidden" name="pk" value="" />
<h3>{% trans "Add Terms and Condistions" %}</h3>
<label for="id_name">{% trans "Name" %}</label><br />
<input type="text" name="name" id="id_name" class="input" /><br />
<label for="id_version_number">{% trans "Version Number" %}</label><br />
<input type="text" name="version_number" id="id_version_number" class="input" /><br />
<label for="id_text">{% trans "Text" %}</label><br />
<textarea type="text" name="text" id="id_text" class="textarea"></textarea><br />
<label for="id_status">{% trans "Status" %}</label><br />
<input type="radio" name="status" value="1" checked>{% trans "Enabled" %}
<input type="radio" name="status" value="0">{% trans "Disabled" %}<br>
<p class="error hide"></p>
<button type="submit" class="submit">{% trans "Submit" %}</button>
</form>
<div id="popup-msg" class="hide"></div>
{% endblock %}
{% block extra_script %}
<script type="text/javascript">
$('#add-btn').click(function() {
$('#tc-form').modal();
$('#simplemodal-container').css({'width':'auto', 'height':'auto'});
});
$('.js-update').click(function() {
var form = $('#tc-form');
form.children('[name="pk"]').val($(this).data('pk'));
form.children('[name="name"]').val($(this).data('name'));
form.children('[name="version_number"]').val($(this).data('version_number'));
form.children('[name="text"]').val($(this).data('text'));
$('#tc-form').modal();
$('#simplemodal-container').css({'width':'auto', 'height':'auto'});
});
$('#tc-form').submit(function(){
var form = $(this),
form_id = form.attr('id'),
submit_btn = form.find('[type="submit"]'),
pk = form.children('[name="pk"]').val();
name = $.trim(form.children('[name="name"]').val()),
version_num = $.trim(form.children('[name="version_number"]').val()),
text = $.trim(form.children('[name="text"]').val()),
status = form.children('[name="status"]:checked').val();
disable(submit_btn);
$.ajax({
url: '{% url 'sys_terms_admin' %}',
type: 'POST',
datatype: 'json',
cache: false,
beforeSend: prepareCSRFToken,
data: {
'name': name,
'version_number': version_num,
'text': text,
'status': status,
'pk': pk
},
success: function(data) {
if (data['success']) {
location.reload(true);
}
},
error: function(jqXHR, textStatus, errorThrown) {
if (jqXHR.responseText) {
apply_form_error(form_id, $.parseJSON(jqXHR.responseText).error);
} else {
apply_form_error(form_id, "{% trans "Failed. Please check the network." %}");
}
}
}).complete(function() {
enable(submit_btn);
});
return false;
});
addConfirmTo($('.remove-btn'), {
'title': "Delete T&C",
'con':"{% trans "Are you sure you want to delete %s ?" %}",
'post': true // post request
});
$('.js-text').click(function() {
$('#popup-msg').html($(this).data('msg'));
$('#popup-msg').modal();
$('#simplemodal-container').css({'height':'auto'});
return false;
});
</script>
{% endblock %}

View File

@@ -0,0 +1,29 @@
{% extends "base.html" %}
{% load i18n %}
{% block main_panel %}
<div class="wide-panel">
<section title="termsandconditions" data-role="content">
<h1>{{ form.initial.terms.name|safe }}</h1>
{{ form.errors }}
<div id="tc-terms-html">
{{ form.initial.terms.text|safe|linebreaksbr }}
</div>
<form action="{% url 'tc_accept_page' %}" method="post" id="tc-terms-form" data-ajax="false">{% csrf_token %}
{{ form.terms }}
{{ form.returnTo }}
<input type="submit" value="{% trans 'Accept' %}" />
<button class="cancel-btn">{% trans 'Cancel' %}</button>
</form>
</section>
</div>
{% endblock %}
{% block extra_script %}
<script type="text/javascript">
$('.cancel-btn').click(function() {
location.href = "{% url 'auth_logout' %}";
return false;
});
</script>
{% endblock %}

View File

@@ -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<email>[^/]+)/$', user_toggle_status, name='user_toggle_status'),
url(r'^useradmin/toggle_role/(?P<email>[^/]+)/$', user_toggle_role, name='user_toggle_role'),
url(r'^useradmin/(?P<email>[^/]+)/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<pk>[^/]+)/$', sys_delete_terms, name='sys_delete_terms'),
url(r'^useradmin/password/reset/(?P<email>[^/]+)/$', 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'),

View File

@@ -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'))

View File

@@ -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()}

View File

@@ -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):

View File

@@ -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')]),
),
]

View File

@@ -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,
),
]

View File

@@ -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

View File

@@ -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<slug>[a-zA-Z0-9_.-]+)/$', TermsView.as_view(), name="tc_view_specific_page"),
# # View Specific Active Terms
# url(r'^view/(?P<slug>[a-zA-Z0-9_.-]+)/$', TermsView.as_view(), name="tc_view_specific_page"),
# View Specific Version of Terms
url(r'^view/(?P<slug>[a-zA-Z0-9_.-]+)/(?P<version>[0-9.]+)/$', TermsView.as_view(), name="tc_view_specific_version_page"),
# # View Specific Version of Terms
# url(r'^view/(?P<slug>[a-zA-Z0-9_.-]+)/(?P<version>[0-9.]+)/$', TermsView.as_view(), name="tc_view_specific_version_page"),
# Print Specific Version of Terms
url(r'^print/(?P<slug>[a-zA-Z0-9_.-]+)/(?P<version>[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<slug>[a-zA-Z0-9_.-]+)/(?P<version>[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<slug>[a-zA-Z0-9_.-]+)/(?P<version>[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<slug>[a-zA-Z0-9_.-]+)/(?P<version>[0-9\.]+)/$', EmailTermsView.as_view(), name="tc_specific_version_page"),
# # Email Specific Terms Version
# url(r'^email/(?P<slug>[a-zA-Z0-9_.-]+)/(?P<version>[0-9\.]+)/$', EmailTermsView.as_view(), name="tc_specific_version_page"),
)

View File

@@ -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']