Skip to content

Commit

Permalink
User Story #1242 Реструктуризация репозитория
Browse files Browse the repository at this point in the history
Изменение структуры каталогов репозитория.
  • Loading branch information
vintorez committed Apr 9, 2013
1 parent 4557407 commit 737f2d1
Show file tree
Hide file tree
Showing 527 changed files with 3,410 additions and 2,194 deletions.
11 changes: 8 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
*.pyc
*.db
local_settings.py
*~
exmo/settings.py
*.mo
*.egg
cache
/static
_build
.idea
*.swp

/env
/venv
/cache/*
/static/*
/media/*
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
68 changes: 68 additions & 0 deletions exmo/accounts/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# -*- coding: utf-8 -*-
# This file is part of EXMO2010 software.
# Copyright 2010, 2011 Al Nikolov
# Copyright 2010, 2011 non-profit partnership Institute of Information Freedom Development
# Copyright 2012, 2013 Foundation "Institute for Information Freedom Development"
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from django.contrib import admin
from django.db import models
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User

from exmo2010.models import UserProfile


UserAdmin.filter_horizontal = ('user_permissions', 'groups')


class UserProfileAdmin(admin.ModelAdmin):
search_fields = ('user__username', )
formfield_overrides = {
models.ManyToManyField: {
'widget': admin.widgets.FilteredSelectMultiple('',
is_stacked=False)
},
}

class Media:
css = {
"all": ("exmo2010/selector.css",)
}


class UserProfileInline(admin.StackedInline):
model = UserProfile
fk_name = 'user'
max_num = 1
formfield_overrides = {
models.ManyToManyField: {
'widget': admin.widgets.FilteredSelectMultiple('',
is_stacked=False)
},
}

class Media:
css = {
"all": ("exmo2010/selector.css",)
}


class UserAdmin(UserAdmin):
inlines = [UserProfileInline, ]


admin.site.unregister(User)
admin.site.register(User, UserAdmin)
182 changes: 182 additions & 0 deletions exmo/accounts/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
# -*- coding: utf-8 -*-
# This file is part of EXMO2010 software.
# Copyright 2010, 2011 Al Nikolov
# Copyright 2010, 2011 non-profit partnership Institute of Information Freedom Development
# Copyright 2012, 2013 Foundation "Institute for Information Freedom Development"
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import string
import time
from annoying.decorators import autostrip

from django import forms
from django.core.exceptions import ObjectDoesNotExist
from django.utils.translation import ugettext as _

from exmo2010.models import Organization


COMMENT_NOTIFICATION_CHOICES = (
(0, _('do not send')),
(1, _('one email per one comment')),
(2, _('one email for all in time interval')),
)

DIGEST_INTERVALS = (
(1, _("once in 1 hour")),
(3, _("once in 3 hours")),
(6, _("once in 6 hours")),
(12, _("once in 12 hours")),
(24, _("once in 24 hours")),
)

PASSWORD_ALLOWED_CHARS = string.ascii_letters + string.digits

SCORE_CHANGE_NOTIFICATION_CHOICES = (
(0, _('do not send')),
(1, _('one email per one change')),
(2, _('one email for all in time interval')),
)


@autostrip
class SettingsPersInfForm(forms.Form):
"""
Форма для блока "Личная информация" страницы настроек пользователя.
Версия для пользователя, не являющегося представителем организации.
"""
# required=False у email потому, что не предполагается сабмит этого поля
# из-за кастомного виджета.
first_name = forms.CharField(label=_("First name"),
widget=forms.TextInput(attrs={"maxlength": 14}),
required=False, max_length=14)
patronymic = forms.CharField(label=_("Patronymic"),
widget=forms.TextInput(attrs={"maxlength": 14}),
required=False, max_length=14)
last_name = forms.CharField(label=_("Last name"),
widget=forms.TextInput(attrs={"maxlength": 30}),
required=False, max_length=30)


@autostrip
class SettingsPersInfFormFull(SettingsPersInfForm):
"""
Форма для блока "Личная информация" страницы настроек пользователя.
Версия для пользователя, являющегося представителем организации.
"""
position = forms.CharField(label=_("Seat"),
widget=forms.TextInput(attrs={"maxlength": 48}),
required=False, max_length=48)
phone = forms.CharField(label=_("Phone"),
widget=forms.TextInput(attrs={"maxlength": 30}),
required=False, max_length=30)


@autostrip
class SettingsInvCodeForm(forms.Form):
"""
Форма для блока "Код приглашения" страницы настроек пользователя.
"""
invitation_code = forms.CharField(label=_("New code"),
widget=forms.TextInput(attrs={"maxlength": 6}),
max_length=6, min_length=6)

def clean_invitation_code(self):
invitation_code = self.cleaned_data.get("invitation_code")
try:
organization = Organization.objects.get(inv_code=invitation_code)
except ObjectDoesNotExist:
time.sleep(3) # Чтобы усложнить перебор.
raise forms.ValidationError("") # Текст ошибки не нужен.
else:
return invitation_code


class SettingsChPassForm(forms.Form):
"""
Форма для блока "Сменить пароль" страницы настроек пользователя.
"""
old_password = forms.CharField(label=_("Old password"),
widget=forms.PasswordInput(attrs={"maxlength": 24},
render_value=True), required=False)
new_password = forms.CharField(label=_("New password"),
widget=forms.TextInput(attrs={"maxlength": 24, "autocomplete": "off"}),
required=False)

def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super(SettingsChPassForm, self).__init__(*args, **kwargs)

def clean_old_password(self):
if not self.user.check_password(self.cleaned_data.get("old_password")):
raise forms.ValidationError(_("Failed to change password: "
"submitted wrong current password"))

def clean_new_password(self):
"""Проверка пароля на наличие недопустимых символов."""
new_password = self.cleaned_data.get('new_password')
if not new_password:
# Ставим заведомо недопустимый символ.
new_password = "@"
for char in new_password: # Проверять на наличие пароля необязательно.
if char not in PASSWORD_ALLOWED_CHARS:
raise forms.ValidationError(_("Failed to change password: "
"it can contain only latin "
"characters (A-Z, a-z) and "
"digits (0-9)"))
return new_password


class SettingsSendNotifForm(forms.Form):
"""
Форма для блока "Рассылка уведомлений" страницы настроек пользователя.
Версия для пользователя, не являющегося представителем организации.
"""
# Скрытое поле, нужное для того, чтобы однозначно идентифицировать форму,
# т.к. при снятой галке у subscribe, django вообще не кладет
# это поле (subscribe) в POST.
snf = forms.IntegerField(widget=forms.HiddenInput, required=False)
subscribe = forms.BooleanField(label="",
help_text=_("Subscribe to news e-mail notification"), required=False)


class SettingsSendNotifFormFull(SettingsSendNotifForm):
"""
Форма для блока "Рассылка уведомлений" страницы настроек пользователя.
Версия для пользователя, являющегося представителем организации.
"""
comment_notification_type = forms.ChoiceField(
choices=COMMENT_NOTIFICATION_CHOICES,
label=_('Comment notification'))
comment_notification_digest = forms.ChoiceField(choices=DIGEST_INTERVALS,
required=False)
score_notification_type = forms.ChoiceField(
choices=SCORE_CHANGE_NOTIFICATION_CHOICES,
label=_('Score change notification'))
score_notification_digest = forms.ChoiceField(choices=DIGEST_INTERVALS,
required=False)
notify_on_my_comments = forms.BooleanField(label="",
help_text=_("Send to me my comments"), required=False)
notify_on_all_comments = forms.BooleanField(label="",
help_text=_("Send whole comment thread"), required=False)

def __init__(self, *args, **kwargs):
super(SettingsSendNotifFormFull, self).__init__(*args, **kwargs)
File renamed without changes.
27 changes: 20 additions & 7 deletions exmo/exmo2010/view/user.py → exmo/accounts/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,25 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from django.contrib import messages
from django.contrib.auth.models import User, Group
from django.contrib.auth.models import Group
from django.core.urlresolvers import reverse
from django.http import HttpResponseForbidden, HttpResponseRedirect, Http404
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.utils.translation import ugettext as _
from django.views.decorators.csrf import csrf_protect
from admin_tools.dashboard.models import DashboardPreferences

from exmo2010.forms import SettingsInvCodeForm, SettingsChPassForm, SettingsPersInfForm
from exmo2010.forms import SettingsPersInfFormFull, SettingsSendNotifForm, SettingsSendNotifFormFull
from accounts.forms import *
from bread_crumbs.views import breadcrumbs
from exmo2010.models import Organization, UserProfile
from exmo2010.view.breadcrumbs import breadcrumbs


def settings(request):
"""Страница настроек пользователя."""
"""
Страница настроек пользователя.
"""
if not request.user.is_authenticated():
raise Http404

Expand Down Expand Up @@ -228,7 +231,7 @@ def settings(request):
breadcrumbs(request, crumbs)
title = _('Settings')

return render_to_response('exmo2010/user_settings.html',
return render_to_response('user_settings.html',
{"email": user.email,
"current_title": title,
"is_organization": is_organization, "is_internal": is_internal,
Expand All @@ -243,7 +246,6 @@ def settings(request):
context_instance=RequestContext(request))


from admin_tools.dashboard.models import DashboardPreferences
@csrf_protect
def user_reset_dashboard(request):
if request.method == 'POST':
Expand All @@ -258,3 +260,14 @@ def user_reset_dashboard(request):
return HttpResponseRedirect(reverse('exmo2010:user_profile'))
else:
return HttpResponseForbidden(_('Forbidden'))


# TODO: не используется?
def create_profile(sender, instance, created, **kwargs):
"""
post-save для модели User для создания профиля.
"""
if created:
profile = UserProfile(user=instance)
profile.save()
File renamed without changes.
8 changes: 5 additions & 3 deletions exmo/exmo2010/auth/backends.py → exmo/auth/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,16 @@
Модуль с классом пригодным для использования как authentication backend
"""

from exmo2010.auth.helpers import check_permission
from auth.helpers import check_permission


class ObjectPermBackend(object):
"""
Это бекенд для получения прав для объекта
Сделан по описанию https://docs.djangoproject.com/en/1.3/topics/auth/#handling-object-permissions
Имеет один активный метод -- has_perm который принимает и обрабатывает obj -- объект для которого проверяет привелегия
По сути django-врапер для check_permission
Имеет один активный метод -- has_perm который принимает и обрабатывает obj -- объект для которого
проверяет привелегия. По сути django-врапер для check_permission.
"""
supports_object_permissions = True
supports_anonymous_user = True
Expand Down
Loading

0 comments on commit 737f2d1

Please sign in to comment.