mirror of
https://github.com/QingdaoU/Spirit.git
synced 2025-01-01 09:31:48 +00:00
user profile
This commit is contained in:
parent
1074898854
commit
fba524786e
16
README.md
16
README.md
@ -9,27 +9,13 @@ To see it in action, please visit [The Spirit Project](http://spirit-project.com
|
||||
Spirit requires the following software to be installed:
|
||||
|
||||
* Python 2.7, 3.3 or 3.4 (recommended)
|
||||
* Django 1.7
|
||||
* Django 1.8
|
||||
* PostgreSQL or MySQL or Oracle Database
|
||||
|
||||
## Dependencies
|
||||
|
||||
Check out the [requirements](https://github.com/nitely/Spirit/blob/master/requirements.txt) provided.
|
||||
|
||||
## Integration
|
||||
|
||||
Spirit can be integrated with any other Django application without much of a hassle.
|
||||
|
||||
The only thing to notice is that Spirit uses its own *AUTH_USER_MODEL*.
|
||||
|
||||
If you want to roll your own user app, your user model must inherit from `spirit.models.user.AbstractForumUser`.
|
||||
|
||||
If you want to extend the Spirit user model (adding new fields or methods),
|
||||
your model must inherit from `spirit.models.user.AbstractUser`.
|
||||
|
||||
If you just want to integrate Spirit's user profile to your *existing* project
|
||||
and you are using the default Django's user model, check out the [Spirit-User-Profile](https://github.com/nitely/Spirit-User-Profile) app.
|
||||
|
||||
## Installing (Advanced)
|
||||
|
||||
Check out the [example](https://github.com/nitely/Spirit/tree/master/example) provided.
|
||||
|
@ -10,17 +10,24 @@ from django.contrib.auth import get_user_model
|
||||
|
||||
from spirit.models.category import Category
|
||||
from spirit.models.comment_flag import CommentFlag
|
||||
from spirit.models.user import UserProfile
|
||||
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class UserEditForm(forms.ModelForm):
|
||||
class UserForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ("username", "email", "location",
|
||||
"timezone", "is_administrator", "is_moderator", "is_active")
|
||||
fields = ("username", "email", "is_active")
|
||||
|
||||
|
||||
class UserProfileForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = UserProfile
|
||||
fields = ("location", "timezone", "is_administrator", "is_moderator")
|
||||
|
||||
|
||||
class CategoryForm(forms.ModelForm):
|
||||
|
@ -27,7 +27,7 @@ class TopicForm(forms.ModelForm):
|
||||
label=_("Category"),
|
||||
empty_label=_("Chose a category"))
|
||||
|
||||
if self.instance.pk and not user.is_moderator:
|
||||
if self.instance.pk and not user.st.is_moderator:
|
||||
del self.fields['category']
|
||||
|
||||
def save(self, commit=True):
|
||||
|
@ -9,6 +9,8 @@ from django.contrib.auth import get_user_model
|
||||
from django.utils import timezone
|
||||
from django.template import defaultfilters
|
||||
|
||||
from ..models.user import UserProfile
|
||||
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
@ -22,7 +24,7 @@ class RegistrationForm(UserCreationForm):
|
||||
fields = ("username", "email")
|
||||
|
||||
def clean_honeypot(self):
|
||||
"""Check that nothing's been entered into the honeypot."""
|
||||
"""Check that nothing has been entered into the honeypot."""
|
||||
value = self.cleaned_data["honeypot"]
|
||||
|
||||
if value:
|
||||
@ -41,16 +43,25 @@ class RegistrationForm(UserCreationForm):
|
||||
|
||||
raise forms.ValidationError(_("The username is taken."))
|
||||
|
||||
# TODO: check email is unique
|
||||
|
||||
def save(self, commit=True):
|
||||
self.instance.is_active = False
|
||||
return super(RegistrationForm, self).save(commit)
|
||||
|
||||
|
||||
class UserProfileForm(forms.ModelForm):
|
||||
class UserForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ("first_name", "last_name", "location", "timezone")
|
||||
fields = ("first_name", "last_name")
|
||||
|
||||
|
||||
class UserProfileForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = UserProfile
|
||||
fields = ("location", "timezone")
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(UserProfileForm, self).__init__(*args, **kwargs)
|
||||
@ -108,7 +119,7 @@ class ResendActivationForm(forms.Form):
|
||||
except User.DoesNotExist:
|
||||
raise forms.ValidationError(_("The provided email does not exists."))
|
||||
|
||||
if self.user.is_verified:
|
||||
if self.user.st.is_verified:
|
||||
raise forms.ValidationError(_("This account is verified, try logging-in."))
|
||||
|
||||
return email
|
||||
|
@ -48,7 +48,7 @@ class CommentQuerySet(models.QuerySet):
|
||||
return self.unremoved()._access(user=user)
|
||||
|
||||
def for_update_or_404(self, pk, user):
|
||||
if user.is_moderator:
|
||||
if user.st.is_moderator:
|
||||
return get_object_or_404(self._access(user=user), pk=pk)
|
||||
else:
|
||||
return get_object_or_404(self.for_access(user), user=user, pk=pk)
|
||||
|
@ -52,7 +52,7 @@ class TopicQuerySet(models.QuerySet):
|
||||
return self.prefetch_related(prefetch)
|
||||
|
||||
def get_public_or_404(self, pk, user):
|
||||
if user.is_authenticated() and user.is_moderator:
|
||||
if user.is_authenticated() and user.st.is_moderator:
|
||||
return get_object_or_404(self.public()
|
||||
.select_related('category__parent'),
|
||||
pk=pk)
|
||||
@ -62,7 +62,7 @@ class TopicQuerySet(models.QuerySet):
|
||||
pk=pk)
|
||||
|
||||
def for_update_or_404(self, pk, user):
|
||||
if user.is_moderator:
|
||||
if user.st.is_moderator:
|
||||
return get_object_or_404(self.public(), pk=pk)
|
||||
else:
|
||||
return get_object_or_404(self.visible().opened(), pk=pk, user=user)
|
||||
|
@ -10,6 +10,8 @@ from django.contrib.auth import logout
|
||||
from django.core.urlresolvers import resolve
|
||||
from django.contrib.auth.views import redirect_to_login
|
||||
|
||||
from .models.user import UserProfile
|
||||
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
@ -25,7 +27,7 @@ class TimezoneMiddleware(object):
|
||||
|
||||
def process_request(self, request):
|
||||
if request.user.is_authenticated():
|
||||
timezone.activate(request.user.timezone)
|
||||
timezone.activate(request.user.st.timezone)
|
||||
else:
|
||||
timezone.deactivate()
|
||||
|
||||
@ -38,10 +40,10 @@ class LastIPMiddleware(object):
|
||||
|
||||
last_ip = request.META['REMOTE_ADDR'].strip()
|
||||
|
||||
if request.user.last_ip == last_ip:
|
||||
if request.user.st.last_ip == last_ip:
|
||||
return
|
||||
|
||||
User.objects.filter(pk=request.user.pk)\
|
||||
UserProfile.objects.filter(user__pk=request.user.pk)\
|
||||
.update(last_ip=last_ip)
|
||||
|
||||
|
||||
@ -52,12 +54,12 @@ class LastSeenMiddleware(object):
|
||||
return
|
||||
|
||||
threshold = settings.ST_USER_LAST_SEEN_THRESHOLD_MINUTES * 60
|
||||
delta = timezone.now() - request.user.last_seen
|
||||
delta = timezone.now() - request.user.st.last_seen
|
||||
|
||||
if delta.seconds < threshold:
|
||||
return
|
||||
|
||||
User.objects.filter(pk=request.user.pk)\
|
||||
UserProfile.objects.filter(user__pk=request.user.pk)\
|
||||
.update(last_seen=timezone.now())
|
||||
|
||||
|
||||
|
@ -7,7 +7,9 @@ from django.conf import settings
|
||||
|
||||
def verify_active_users(apps, schema_editor):
|
||||
User = apps.get_model(settings.AUTH_USER_MODEL)
|
||||
User.objects.filter(is_active=True).update(is_verified=True)
|
||||
|
||||
if hasattr(User, 'is_verified'):
|
||||
User.objects.filter(is_active=True).update(is_verified=True)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
39
spirit/migrations/0007_userprofile.py
Normal file
39
spirit/migrations/0007_userprofile.py
Normal file
@ -0,0 +1,39 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
import spirit.utils.models
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('spirit', '0006_auto_20150327_0204'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='UserProfile',
|
||||
fields=[
|
||||
('id', models.AutoField(primary_key=True, serialize=False, verbose_name='ID', auto_created=True)),
|
||||
('slug', spirit.utils.models.AutoSlugField(db_index=False, blank=True, populate_from='user.username')),
|
||||
('location', models.CharField(blank=True, verbose_name='location', max_length=75)),
|
||||
('last_seen', models.DateTimeField(auto_now=True, verbose_name='last seen')),
|
||||
('last_ip', models.GenericIPAddressField(blank=True, verbose_name='last ip', null=True)),
|
||||
('timezone', models.CharField(max_length=32, verbose_name='time zone', choices=[('Etc/GMT+12', '(GMT -12:00) Eniwetok, Kwajalein'), ('Etc/GMT+11', '(GMT -11:00) Midway Island, Samoa'), ('Etc/GMT+10', '(GMT -10:00) Hawaii'), ('Pacific/Marquesas', '(GMT -9:30) Marquesas Islands'), ('Etc/GMT+9', '(GMT -9:00) Alaska'), ('Etc/GMT+8', '(GMT -8:00) Pacific Time (US & Canada)'), ('Etc/GMT+7', '(GMT -7:00) Mountain Time (US & Canada)'), ('Etc/GMT+6', '(GMT -6:00) Central Time (US & Canada), Mexico City'), ('Etc/GMT+5', '(GMT -5:00) Eastern Time (US & Canada), Bogota, Lima'), ('America/Caracas', '(GMT -4:30) Venezuela'), ('Etc/GMT+4', '(GMT -4:00) Atlantic Time (Canada), Caracas, La Paz'), ('Etc/GMT+3', '(GMT -3:00) Brazil, Buenos Aires, Georgetown'), ('Etc/GMT+2', '(GMT -2:00) Mid-Atlantic'), ('Etc/GMT+1', '(GMT -1:00) Azores, Cape Verde Islands'), ('UTC', '(GMT) Western Europe Time, London, Lisbon, Casablanca'), ('Etc/GMT-1', '(GMT +1:00) Brussels, Copenhagen, Madrid, Paris'), ('Etc/GMT-2', '(GMT +2:00) Kaliningrad, South Africa'), ('Etc/GMT-3', '(GMT +3:00) Baghdad, Riyadh, Moscow, St. Petersburg'), ('Etc/GMT-4', '(GMT +4:00) Abu Dhabi, Muscat, Baku, Tbilisi'), ('Asia/Kabul', '(GMT +4:30) Afghanistan'), ('Etc/GMT-5', '(GMT +5:00) Ekaterinburg, Islamabad, Karachi, Tashkent'), ('Asia/Kolkata', '(GMT +5:30) India, Sri Lanka'), ('Asia/Kathmandu', '(GMT +5:45) Nepal'), ('Etc/GMT-6', '(GMT +6:00) Almaty, Dhaka, Colombo'), ('Indian/Cocos', '(GMT +6:30) Cocos Islands, Myanmar'), ('Etc/GMT-7', '(GMT +7:00) Bangkok, Hanoi, Jakarta'), ('Etc/GMT-8', '(GMT +8:00) Beijing, Perth, Singapore, Hong Kong'), ('Australia/Eucla', '(GMT +8:45) Australia (Eucla)'), ('Etc/GMT-9', '(GMT +9:00) Tokyo, Seoul, Osaka, Sapporo, Yakutsk'), ('Australia/North', '(GMT +9:30) Australia (Northern Territory)'), ('Etc/GMT-10', '(GMT +10:00) Eastern Australia, Guam, Vladivostok'), ('Etc/GMT-11', '(GMT +11:00) Magadan, Solomon Islands, New Caledonia'), ('Pacific/Norfolk', '(GMT +11:30) Norfolk Island'), ('Etc/GMT-12', '(GMT +12:00) Auckland, Wellington, Fiji, Kamchatka')], default='UTC')),
|
||||
('is_administrator', models.BooleanField(verbose_name='administrator status', default=False)),
|
||||
('is_moderator', models.BooleanField(verbose_name='moderator status', default=False)),
|
||||
('is_verified', models.BooleanField(verbose_name='verified', help_text='Designates whether the user has verified his account by email or by other means. Un-select this to let the user activate his account.', default=False)),
|
||||
('topic_count', models.PositiveIntegerField(verbose_name='topic count', default=0)),
|
||||
('comment_count', models.PositiveIntegerField(verbose_name='comment count', default=0)),
|
||||
('user', models.OneToOneField(to=settings.AUTH_USER_MODEL, verbose_name='profile', related_name='st')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'forum profile',
|
||||
'verbose_name_plural': 'forum profiles',
|
||||
},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
]
|
@ -11,11 +11,49 @@ from django.core.mail import send_mail
|
||||
from django.core import validators
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils import timezone
|
||||
from django.conf import settings
|
||||
|
||||
from spirit.utils.timezone import TIMEZONE_CHOICES
|
||||
from spirit.utils.models import AutoSlugField
|
||||
|
||||
|
||||
class UserProfile(models.Model):
|
||||
user = models.OneToOneField(settings.AUTH_USER_MODEL, verbose_name=_("profile"), related_name='st')
|
||||
|
||||
slug = AutoSlugField(populate_from="user.username", db_index=False, blank=True)
|
||||
location = models.CharField(_("location"), max_length=75, blank=True)
|
||||
last_seen = models.DateTimeField(_("last seen"), auto_now=True)
|
||||
last_ip = models.GenericIPAddressField(_("last ip"), blank=True, null=True)
|
||||
timezone = models.CharField(_("time zone"), max_length=32, choices=TIMEZONE_CHOICES, default='UTC')
|
||||
is_administrator = models.BooleanField(_('administrator status'), default=False)
|
||||
is_moderator = models.BooleanField(_('moderator status'), default=False)
|
||||
is_verified = models.BooleanField(_('verified'), default=False,
|
||||
help_text=_('Designates whether the user has verified his '
|
||||
'account by email or by other means. Un-select this '
|
||||
'to let the user activate his account.'))
|
||||
|
||||
topic_count = models.PositiveIntegerField(_("topic count"), default=0)
|
||||
comment_count = models.PositiveIntegerField(_("comment count"), default=0)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("forum profile")
|
||||
verbose_name_plural = _("forum profiles")
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.user.is_superuser:
|
||||
self.is_administrator = True
|
||||
|
||||
if self.is_administrator:
|
||||
self.is_moderator = True
|
||||
|
||||
super(UserProfile, self).save(*args, **kwargs)
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('spirit:profile-detail', kwargs={'pk': self.pk,
|
||||
'slug': self.slug})
|
||||
|
||||
|
||||
|
||||
class AbstractForumUser(models.Model):
|
||||
slug = AutoSlugField(populate_from="username", db_index=False, blank=True)
|
||||
location = models.CharField(_("location"), max_length=75, blank=True)
|
||||
@ -46,12 +84,6 @@ class AbstractForumUser(models.Model):
|
||||
|
||||
|
||||
class AbstractUser(AbstractBaseUser, PermissionsMixin, AbstractForumUser):
|
||||
# almost verbatim copy from the auth user model
|
||||
# adds email(unique=True, blank=False, max_length=254)
|
||||
|
||||
# TODO: Django 1.8 sets email to max_length=254, so there is no point in keeping this,
|
||||
# uniqueness can be checked at app level, although it's better to have a db index (for login)
|
||||
# this should be change to the good old OneToOneField.
|
||||
username = models.CharField(_("username"), max_length=30, unique=True, db_index=True,
|
||||
help_text=_('Required. 30 characters or fewer. Letters, numbers and '
|
||||
'@/./+/-/_ characters'),
|
||||
|
@ -55,8 +55,6 @@ CACHES = {
|
||||
},
|
||||
}
|
||||
|
||||
AUTH_USER_MODEL = 'spirit.User'
|
||||
|
||||
AUTHENTICATION_BACKENDS = (
|
||||
'django.contrib.auth.backends.ModelBackend',
|
||||
'spirit.backends.user.EmailAuthBackend',
|
||||
|
@ -7,3 +7,4 @@ from . import topic
|
||||
from . import topic_notification
|
||||
from . import topic_poll
|
||||
from . import topic_unread
|
||||
from . import user
|
21
spirit/signals/handlers/user.py
Normal file
21
spirit/signals/handlers/user.py
Normal file
@ -0,0 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db.models.signals import post_save
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
from ...models.user import UserProfile
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
def update_or_create_user_profile(sender, instance, created, **kwargs):
|
||||
user = instance
|
||||
|
||||
if created:
|
||||
UserProfile.objects.create(user=user)
|
||||
else:
|
||||
user.st.save()
|
||||
|
||||
post_save.connect(update_or_create_user_profile, sender=User, dispatch_uid=__name__)
|
@ -36,7 +36,7 @@
|
||||
<script src="{% static "spirit/scripts/notification.js" %}"></script>
|
||||
{% endif %}
|
||||
|
||||
{% if user.is_moderator %}
|
||||
{% if user.st.is_moderator %}
|
||||
<script src="{% static "spirit/scripts/move_comments.js" %}"></script>
|
||||
{% endif %}
|
||||
|
||||
|
@ -17,12 +17,12 @@
|
||||
<div class="header-tab-content js-tab-content js-user-content">
|
||||
<nav class="header-nav">
|
||||
<ul class="menu">
|
||||
<li><a class="menu-link" href="{% url "spirit:profile-detail" pk=user.pk slug=user.slug %}">{% trans "Profile" %}</a></li>
|
||||
<li><a class="menu-link" href="{% url "spirit:profile-detail" pk=user.pk slug=user.st.slug %}">{% trans "Profile" %}</a></li>
|
||||
<li><a class="menu-link" href="{% url "spirit:topic-active" %}">{% trans "Topics" %}</a></li>
|
||||
<li><a class="menu-link" href="{% url "spirit:topic-unread-list" %}">{% trans "Unread topics" %}</a></li>
|
||||
<li><a class="menu-link" href="{% url "spirit:private-list" %}">{% trans "Private topics" %}</a></li>
|
||||
|
||||
{% if user.is_administrator %}
|
||||
{% if user.st.is_administrator %}
|
||||
<li><a class="menu-link" href="{% url "spirit:admin" %}">{% trans "Admin" %}</a></li>
|
||||
{% endif %}
|
||||
|
||||
|
@ -41,7 +41,7 @@
|
||||
<img class="comment-avatar" src="{% get_gravatar_url user=flag.comment.user size=50 %}" />
|
||||
|
||||
<div class="comment-username">
|
||||
<a href="{{ flag.comment.user.get_absolute_url }}">{{ flag.comment.user.username }}</a>
|
||||
<a href="{{ flag.comment.user.st.get_absolute_url }}">{{ flag.comment.user.username }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -73,7 +73,7 @@
|
||||
<img class="comment-avatar" src="{% get_gravatar_url user=f.user size=50 %}" />
|
||||
|
||||
<div class="comment-username">
|
||||
<a href="{{ f.user.get_absolute_url }}">{{ f.user.username }}</a>
|
||||
<a href="{{ f.user.st.get_absolute_url }}">{{ f.user.username }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
<form action="." method="post">
|
||||
{% csrf_token %}
|
||||
{% include "spirit/_form.html" with form=uform %}
|
||||
{% include "spirit/_form.html" %}
|
||||
|
||||
<input class="button" type="submit" name="post" value="{% trans "Save" %}" />
|
||||
|
@ -17,7 +17,7 @@
|
||||
<div class="comment-info">
|
||||
|
||||
<div class="comment-username">
|
||||
<a class="username{% if c.user.is_administrator %} is-admin{% elif c.user.is_moderator %} is-mod{% endif %}" href="{{ c.user.get_absolute_url }}">{{ c.user.username }}</a><span class="comment-realname">{{ c.user.get_full_name }}</span>
|
||||
<a class="username{% if c.user.st.is_administrator %} is-admin{% elif c.user.st.is_moderator %} is-mod{% endif %}" href="{{ c.user.st.get_absolute_url }}">{{ c.user.username }}</a><span class="comment-realname">{{ c.user.get_full_name }}</span>
|
||||
</div>
|
||||
|
||||
<ul class="comment-date">
|
||||
@ -43,7 +43,7 @@
|
||||
{% if not c.action %}
|
||||
<ul class="comment-actions">
|
||||
{% if user.is_authenticated %}
|
||||
{% if user.is_moderator %}
|
||||
{% if user.st.is_moderator %}
|
||||
<li><a href="{% url "spirit:comment-delete" c.pk %}"><i class="fa fa-times"></i> {% trans "delete" %}</a></li>
|
||||
{% endif %}
|
||||
|
||||
@ -63,7 +63,7 @@
|
||||
{% endifnotequal %}
|
||||
{% endif %}
|
||||
|
||||
{% if user.is_moderator or c.user.pk == user.pk %}
|
||||
{% if user.st.is_moderator or c.user.pk == user.pk %}
|
||||
<li><a href="{% url "spirit:comment-update" pk=c.pk %}" >{% trans "edit" %}</a></li>
|
||||
{% endif %}
|
||||
|
||||
@ -97,14 +97,14 @@
|
||||
<div class="comment-media">
|
||||
<div class="comment-img">
|
||||
<div class="comment-removed">
|
||||
<a href="{{ c.user.get_absolute_url }}">{{ c.user.username }}</a>
|
||||
<a href="{{ c.user.st.get_absolute_url }}">{{ c.user.username }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="comment-body">
|
||||
|
||||
<div class="comment-text">
|
||||
{% if user.is_moderator %}
|
||||
{% if user.st.is_moderator %}
|
||||
{{ c.comment_html|safe }}
|
||||
{% else %}
|
||||
{% trans "This comment was deleted" %}.
|
||||
@ -113,7 +113,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if user.is_moderator %}
|
||||
{% if user.st.is_moderator %}
|
||||
<ul class="comment-actions">
|
||||
<li><a href="{% url "spirit:comment-undelete" c.pk %}"><i class="fa fa-times"></i> {% trans "undelete" %}</a></li>
|
||||
</ul>
|
||||
|
@ -24,7 +24,7 @@
|
||||
<div class="comment-info">
|
||||
|
||||
<div class="comment-username">
|
||||
<a href="{{ c.comment_fk.user.get_absolute_url }}">{{ c.comment_fk.user.username }}</a>
|
||||
<a href="{{ c.comment_fk.user.st.get_absolute_url }}">{{ c.comment_fk.user.username }}</a>
|
||||
</div>
|
||||
|
||||
<ul class="comment-date">
|
||||
|
@ -26,14 +26,14 @@
|
||||
|
||||
{{ topic.title }}
|
||||
|
||||
{% if user.is_moderator %}
|
||||
{% if user.st.is_moderator %}
|
||||
<a class="head-edit-link" href="{% url "spirit:topic-update" topic.pk %}"><i class="fa fa-pencil"></i> {% trans "edit" %}</a>
|
||||
{% elif user.pk == topic.user.pk and not topic.is_closed %}
|
||||
<a class="head-edit-link" href="{% url "spirit:topic-update" topic.pk %}"><i class="fa fa-pencil"></i> {% trans "edit" %}</a>
|
||||
{% endif %}
|
||||
</h1>
|
||||
|
||||
{% if user.is_moderator %}
|
||||
{% if user.st.is_moderator %}
|
||||
<div class="topic-moderation js-tabs-container">
|
||||
<a class="dropdown-button js-tab" href="#" data-related=".js-mod-content"><i class="fa fa-cogs"></i></a>
|
||||
|
||||
@ -120,7 +120,7 @@
|
||||
} );
|
||||
|
||||
|
||||
{% if user.is_moderator %}
|
||||
{% if user.st.is_moderator %}
|
||||
$('.js-show-move-comments').move_comments( {
|
||||
csrfToken: "{{ csrf_token }}",
|
||||
target: "{% url "spirit:comment-move" topic.pk %}",
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
{% for n in notifications %}
|
||||
<div class="row">
|
||||
{% url "spirit:profile-detail" pk=n.comment.user.pk slug=n.comment.user.slug as url_profile %}
|
||||
{% url "spirit:profile-detail" pk=n.comment.user.pk slug=n.comment.user.st.slug as url_profile %}
|
||||
{% url "spirit:comment-find" pk=n.comment.pk as url_topic %}
|
||||
|
||||
{% if n.is_comment %}
|
||||
|
@ -14,13 +14,13 @@
|
||||
</li><!--
|
||||
--><li>
|
||||
<div class="profile-title">{% trans "Seen" %}</div>
|
||||
<div class="profile-date">{{ p_user.last_seen|shortnaturaltime }}</div>
|
||||
<div class="profile-date">{{ p_user.st.last_seen|shortnaturaltime }}</div>
|
||||
</li>
|
||||
|
||||
{% if user.is_administrator %}
|
||||
{% if user.st.is_administrator %}
|
||||
<li>
|
||||
<div class="profile-title">{% trans "Last IP" %}</div>
|
||||
<div class="profile-date">{{ p_user.last_ip }}</div>
|
||||
<div class="profile-date">{{ p_user.st.last_ip }}</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
@ -36,14 +36,14 @@
|
||||
</div>
|
||||
{% endifequal %}
|
||||
|
||||
{% if user.is_administrator %}
|
||||
{% if user.st.is_administrator %}
|
||||
<div class="profile-preferences">
|
||||
<a class="button" href="{% url "spirit:admin-user-edit" user_id=p_user.pk %}"><i class="fa fa-cog"></i> {% trans "Edit user" %}</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<ul class="tabs">
|
||||
<li><a class="tab-link{% ifequal active_tab 0 %} is-selected{% endifequal %}" href="{% url "spirit:profile-detail" pk=p_user.pk slug=p_user.slug %}" >{% trans "Comments" %}</a></li><!--
|
||||
--><li><a class="tab-link{% ifequal active_tab 1 %} is-selected{% endifequal %}" href="{% url "spirit:profile-topics" pk=p_user.pk slug=p_user.slug %}" >{% trans "Topics" %}</a></li><!--
|
||||
--><li><a class="tab-link{% ifequal active_tab 2 %} is-selected{% endifequal %}" href="{% url "spirit:profile-likes" pk=p_user.pk slug=p_user.slug %}" >{% trans "Likes" %}</a></li>
|
||||
<li><a class="tab-link{% ifequal active_tab 0 %} is-selected{% endifequal %}" href="{% url "spirit:profile-detail" pk=p_user.pk slug=p_user.st.slug %}" >{% trans "Comments" %}</a></li><!--
|
||||
--><li><a class="tab-link{% ifequal active_tab 1 %} is-selected{% endifequal %}" href="{% url "spirit:profile-topics" pk=p_user.pk slug=p_user.st.slug %}" >{% trans "Topics" %}</a></li><!--
|
||||
--><li><a class="tab-link{% ifequal active_tab 2 %} is-selected{% endifequal %}" href="{% url "spirit:profile-likes" pk=p_user.pk slug=p_user.st.slug %}" >{% trans "Likes" %}</a></li>
|
||||
</ul>
|
@ -15,7 +15,7 @@
|
||||
<div class="comment-info">
|
||||
|
||||
<div class="comment-username">
|
||||
<a href="{{ c.user.get_absolute_url }}">{{ c.user.username }}</a>
|
||||
<a href="{{ c.user.st.get_absolute_url }}">{{ c.user.username }}</a>
|
||||
</div>
|
||||
|
||||
<ul class="comment-date">
|
||||
|
@ -11,12 +11,12 @@
|
||||
<h1 class="headline">{% trans "Menu" %}</h1>
|
||||
|
||||
<ul class="menu">
|
||||
<li><a class="menu-link" href="{% url "spirit:profile-detail" pk=user.pk slug=user.slug %}">{% trans "Profile" %}</a></li>
|
||||
<li><a class="menu-link" href="{% url "spirit:profile-detail" pk=user.pk slug=user.st.slug %}">{% trans "Profile" %}</a></li>
|
||||
<li><a class="menu-link" href="{% url "spirit:topic-active" %}">{% trans "Topics" %}</a></li>
|
||||
<li><a class="menu-link" href="{% url "spirit:topic-unread-list" %}">{% trans "Unread topics" %}</a></li>
|
||||
<li><a class="menu-link" href="{% url "spirit:private-list" %}">{% trans "Private topics" %}</a></li>
|
||||
|
||||
{% if user.is_administrator %}
|
||||
{% if user.st.is_administrator %}
|
||||
<li><a class="menu-link" href="{% url "spirit:admin" %}">{% trans "Admin" %}</a></li>
|
||||
{% endif %}
|
||||
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
<form action="." method="post">
|
||||
{% csrf_token %}
|
||||
{% include "spirit/_form.html" with form=uform %}
|
||||
{% include "spirit/_form.html" %}
|
||||
|
||||
<input class="button" type="submit" name="post" value="{% trans "Save" %}" />
|
||||
|
@ -11,4 +11,4 @@ from .. import register
|
||||
@register.simple_tag()
|
||||
def get_avatar_color(user):
|
||||
# returns 0-215
|
||||
return smart_text(int(215 * math.log10(user.id)))
|
||||
return smart_text(int(215 * math.log10(user.pk)))
|
||||
|
@ -18,7 +18,7 @@ def moderator_required(view_func):
|
||||
return redirect_to_login(next=request.get_full_path(),
|
||||
login_url=settings.LOGIN_URL)
|
||||
|
||||
if not user.is_moderator:
|
||||
if not user.st.is_moderator:
|
||||
raise PermissionDenied
|
||||
|
||||
return view_func(request, *args, **kwargs)
|
||||
@ -35,7 +35,7 @@ def administrator_required(view_func):
|
||||
return redirect_to_login(next=request.get_full_path(),
|
||||
login_url=settings.LOGIN_URL)
|
||||
|
||||
if not user.is_administrator:
|
||||
if not user.st.is_administrator:
|
||||
raise PermissionDenied
|
||||
|
||||
return view_func(request, *args, **kwargs)
|
||||
@ -48,7 +48,7 @@ def guest_only(view_func):
|
||||
@wraps(view_func)
|
||||
def wrapper(request, *args, **kwargs):
|
||||
if request.user.is_authenticated():
|
||||
return redirect(request.GET.get('next', request.user.get_absolute_url()))
|
||||
return redirect(request.GET.get('next', request.user.st.get_absolute_url()))
|
||||
|
||||
return view_func(request, *args, **kwargs)
|
||||
|
||||
|
@ -71,7 +71,7 @@ class InlineLexer(mistune.InlineLexer):
|
||||
# Already mentioned?
|
||||
if username in self.mentions:
|
||||
user = self.mentions[username]
|
||||
return self.renderer.mention(username, user.get_absolute_url())
|
||||
return self.renderer.mention(username, user.st.get_absolute_url())
|
||||
|
||||
# Mentions limiter
|
||||
if self._mention_count >= settings.ST_MENTIONS_PER_COMMENT:
|
||||
@ -87,4 +87,4 @@ class InlineLexer(mistune.InlineLexer):
|
||||
return m.group(0)
|
||||
|
||||
self.mentions[username] = user
|
||||
return self.renderer.mention(username, user.get_absolute_url())
|
||||
return self.renderer.mention(username, user.st.get_absolute_url())
|
||||
|
@ -31,7 +31,11 @@ class AutoSlugField(SlugField):
|
||||
if default or not add or not self.populate_from:
|
||||
return default
|
||||
|
||||
value = getattr(instance, self.populate_from)
|
||||
inst = instance
|
||||
|
||||
for attr in self.populate_from.split('.'):
|
||||
value = getattr(inst, attr)
|
||||
inst = value
|
||||
|
||||
if value is None:
|
||||
return default
|
||||
|
@ -38,7 +38,7 @@ class TokenGenerator(object):
|
||||
class UserActivationTokenGenerator(TokenGenerator):
|
||||
|
||||
def _uid(self, user):
|
||||
return ";".join((smart_text(user.pk), smart_text(user.is_verified)))
|
||||
return ";".join((smart_text(user.pk), smart_text(user.st.is_verified)))
|
||||
|
||||
|
||||
class UserEmailChangeTokenGenerator(TokenGenerator):
|
||||
|
@ -12,7 +12,7 @@ from djconfig import config
|
||||
from ...utils.paginator import yt_paginate
|
||||
from spirit.utils.decorators import administrator_required
|
||||
|
||||
from spirit.forms.admin import UserEditForm
|
||||
from spirit.forms.admin import UserForm, UserProfileForm
|
||||
|
||||
|
||||
User = get_user_model()
|
||||
@ -23,16 +23,22 @@ def user_edit(request, user_id):
|
||||
user = get_object_or_404(User, pk=user_id)
|
||||
|
||||
if request.method == 'POST':
|
||||
form = UserEditForm(data=request.POST, instance=user)
|
||||
uform = UserForm(data=request.POST, instance=user)
|
||||
form = UserProfileForm(data=request.POST, instance=user.st)
|
||||
|
||||
if form.is_valid():
|
||||
if uform.is_valid() and form.is_valid():
|
||||
uform.save()
|
||||
form.save()
|
||||
messages.info(request, _("This profile has been updated!"))
|
||||
return redirect(request.GET.get("next", request.get_full_path()))
|
||||
else:
|
||||
form = UserEditForm(instance=user)
|
||||
uform = UserForm(instance=user)
|
||||
form = UserProfileForm(instance=user.st)
|
||||
|
||||
context = {'form': form, }
|
||||
context = {
|
||||
'form': form,
|
||||
'uform': uform
|
||||
}
|
||||
|
||||
return render(request, 'spirit/admin/user/user_edit.html', context)
|
||||
|
||||
@ -40,7 +46,7 @@ def user_edit(request, user_id):
|
||||
@administrator_required
|
||||
def user_list(request):
|
||||
users = yt_paginate(
|
||||
User.objects.all(),
|
||||
User.objects.all().order_by('-date_joined', '-pk'),
|
||||
per_page=config.topics_per_page,
|
||||
page_number=request.GET.get('page', 1)
|
||||
)
|
||||
@ -51,7 +57,7 @@ def user_list(request):
|
||||
@administrator_required
|
||||
def user_admins(request):
|
||||
users = yt_paginate(
|
||||
User.objects.filter(is_administrator=True),
|
||||
User.objects.filter(st__is_administrator=True).order_by('-date_joined', '-pk'),
|
||||
per_page=config.topics_per_page,
|
||||
page_number=request.GET.get('page', 1)
|
||||
)
|
||||
@ -62,7 +68,7 @@ def user_admins(request):
|
||||
@administrator_required
|
||||
def user_mods(request):
|
||||
users = yt_paginate(
|
||||
User.objects.filter(is_moderator=True, is_administrator=False),
|
||||
User.objects.filter(st__is_moderator=True, st__is_administrator=False).order_by('-date_joined', '-pk'),
|
||||
per_page=config.topics_per_page,
|
||||
page_number=request.GET.get('page', 1)
|
||||
)
|
||||
@ -73,7 +79,7 @@ def user_mods(request):
|
||||
@administrator_required
|
||||
def user_unactive(request):
|
||||
users = yt_paginate(
|
||||
User.objects.filter(is_active=False),
|
||||
User.objects.filter(is_active=False).order_by('-date_joined', '-pk'),
|
||||
per_page=config.topics_per_page,
|
||||
page_number=request.GET.get('page', 1)
|
||||
)
|
||||
|
@ -23,7 +23,8 @@ from ..utils.paginator import yt_paginate
|
||||
from ..models.topic import Topic
|
||||
from ..models.comment import Comment
|
||||
|
||||
from ..forms.user import UserProfileForm, RegistrationForm, LoginForm, EmailChangeForm, ResendActivationForm
|
||||
from ..forms.user import UserProfileForm, RegistrationForm, \
|
||||
LoginForm, EmailChangeForm, ResendActivationForm, UserForm
|
||||
|
||||
|
||||
User = get_user_model()
|
||||
@ -34,7 +35,7 @@ User = get_user_model()
|
||||
def custom_login(request, **kwargs):
|
||||
# Current Django 1.5 login view does not redirect somewhere if the user is logged in
|
||||
if request.user.is_authenticated():
|
||||
return redirect(request.GET.get('next', request.user.get_absolute_url()))
|
||||
return redirect(request.GET.get('next', request.user.st.get_absolute_url()))
|
||||
|
||||
if request.is_limited and request.method == "POST":
|
||||
return redirect(request.get_full_path())
|
||||
@ -95,7 +96,7 @@ def registration_activation(request, pk, token):
|
||||
activation = UserActivationTokenGenerator()
|
||||
|
||||
if activation.is_valid(user, token):
|
||||
user.is_verified = True
|
||||
user.st.is_verified = True
|
||||
user.is_active = True
|
||||
user.save()
|
||||
messages.info(request, _("Your account has been activated!"))
|
||||
@ -131,16 +132,22 @@ def resend_activation_email(request):
|
||||
@login_required
|
||||
def profile_update(request):
|
||||
if request.method == 'POST':
|
||||
form = UserProfileForm(data=request.POST, instance=request.user)
|
||||
uform = UserForm(data=request.POST, instance=request.user)
|
||||
form = UserProfileForm(data=request.POST, instance=request.user.st)
|
||||
|
||||
if form.is_valid():
|
||||
if uform.is_valid() and form.is_valid():
|
||||
uform.save()
|
||||
form.save()
|
||||
messages.info(request, _("Your profile has been updated!"))
|
||||
return redirect(reverse('spirit:profile-update'))
|
||||
else:
|
||||
form = UserProfileForm(instance=request.user)
|
||||
uform = UserForm(instance=request.user)
|
||||
form = UserProfileForm(instance=request.user.st)
|
||||
|
||||
context = {'form': form, }
|
||||
context = {
|
||||
'form': form,
|
||||
'uform': uform
|
||||
}
|
||||
|
||||
return render(request, 'spirit/user/profile_update.html', context)
|
||||
|
||||
@ -196,8 +203,8 @@ def email_change_confirm(request, token):
|
||||
def profile_topics(request, pk, slug):
|
||||
p_user = get_object_or_404(User, pk=pk)
|
||||
|
||||
if p_user.slug != slug:
|
||||
url = reverse("spirit:profile-topics", kwargs={'pk': p_user.pk, 'slug': p_user.slug})
|
||||
if p_user.st.slug != slug:
|
||||
url = reverse("spirit:profile-topics", kwargs={'pk': p_user.pk, 'slug': p_user.st.slug})
|
||||
return HttpResponsePermanentRedirect(url)
|
||||
|
||||
topics = Topic.objects\
|
||||
@ -225,8 +232,8 @@ def profile_topics(request, pk, slug):
|
||||
def profile_comments(request, pk, slug):
|
||||
p_user = get_object_or_404(User, pk=pk)
|
||||
|
||||
if p_user.slug != slug:
|
||||
url = reverse("spirit:profile-detail", kwargs={'pk': p_user.pk, 'slug': p_user.slug})
|
||||
if p_user.st.slug != slug:
|
||||
url = reverse("spirit:profile-detail", kwargs={'pk': p_user.pk, 'slug': p_user.st.slug})
|
||||
return HttpResponsePermanentRedirect(url)
|
||||
|
||||
comments = Comment.objects\
|
||||
@ -251,8 +258,8 @@ def profile_comments(request, pk, slug):
|
||||
def profile_likes(request, pk, slug):
|
||||
p_user = get_object_or_404(User, pk=pk)
|
||||
|
||||
if p_user.slug != slug:
|
||||
url = reverse("spirit:profile-likes", kwargs={'pk': p_user.pk, 'slug': p_user.slug})
|
||||
if p_user.st.slug != slug:
|
||||
url = reverse("spirit:profile-likes", kwargs={'pk': p_user.pk, 'slug': p_user.st.slug})
|
||||
return HttpResponsePermanentRedirect(url)
|
||||
|
||||
comments = Comment.objects\
|
||||
|
@ -6,7 +6,6 @@ from django.test import TestCase, RequestFactory
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.core.cache import cache
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.contrib.auth.models import User as UserModel
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
from djconfig.utils import override_djconfig
|
||||
@ -16,7 +15,7 @@ from . import utils
|
||||
from spirit.views.admin import user, category, comment_flag, config, index, topic
|
||||
from spirit.models.category import Category
|
||||
from spirit.models.comment_flag import CommentFlag, Flag
|
||||
from spirit.forms.admin import UserEditForm, CategoryForm, BasicConfigForm, CommentFlagForm
|
||||
from spirit.forms.admin import UserForm, CategoryForm, BasicConfigForm, CommentFlagForm, UserProfileForm
|
||||
|
||||
|
||||
User = get_user_model()
|
||||
@ -26,14 +25,16 @@ class AdminViewTest(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
cache.clear()
|
||||
self.user = utils.create_user(is_administrator=True)
|
||||
self.user = utils.create_user()
|
||||
self.user.st.is_administrator = True
|
||||
self.user.st.save()
|
||||
self.category = utils.create_category()
|
||||
self.topic = utils.create_topic(self.category, user=self.user)
|
||||
|
||||
def test_permission_denied_to_non_admin(self):
|
||||
req = RequestFactory().get('/')
|
||||
req.user = UserModel()
|
||||
req.user.is_administrator = False
|
||||
req.user = self.user
|
||||
req.user.st.is_administrator = False
|
||||
|
||||
self.assertRaises(PermissionDenied, category.category_list, req)
|
||||
self.assertRaises(PermissionDenied, category.category_create, req)
|
||||
@ -104,7 +105,9 @@ class AdminViewTest(TestCase):
|
||||
"""
|
||||
List of admins paginated
|
||||
"""
|
||||
user2 = utils.create_user(is_administrator=True)
|
||||
user2 = utils.create_user()
|
||||
user2.st.is_administrator = True
|
||||
user2.st.save()
|
||||
|
||||
utils.login(self)
|
||||
response = self.client.get(reverse('spirit:admin-user-admins'))
|
||||
@ -114,7 +117,10 @@ class AdminViewTest(TestCase):
|
||||
"""
|
||||
List of mods
|
||||
"""
|
||||
mod = utils.create_user(is_moderator=True)
|
||||
mod = utils.create_user()
|
||||
mod.st.is_moderator = True
|
||||
mod.st.save()
|
||||
|
||||
utils.login(self)
|
||||
response = self.client.get(reverse('spirit:admin-user-mods'))
|
||||
self.assertQuerysetEqual(response.context['users'], map(repr, [mod, ]))
|
||||
@ -124,12 +130,17 @@ class AdminViewTest(TestCase):
|
||||
"""
|
||||
List of mods paginated
|
||||
"""
|
||||
utils.create_user(is_moderator=True)
|
||||
mod = utils.create_user(is_moderator=True)
|
||||
mod = utils.create_user()
|
||||
mod.st.is_moderator = True
|
||||
mod.st.save()
|
||||
|
||||
mod2 = utils.create_user()
|
||||
mod2.st.is_moderator = True
|
||||
mod2.st.save()
|
||||
|
||||
utils.login(self)
|
||||
response = self.client.get(reverse('spirit:admin-user-mods'))
|
||||
self.assertQuerysetEqual(response.context['users'], map(repr, [mod, ]))
|
||||
self.assertQuerysetEqual(response.context['users'], map(repr, [mod2, ]))
|
||||
|
||||
def test_user_unactive(self):
|
||||
"""
|
||||
@ -387,7 +398,10 @@ class AdminFormTest(TestCase):
|
||||
"is_administrator": True,
|
||||
"is_moderator": True,
|
||||
"is_active": True}
|
||||
form = UserEditForm(data=form_data)
|
||||
form = UserForm(data=form_data)
|
||||
self.assertEqual(form.is_valid(), True)
|
||||
|
||||
form = UserProfileForm(data=form_data)
|
||||
self.assertEqual(form.is_valid(), True)
|
||||
|
||||
def test_category(self):
|
||||
|
@ -10,7 +10,6 @@ from django.core.cache import cache
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.template import Template, Context
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.contrib.auth.models import User as UserModel
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.conf import settings
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
@ -29,6 +28,7 @@ from spirit.utils import markdown
|
||||
from spirit.views.comment import comment_delete
|
||||
from spirit.models.topic import Topic
|
||||
from spirit.models.category import Category
|
||||
from spirit.models.user import UserProfile
|
||||
|
||||
|
||||
User = get_user_model()
|
||||
@ -221,7 +221,7 @@ class CommentViewTest(TestCase):
|
||||
"""
|
||||
moderators can update other people comments
|
||||
"""
|
||||
User.objects.filter(pk=self.user.pk).update(is_moderator=True)
|
||||
UserProfile.objects.filter(user__pk=self.user.pk).update(is_moderator=True)
|
||||
user = utils.create_user()
|
||||
comment = utils.create_comment(user=user, topic=self.topic)
|
||||
|
||||
@ -237,7 +237,7 @@ class CommentViewTest(TestCase):
|
||||
"""
|
||||
moderators can not update comments in private topics they has no access
|
||||
"""
|
||||
User.objects.filter(pk=self.user.pk).update(is_moderator=True)
|
||||
UserProfile.objects.filter(user__pk=self.user.pk).update(is_moderator=True)
|
||||
user = utils.create_user()
|
||||
topic_private = utils.create_private_topic()
|
||||
comment = utils.create_comment(user=user, topic=topic_private.topic)
|
||||
@ -270,15 +270,17 @@ class CommentViewTest(TestCase):
|
||||
|
||||
def test_comment_delete_permission_denied_to_non_moderator(self):
|
||||
req = RequestFactory().get('/')
|
||||
req.user = UserModel()
|
||||
req.user.is_moderator = False
|
||||
req.user = self.user
|
||||
req.user.st.is_moderator = False
|
||||
self.assertRaises(PermissionDenied, comment_delete, req)
|
||||
|
||||
def test_comment_delete(self):
|
||||
"""
|
||||
comment delete
|
||||
"""
|
||||
self.user = utils.create_user(is_moderator=True)
|
||||
self.user = utils.create_user()
|
||||
self.user.st.is_moderator = True
|
||||
self.user.st.save()
|
||||
comment = utils.create_comment(user=self.user, topic=self.topic)
|
||||
|
||||
utils.login(self)
|
||||
@ -295,7 +297,9 @@ class CommentViewTest(TestCase):
|
||||
"""
|
||||
comment undelete
|
||||
"""
|
||||
self.user = utils.create_user(is_moderator=True)
|
||||
self.user = utils.create_user()
|
||||
self.user.st.is_moderator = True
|
||||
self.user.st.save()
|
||||
comment = utils.create_comment(user=self.user, topic=self.topic, is_removed=True)
|
||||
|
||||
utils.login(self)
|
||||
@ -313,7 +317,7 @@ class CommentViewTest(TestCase):
|
||||
comment move to another topic
|
||||
"""
|
||||
utils.login(self)
|
||||
self.user.is_moderator = True
|
||||
self.user.st.is_moderator = True
|
||||
self.user.save()
|
||||
comment = utils.create_comment(user=self.user, topic=self.topic)
|
||||
comment2 = utils.create_comment(user=self.user, topic=self.topic)
|
||||
@ -343,7 +347,7 @@ class CommentViewTest(TestCase):
|
||||
comment_moved.connect(comment_moved_handler)
|
||||
|
||||
utils.login(self)
|
||||
self.user.is_moderator = True
|
||||
self.user.st.is_moderator = True
|
||||
self.user.save()
|
||||
|
||||
comment = utils.create_comment(user=self.user, topic=self.topic)
|
||||
|
@ -178,7 +178,7 @@ class TopicViewTest(TestCase):
|
||||
topic_post_moderate.connect(topic_post_moderate_handler)
|
||||
|
||||
utils.login(self)
|
||||
self.user.is_moderator = True
|
||||
self.user.st.is_moderator = True
|
||||
self.user.save()
|
||||
|
||||
category = utils.create_category()
|
||||
|
@ -24,7 +24,7 @@ class TopicViewTest(TestCase):
|
||||
delete topic
|
||||
"""
|
||||
utils.login(self)
|
||||
self.user.is_moderator = True
|
||||
self.user.st.is_moderator = True
|
||||
self.user.save()
|
||||
|
||||
category = utils.create_category()
|
||||
@ -41,7 +41,7 @@ class TopicViewTest(TestCase):
|
||||
undelete topic
|
||||
"""
|
||||
utils.login(self)
|
||||
self.user.is_moderator = True
|
||||
self.user.st.is_moderator = True
|
||||
self.user.save()
|
||||
|
||||
category = utils.create_category()
|
||||
@ -62,7 +62,7 @@ class TopicViewTest(TestCase):
|
||||
topic_post_moderate.connect(topic_post_moderate_handler)
|
||||
|
||||
utils.login(self)
|
||||
self.user.is_moderator = True
|
||||
self.user.st.is_moderator = True
|
||||
self.user.save()
|
||||
|
||||
category = utils.create_category()
|
||||
@ -84,7 +84,7 @@ class TopicViewTest(TestCase):
|
||||
topic_post_moderate.connect(topic_post_moderate_handler)
|
||||
|
||||
utils.login(self)
|
||||
self.user.is_moderator = True
|
||||
self.user.st.is_moderator = True
|
||||
self.user.save()
|
||||
|
||||
category = utils.create_category()
|
||||
@ -106,7 +106,7 @@ class TopicViewTest(TestCase):
|
||||
topic_post_moderate.connect(topic_post_moderate_handler)
|
||||
|
||||
utils.login(self)
|
||||
self.user.is_moderator = True
|
||||
self.user.st.is_moderator = True
|
||||
self.user.save()
|
||||
|
||||
category = utils.create_category()
|
||||
@ -128,7 +128,7 @@ class TopicViewTest(TestCase):
|
||||
topic_post_moderate.connect(topic_post_moderate_handler)
|
||||
|
||||
utils.login(self)
|
||||
self.user.is_moderator = True
|
||||
self.user.st.is_moderator = True
|
||||
self.user.save()
|
||||
|
||||
category = utils.create_category()
|
||||
@ -150,7 +150,7 @@ class TopicViewTest(TestCase):
|
||||
topic_post_moderate.connect(topic_post_moderate_handler)
|
||||
|
||||
utils.login(self)
|
||||
self.user.is_moderator = True
|
||||
self.user.st.is_moderator = True
|
||||
self.user.save()
|
||||
|
||||
category = utils.create_category()
|
||||
@ -172,7 +172,7 @@ class TopicViewTest(TestCase):
|
||||
topic_post_moderate.connect(topic_post_moderate_handler)
|
||||
|
||||
utils.login(self)
|
||||
self.user.is_moderator = True
|
||||
self.user.st.is_moderator = True
|
||||
self.user.save()
|
||||
|
||||
category = utils.create_category()
|
||||
|
@ -16,11 +16,11 @@ from djconfig.utils import override_djconfig
|
||||
|
||||
from . import utils
|
||||
|
||||
from spirit.forms.user import RegistrationForm, UserProfileForm, EmailChangeForm, ResendActivationForm
|
||||
from spirit.forms.user import RegistrationForm, UserProfileForm, EmailChangeForm, ResendActivationForm, UserForm
|
||||
from spirit.backends.user import EmailAuthBackend
|
||||
from spirit.models.comment_like import CommentLike
|
||||
from spirit.utils.user.tokens import UserActivationTokenGenerator, UserEmailChangeTokenGenerator
|
||||
from spirit.models.user import User as UserModel
|
||||
from spirit.models.user import UserProfile
|
||||
from spirit.models.topic import Topic
|
||||
from spirit.models.comment import Comment
|
||||
from spirit.models.comment_bookmark import CommentBookmark
|
||||
@ -60,7 +60,7 @@ class UserViewTest(TestCase):
|
||||
"""
|
||||
utils.login(self)
|
||||
response = self.client.get(reverse('spirit:user-login'))
|
||||
expected_url = self.user.get_absolute_url()
|
||||
expected_url = self.user.st.get_absolute_url()
|
||||
self.assertRedirects(response, expected_url, status_code=302)
|
||||
# next
|
||||
response = self.client.get(reverse('spirit:user-login') + '?next=/fakepath/')
|
||||
@ -111,7 +111,7 @@ class UserViewTest(TestCase):
|
||||
"""
|
||||
utils.login(self)
|
||||
response = self.client.get(reverse("spirit:profile-topics", kwargs={'pk': self.user2.pk,
|
||||
'slug': self.user2.slug}))
|
||||
'slug': self.user2.st.slug}))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertQuerysetEqual(response.context['topics'], [repr(self.topic), ])
|
||||
self.assertEqual(repr(response.context['p_user']), repr(self.user2))
|
||||
@ -132,7 +132,7 @@ class UserViewTest(TestCase):
|
||||
|
||||
utils.login(self)
|
||||
response = self.client.get(reverse("spirit:profile-topics", kwargs={'pk': self.user2.pk,
|
||||
'slug': self.user2.slug}))
|
||||
'slug': self.user2.st.slug}))
|
||||
self.assertQuerysetEqual(response.context['topics'], map(repr, [topic_b, topic_c, topic_a]))
|
||||
|
||||
def test_profile_topics_bookmarks(self):
|
||||
@ -143,7 +143,7 @@ class UserViewTest(TestCase):
|
||||
|
||||
utils.login(self)
|
||||
response = self.client.get(reverse("spirit:profile-topics",
|
||||
kwargs={'pk': self.user2.pk, 'slug': self.user2.slug}))
|
||||
kwargs={'pk': self.user2.pk, 'slug': self.user2.st.slug}))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertQuerysetEqual(response.context['topics'], [repr(self.topic), ])
|
||||
self.assertEqual(response.context['topics'][0].bookmark, bookmark)
|
||||
@ -157,7 +157,7 @@ class UserViewTest(TestCase):
|
||||
|
||||
utils.login(self)
|
||||
response = self.client.get(reverse("spirit:profile-topics", kwargs={'pk': self.user2.pk,
|
||||
'slug': self.user2.slug}))
|
||||
'slug': self.user2.st.slug}))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertQuerysetEqual(response.context['topics'], [repr(topic), ])
|
||||
|
||||
@ -179,7 +179,7 @@ class UserViewTest(TestCase):
|
||||
|
||||
utils.login(self)
|
||||
response = self.client.get(reverse("spirit:profile-topics", kwargs={'pk': self.user2.pk,
|
||||
'slug': self.user2.slug}))
|
||||
'slug': self.user2.st.slug}))
|
||||
self.assertQuerysetEqual(response.context['topics'], [])
|
||||
|
||||
def test_profile_topics_invalid_slug(self):
|
||||
@ -190,7 +190,7 @@ class UserViewTest(TestCase):
|
||||
response = self.client.get(reverse("spirit:profile-topics", kwargs={'pk': self.user2.pk,
|
||||
'slug': "invalid"}))
|
||||
expected_url = reverse("spirit:profile-topics", kwargs={'pk': self.user2.pk,
|
||||
'slug': self.user2.slug})
|
||||
'slug': self.user2.st.slug})
|
||||
self.assertRedirects(response, expected_url, status_code=301)
|
||||
|
||||
def test_profile_comments(self):
|
||||
@ -201,7 +201,7 @@ class UserViewTest(TestCase):
|
||||
comment = utils.create_comment(user=self.user2, topic=self.topic)
|
||||
utils.create_comment(user=self.user, topic=self.topic)
|
||||
response = self.client.get(reverse("spirit:profile-detail", kwargs={'pk': self.user2.pk,
|
||||
'slug': self.user2.slug}))
|
||||
'slug': self.user2.st.slug}))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertQuerysetEqual(response.context['comments'], [repr(comment), ])
|
||||
self.assertEqual(repr(response.context['p_user']), repr(self.user2))
|
||||
@ -219,7 +219,7 @@ class UserViewTest(TestCase):
|
||||
|
||||
utils.login(self)
|
||||
response = self.client.get(reverse("spirit:profile-detail", kwargs={'pk': self.user2.pk,
|
||||
'slug': self.user2.slug}))
|
||||
'slug': self.user2.st.slug}))
|
||||
self.assertQuerysetEqual(response.context['comments'], map(repr, [comment_b, comment_c, comment_a]))
|
||||
|
||||
@override_djconfig(comments_per_page=1)
|
||||
@ -232,7 +232,7 @@ class UserViewTest(TestCase):
|
||||
|
||||
utils.login(self)
|
||||
response = self.client.get(reverse("spirit:profile-detail", kwargs={'pk': self.user2.pk,
|
||||
'slug': self.user2.slug}))
|
||||
'slug': self.user2.st.slug}))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertQuerysetEqual(response.context['comments'], [repr(comment), ])
|
||||
|
||||
@ -257,7 +257,7 @@ class UserViewTest(TestCase):
|
||||
|
||||
utils.login(self)
|
||||
response = self.client.get(reverse("spirit:profile-detail", kwargs={'pk': self.user2.pk,
|
||||
'slug': self.user2.slug}))
|
||||
'slug': self.user2.st.slug}))
|
||||
self.assertQuerysetEqual(response.context['comments'], [])
|
||||
|
||||
def test_profile_comments_invalid_slug(self):
|
||||
@ -268,7 +268,7 @@ class UserViewTest(TestCase):
|
||||
response = self.client.get(reverse("spirit:profile-detail", kwargs={'pk': self.user2.pk,
|
||||
'slug': "invalid"}))
|
||||
expected_url = reverse("spirit:profile-detail", kwargs={'pk': self.user2.pk,
|
||||
'slug': self.user2.slug})
|
||||
'slug': self.user2.st.slug})
|
||||
self.assertRedirects(response, expected_url, status_code=301)
|
||||
|
||||
def test_profile_likes(self):
|
||||
@ -281,7 +281,7 @@ class UserViewTest(TestCase):
|
||||
like = CommentLike.objects.create(user=self.user2, comment=comment)
|
||||
CommentLike.objects.create(user=self.user, comment=comment2)
|
||||
response = self.client.get(reverse("spirit:profile-likes", kwargs={'pk': self.user2.pk,
|
||||
'slug': self.user2.slug}))
|
||||
'slug': self.user2.st.slug}))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertQuerysetEqual(response.context['comments'], [repr(like.comment), ])
|
||||
self.assertEqual(repr(response.context['p_user']), repr(self.user2))
|
||||
@ -302,7 +302,7 @@ class UserViewTest(TestCase):
|
||||
|
||||
utils.login(self)
|
||||
response = self.client.get(reverse("spirit:profile-likes", kwargs={'pk': self.user2.pk,
|
||||
'slug': self.user2.slug}))
|
||||
'slug': self.user2.st.slug}))
|
||||
self.assertQuerysetEqual(response.context['comments'], map(repr, [comment_b, comment_c, comment_a]))
|
||||
|
||||
def test_profile_likes_dont_show_removed_or_private(self):
|
||||
@ -331,7 +331,7 @@ class UserViewTest(TestCase):
|
||||
|
||||
utils.login(self)
|
||||
response = self.client.get(reverse("spirit:profile-likes", kwargs={'pk': self.user2.pk,
|
||||
'slug': self.user2.slug}))
|
||||
'slug': self.user2.st.slug}))
|
||||
self.assertQuerysetEqual(response.context['comments'], [])
|
||||
|
||||
def test_profile_likes_invalid_slug(self):
|
||||
@ -342,7 +342,7 @@ class UserViewTest(TestCase):
|
||||
response = self.client.get(reverse("spirit:profile-likes", kwargs={'pk': self.user2.pk,
|
||||
'slug': "invalid"}))
|
||||
expected_url = reverse("spirit:profile-likes", kwargs={'pk': self.user2.pk,
|
||||
'slug': self.user2.slug})
|
||||
'slug': self.user2.st.slug})
|
||||
self.assertRedirects(response, expected_url, status_code=301)
|
||||
|
||||
@override_djconfig(comments_per_page=1)
|
||||
@ -357,7 +357,7 @@ class UserViewTest(TestCase):
|
||||
|
||||
utils.login(self)
|
||||
response = self.client.get(reverse("spirit:profile-likes", kwargs={'pk': self.user2.pk,
|
||||
'slug': self.user2.slug}))
|
||||
'slug': self.user2.st.slug}))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertQuerysetEqual(response.context['comments'], [repr(like.comment), ])
|
||||
|
||||
@ -372,7 +372,7 @@ class UserViewTest(TestCase):
|
||||
|
||||
# post
|
||||
form_data = {'first_name': 'foo', 'last_name': 'bar',
|
||||
'location': 'spirit', 'timezone': self.user.timezone}
|
||||
'location': 'spirit', 'timezone': self.user.st.timezone}
|
||||
response = self.client.post(reverse('spirit:profile-update'),
|
||||
form_data)
|
||||
expected_url = reverse('spirit:profile-update')
|
||||
@ -449,7 +449,7 @@ class UserViewTest(TestCase):
|
||||
"""
|
||||
registration activation
|
||||
"""
|
||||
self.user.is_verified = False
|
||||
self.user.st.is_verified = False
|
||||
self.user.is_active = False
|
||||
self.user.save()
|
||||
token = UserActivationTokenGenerator().generate(self.user)
|
||||
@ -464,11 +464,12 @@ class UserViewTest(TestCase):
|
||||
Activation token should not work if user is verified
|
||||
ActiveUserMiddleware required
|
||||
"""
|
||||
self.user.is_verified = False
|
||||
self.user.st.is_verified = False
|
||||
token = UserActivationTokenGenerator().generate(self.user)
|
||||
|
||||
utils.login(self)
|
||||
User.objects.filter(pk=self.user.pk).update(is_active=False, is_verified=True)
|
||||
User.objects.filter(pk=self.user.pk).update(is_active=False)
|
||||
UserProfile.objects.filter(user__pk=self.user.pk).update(is_verified=True)
|
||||
response = self.client.get(reverse('spirit:registration-activation', kwargs={'pk': self.user.pk,
|
||||
'token': token}))
|
||||
expected_url = reverse("spirit:user-login")
|
||||
@ -543,7 +544,9 @@ class UserViewTest(TestCase):
|
||||
"""
|
||||
resend_activation_email invalid if is_verified was set
|
||||
"""
|
||||
user = utils.create_user(password="foo", is_verified=True)
|
||||
user = utils.create_user(password="foo")
|
||||
user.st.is_verified = True
|
||||
user.st.save()
|
||||
|
||||
form_data = {'email': user.email,
|
||||
'password': "foo"}
|
||||
@ -654,8 +657,11 @@ class UserFormTest(TestCase):
|
||||
edit user profile
|
||||
"""
|
||||
form_data = {'first_name': 'foo', 'last_name': 'bar',
|
||||
'location': 'spirit', 'timezone': self.user.timezone}
|
||||
form = UserProfileForm(data=form_data, instance=self.user)
|
||||
'location': 'spirit', 'timezone': self.user.st.timezone}
|
||||
form = UserProfileForm(data=form_data, instance=self.user.st)
|
||||
self.assertEqual(form.is_valid(), True)
|
||||
|
||||
form = UserForm(data=form_data, instance=self.user)
|
||||
self.assertEqual(form.is_valid(), True)
|
||||
|
||||
def test_email_change(self):
|
||||
@ -718,15 +724,17 @@ class UserModelTest(TestCase):
|
||||
is_superuser should always be is_administrator and is_moderator
|
||||
test model
|
||||
"""
|
||||
user = UserModel(is_superuser=True)
|
||||
user = User(is_superuser=True)
|
||||
user.save()
|
||||
self.assertTrue(user.is_administrator)
|
||||
self.assertTrue(user.is_moderator)
|
||||
self.assertTrue(user.st.is_administrator)
|
||||
self.assertTrue(user.st.is_moderator)
|
||||
|
||||
def test_user_administrator(self):
|
||||
"""
|
||||
is_administrator should always be is_moderator
|
||||
"""
|
||||
user = UserModel(is_administrator=True)
|
||||
user = User()
|
||||
user.save()
|
||||
self.assertTrue(user.is_moderator)
|
||||
user.st.is_administrator = True
|
||||
user.st.save()
|
||||
self.assertTrue(user.st.is_moderator)
|
||||
|
@ -12,7 +12,7 @@ from django.test.utils import override_settings
|
||||
from django.template import Template, Context
|
||||
from django.utils import translation
|
||||
from django.utils import timezone
|
||||
from django.contrib.auth.models import AnonymousUser, User
|
||||
from django.contrib.auth.models import AnonymousUser
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.http import HttpResponse
|
||||
from django.conf import settings
|
||||
@ -22,6 +22,7 @@ from django.contrib import messages
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.timezone import utc
|
||||
from django.utils.http import urlunquote
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
from spirit.models.category import Category
|
||||
from spirit.utils.forms import NestedModelChoiceField
|
||||
@ -38,6 +39,9 @@ from spirit.templatetags.tags.utils.messages import render_messages
|
||||
from spirit.utils.markdown import Markdown, quotify
|
||||
|
||||
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class UtilsTests(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
@ -242,6 +246,10 @@ class UtilsTimezoneTests(TestCase):
|
||||
|
||||
class UtilsDecoratorsTests(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
cache.clear()
|
||||
self.user = test_utils.create_user()
|
||||
|
||||
def test_moderator_required(self):
|
||||
"""
|
||||
Tests the user is logged in and is also a moderator
|
||||
@ -255,11 +263,11 @@ class UtilsDecoratorsTests(TestCase):
|
||||
req.user = AnonymousUser()
|
||||
self.assertIsInstance(view(req), HttpResponseRedirect)
|
||||
|
||||
req.user = User()
|
||||
req.user.is_moderator = False
|
||||
req.user = self.user
|
||||
req.user.st.is_moderator = False
|
||||
self.assertRaises(PermissionDenied, view, req)
|
||||
|
||||
req.user.is_moderator = True
|
||||
req.user.st.is_moderator = True
|
||||
self.assertIsNone(view(req))
|
||||
|
||||
def test_administrator_required(self):
|
||||
@ -275,11 +283,11 @@ class UtilsDecoratorsTests(TestCase):
|
||||
req.user = AnonymousUser()
|
||||
self.assertIsInstance(view(req), HttpResponseRedirect)
|
||||
|
||||
req.user = User()
|
||||
req.user.is_administrator = False
|
||||
req.user = self.user
|
||||
req.user.st.is_administrator = False
|
||||
self.assertRaises(PermissionDenied, view, req)
|
||||
|
||||
req.user.is_administrator = True
|
||||
req.user.st.is_administrator = True
|
||||
self.assertIsNone(view(req))
|
||||
|
||||
|
||||
@ -287,7 +295,7 @@ class UtilsMarkdownTests(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
cache.clear()
|
||||
self.user = test_utils.create_user(username="nitely", slug="nitely")
|
||||
self.user = test_utils.create_user(username="nitely")
|
||||
self.user2 = test_utils.create_user(username="esteban")
|
||||
self.user3 = test_utils.create_user(username="áéíóú")
|
||||
|
||||
@ -302,9 +310,9 @@ class UtilsMarkdownTests(TestCase):
|
||||
'<a class="comment-mention" href="%s">@esteban</a>,'
|
||||
'<a class="comment-mention" href="%s">@\xe1\xe9\xed\xf3\xfa</a>, '
|
||||
'@fakeone</p>' %
|
||||
(self.user.get_absolute_url(),
|
||||
self.user2.get_absolute_url(),
|
||||
self.user3.get_absolute_url()))
|
||||
(self.user.st.get_absolute_url(),
|
||||
self.user2.st.get_absolute_url(),
|
||||
self.user3.st.get_absolute_url()))
|
||||
|
||||
@override_settings(ST_MENTIONS_PER_COMMENT=2)
|
||||
def test_markdown_mentions_limit(self):
|
||||
@ -463,7 +471,7 @@ class UtilsUserTests(TestCase):
|
||||
"""
|
||||
Validate if user can be activated
|
||||
"""
|
||||
self.user.is_verified = False
|
||||
self.user.st.is_verified = False
|
||||
|
||||
activation_token = UserActivationTokenGenerator()
|
||||
token = activation_token.generate(self.user)
|
||||
@ -471,7 +479,7 @@ class UtilsUserTests(TestCase):
|
||||
self.assertFalse(activation_token.is_valid(self.user, "bad token"))
|
||||
|
||||
# Invalid after verification
|
||||
self.user.is_verified = True
|
||||
self.user.st.is_verified = True
|
||||
self.assertFalse(activation_token.is_valid(self.user, token))
|
||||
|
||||
# Invalid for different user
|
||||
|
Loading…
Reference in New Issue
Block a user