diff --git a/boards/abstracts/settingsmanager.py b/boards/abstracts/settingsmanager.py new file mode 100644 --- /dev/null +++ b/boards/abstracts/settingsmanager.py @@ -0,0 +1,106 @@ +from django.shortcuts import get_object_or_404 +from boards.models import Tag + +__author__ = 'neko259' + +SESSION_SETTING = 'setting' + +PERMISSION_MODERATE = 'moderator' + +SETTING_THEME = 'theme' +SETTING_FAVORITE_TAGS = 'favorite_tags' +SETTING_HIDDEN_TAGS = 'hidden_tags' +SETTING_PERMISSIONS = 'permissions' + +DEFAULT_THEME = 'md' + + +class SettingsManager: + + def __init__(self, session): + self.session = session + + def get_theme(self): + theme = self.get_setting(SETTING_THEME) + if not theme: + theme = DEFAULT_THEME + self.set_setting(SETTING_THEME, theme) + + return theme + + def set_theme(self, theme): + self.set_setting(SETTING_THEME, theme) + + def has_permission(self, permission): + permissions = self.get_setting(SETTING_PERMISSIONS) + if permissions: + return permission in permissions + else: + return False + + def get_setting(self, setting): + if setting in self.session: + return self.session[setting] + else: + return None + + def set_setting(self, setting, value): + self.session[setting] = value + + def add_permission(self, permission): + permissions = self.get_setting(SETTING_PERMISSIONS) + if not permissions: + permissions = [permission] + else: + permissions += permission + self.set_setting(SETTING_PERMISSIONS, permissions) + + def get_fav_tags(self): + tag_names = self.get_setting(SETTING_FAVORITE_TAGS) + tags = [] + if tag_names: + for tag_name in tag_names: + tag = get_object_or_404(Tag, name=tag_name) + tags.append(tag) + + return tags + + def add_fav_tag(self, tag): + tags = self.get_setting(SETTING_FAVORITE_TAGS) + if not tags: + tags = [tag.name] + else: + if not tag.name in tags: + tags.append(tag.name) + self.set_setting(SETTING_FAVORITE_TAGS, tags) + + def del_fav_tag(self, tag): + tags = self.get_setting(SETTING_FAVORITE_TAGS) + if tag.name in tags: + tags.remove(tag.name) + self.set_setting(SETTING_FAVORITE_TAGS, tags) + + def get_hidden_tags(self): + tag_names = self.get_setting(SETTING_HIDDEN_TAGS) + tags = [] + if tag_names: + for tag_name in tag_names: + tag = get_object_or_404(Tag, name=tag_name) + tags.append(tag) + + return tags + + def add_hidden_tag(self, tag): + tags = self.get_setting(SETTING_HIDDEN_TAGS) + if not tags: + tags = [tag.name] + else: + if not tag.name in tags: + tags.append(tag.name) + self.set_setting(SETTING_HIDDEN_TAGS, tags) + + def del_hidden_tag(self, tag): + tags = self.get_setting(SETTING_HIDDEN_TAGS) + if tag.name in tags: + tags.remove(tag.name) + self.set_setting(SETTING_HIDDEN_TAGS, tags) diff --git a/boards/admin.py b/boards/admin.py --- a/boards/admin.py +++ b/boards/admin.py @@ -1,5 +1,5 @@ from django.contrib import admin -from boards.models import Post, Tag, User, Ban, Thread +from boards.models import Post, Tag, Ban, Thread class PostAdmin(admin.ModelAdmin): @@ -15,12 +15,6 @@ class TagAdmin(admin.ModelAdmin): list_filter = ('linked',) -class UserAdmin(admin.ModelAdmin): - - list_display = ('user_id', 'rank') - search_fields = ('user_id',) - - class ThreadAdmin(admin.ModelAdmin): def title(self, obj): @@ -35,6 +29,5 @@ class ThreadAdmin(admin.ModelAdmin): admin.site.register(Post, PostAdmin) admin.site.register(Tag, TagAdmin) -admin.site.register(User, UserAdmin) admin.site.register(Ban) admin.site.register(Thread, ThreadAdmin) diff --git a/boards/context_processors.py b/boards/context_processors.py --- a/boards/context_processors.py +++ b/boards/context_processors.py @@ -1,8 +1,10 @@ +from boards.abstracts.settingsmanager import SettingsManager, \ + PERMISSION_MODERATE + __author__ = 'neko259' -from boards import utils, settings +from boards import settings from boards.models import Post -from boards.models.post import SETTING_MODERATE CONTEXT_SITE_NAME = 'site_name' CONTEXT_VERSION = 'version' @@ -17,21 +19,17 @@ CONTEXT_USER = 'user' def user_and_ui_processor(request): context = {} - user = utils.get_user(request) - context[CONTEXT_USER] = user - context[CONTEXT_TAGS] = user.fav_tags.all() context[CONTEXT_PPD] = float(Post.objects.get_posts_per_day()) - theme = utils.get_theme(request, user) + settings_manager = SettingsManager(request.session) + context[CONTEXT_TAGS] = settings_manager.get_fav_tags() + theme = settings_manager.get_theme() context[CONTEXT_THEME] = theme context[CONTEXT_THEME_CSS] = 'css/' + theme + '/base_page.css' # This shows the moderator panel - moderate = user.get_setting(SETTING_MODERATE) - if moderate == 'True': - context[CONTEXT_MODERATOR] = user.is_moderator() - else: - context[CONTEXT_MODERATOR] = False + moderate = settings_manager.has_permission(PERMISSION_MODERATE) + context[CONTEXT_MODERATOR] = moderate context[CONTEXT_VERSION] = settings.VERSION context[CONTEXT_SITE_NAME] = settings.SITE_NAME diff --git a/boards/forms.py b/boards/forms.py --- a/boards/forms.py +++ b/boards/forms.py @@ -9,7 +9,7 @@ from django.utils.translation import uge from boards.mdx_neboard import formatters from boards.models.post import TITLE_MAX_LENGTH -from boards.models import User, PostImage +from boards.models import PostImage from neboard import settings from boards import utils import boards.settings as board_settings @@ -187,11 +187,7 @@ class PostForm(NeboardForm): if not 'user_id' in self.session: return - user = User.objects.get(id=self.session['user_id']) - if user.is_veteran(): - posting_delay = VETERAN_POSTING_DELAY - else: - posting_delay = settings.POSTING_DELAY + posting_delay = settings.POSTING_DELAY if board_settings.LIMIT_POSTING_SPEED and LAST_POST_TIME in \ self.session: @@ -288,51 +284,6 @@ class ModeratorSettingsForm(SettingsForm 'panel')) -class LoginForm(NeboardForm): - - user_id = forms.CharField() - - session = None - - def clean_user_id(self): - user_id = self.cleaned_data['user_id'] - if user_id: - users = User.objects.filter(user_id=user_id) - if len(users) == 0: - raise forms.ValidationError(_('No such user found')) - - return user_id - - def _validate_login_speed(self): - can_post = True - - if LAST_LOGIN_TIME in self.session: - now = time.time() - last_login_time = self.session[LAST_LOGIN_TIME] - - current_delay = int(now - last_login_time) - - if current_delay < board_settings.LOGIN_TIMEOUT: - error_message = _('Wait %s minutes after last login') % str( - (board_settings.LOGIN_TIMEOUT - current_delay) / 60) - self._errors['user_id'] = self.error_class([error_message]) - - can_post = False - - if can_post: - self.session[LAST_LOGIN_TIME] = time.time() - - def clean(self): - if not self.session: - raise forms.ValidationError('Humans have sessions') - - self._validate_login_speed() - - cleaned_data = super(LoginForm, self).clean() - - return cleaned_data - - class AddTagForm(NeboardForm): tag = forms.CharField(max_length=TAG_MAX_LENGTH, label=LABEL_TAG) diff --git a/boards/management/commands/cleanusers.py b/boards/management/commands/cleanusers.py deleted file mode 100644 --- a/boards/management/commands/cleanusers.py +++ /dev/null @@ -1,29 +0,0 @@ -from datetime import datetime, timedelta -from django.core.management import BaseCommand -from django.db import transaction -from django.db.models import Count -from boards.models import User, Post - -__author__ = 'neko259' - -OLD_USER_AGE_DAYS = 90 - - -class Command(BaseCommand): - help = 'Removes empty users (that don\'t have posts or tags' - - @transaction.atomic - def handle(self, *args, **options): - old_registration_date = datetime.now().date() - timedelta( - OLD_USER_AGE_DAYS) - - old_users = User.objects.annotate(tags_count=Count('fav_tags')).filter( - tags_count=0).filter(registration_time__lt=old_registration_date) - deleted_users = 0 - for user in old_users: - if not Post.objects.filter(user=user).exists(): - self.stdout.write('Deleting user %s' % user.user_id) - user.delete() - deleted_users += 1 - - self.stdout.write('Deleted %d users' % deleted_users) \ No newline at end of file diff --git a/boards/management/commands/enforce_privacy.py b/boards/management/commands/enforce_privacy.py --- a/boards/management/commands/enforce_privacy.py +++ b/boards/management/commands/enforce_privacy.py @@ -13,4 +13,4 @@ class Command(BaseCommand): @transaction.atomic def handle(self, *args, **options): - Post.objects.all().update(poster_ip=NO_IP, user=None) \ No newline at end of file + Post.objects.all().update(poster_ip=NO_IP) \ No newline at end of file diff --git a/boards/migrations/0029_auto__del_setting__del_user__del_field_post_user.py b/boards/migrations/0029_auto__del_setting__del_user__del_field_post_user.py new file mode 100644 --- /dev/null +++ b/boards/migrations/0029_auto__del_setting__del_user__del_field_post_user.py @@ -0,0 +1,146 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Deleting model 'Setting' + db.delete_table(u'boards_setting') + + # Deleting model 'User' + db.delete_table(u'boards_user') + + # Removing M2M table for field hidden_threads on 'User' + db.delete_table(db.shorten_name(u'boards_user_hidden_threads')) + + # Removing M2M table for field fav_threads on 'User' + db.delete_table(db.shorten_name(u'boards_user_fav_threads')) + + # Removing M2M table for field fav_tags on 'User' + db.delete_table(db.shorten_name(u'boards_user_fav_tags')) + + # Removing M2M table for field hidden_tags on 'User' + db.delete_table(db.shorten_name(u'boards_user_hidden_tags')) + + # Deleting field 'Post.user' + db.delete_column(u'boards_post', 'user_id') + + + def backwards(self, orm): + # Adding model 'Setting' + db.create_table(u'boards_setting', ( + ('user', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['boards.User'])), + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('value', self.gf('django.db.models.fields.CharField')(max_length=50)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=50)), + )) + db.send_create_signal('boards', ['Setting']) + + # Adding model 'User' + db.create_table(u'boards_user', ( + ('registration_time', self.gf('django.db.models.fields.DateTimeField')()), + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('user_id', self.gf('django.db.models.fields.CharField')(max_length=50)), + ('rank', self.gf('django.db.models.fields.IntegerField')()), + )) + db.send_create_signal('boards', ['User']) + + # Adding M2M table for field hidden_threads on 'User' + m2m_table_name = db.shorten_name(u'boards_user_hidden_threads') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('user', models.ForeignKey(orm['boards.user'], null=False)), + ('post', models.ForeignKey(orm['boards.post'], null=False)) + )) + db.create_unique(m2m_table_name, ['user_id', 'post_id']) + + # Adding M2M table for field fav_threads on 'User' + m2m_table_name = db.shorten_name(u'boards_user_fav_threads') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('user', models.ForeignKey(orm['boards.user'], null=False)), + ('post', models.ForeignKey(orm['boards.post'], null=False)) + )) + db.create_unique(m2m_table_name, ['user_id', 'post_id']) + + # Adding M2M table for field fav_tags on 'User' + m2m_table_name = db.shorten_name(u'boards_user_fav_tags') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('user', models.ForeignKey(orm['boards.user'], null=False)), + ('tag', models.ForeignKey(orm['boards.tag'], null=False)) + )) + db.create_unique(m2m_table_name, ['user_id', 'tag_id']) + + # Adding M2M table for field hidden_tags on 'User' + m2m_table_name = db.shorten_name(u'boards_user_hidden_tags') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('user', models.ForeignKey(orm['boards.user'], null=False)), + ('tag', models.ForeignKey(orm['boards.tag'], null=False)) + )) + db.create_unique(m2m_table_name, ['user_id', 'tag_id']) + + # Adding field 'Post.user' + db.add_column(u'boards_post', 'user', + self.gf('django.db.models.fields.related.ForeignKey')(default=None, to=orm['boards.User'], null=True), + keep_default=False) + + + models = { + 'boards.ban': { + 'Meta': {'object_name': 'Ban'}, + 'can_read': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}), + 'reason': ('django.db.models.fields.CharField', [], {'default': "'Auto'", 'max_length': '200'}) + }, + 'boards.post': { + 'Meta': {'ordering': "('id',)", 'object_name': 'Post'}, + '_text_rendered': ('django.db.models.fields.TextField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'images': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'ip+'", 'to': "orm['boards.PostImage']", 'blank': 'True', 'symmetrical': 'False', 'null': 'True', 'db_index': 'True'}), + 'last_edit_time': ('django.db.models.fields.DateTimeField', [], {}), + 'poster_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}), + 'poster_user_agent': ('django.db.models.fields.TextField', [], {}), + 'pub_time': ('django.db.models.fields.DateTimeField', [], {}), + 'referenced_posts': ('django.db.models.fields.related.ManyToManyField', [], {'related_name': "'rfp+'", 'to': "orm['boards.Post']", 'blank': 'True', 'symmetrical': 'False', 'null': 'True', 'db_index': 'True'}), + 'refmap': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}), + 'text': ('markupfield.fields.MarkupField', [], {'rendered_field': 'True'}), + 'text_markup_type': ('django.db.models.fields.CharField', [], {'default': "'markdown'", 'max_length': '30'}), + 'thread_new': ('django.db.models.fields.related.ForeignKey', [], {'default': 'None', 'to': "orm['boards.Thread']", 'null': 'True'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '200'}) + }, + 'boards.postimage': { + 'Meta': {'ordering': "('id',)", 'object_name': 'PostImage'}, + 'hash': ('django.db.models.fields.CharField', [], {'max_length': '36'}), + 'height': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'image': ('boards.thumbs.ImageWithThumbsField', [], {'max_length': '100', 'blank': 'True'}), + 'pre_height': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'pre_width': ('django.db.models.fields.IntegerField', [], {'default': '0'}), + 'width': ('django.db.models.fields.IntegerField', [], {'default': '0'}) + }, + 'boards.tag': { + 'Meta': {'ordering': "('name',)", 'object_name': 'Tag'}, + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'linked': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['boards.Tag']", 'null': 'True', 'blank': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'db_index': 'True'}), + 'threads': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'tag+'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['boards.Thread']"}) + }, + 'boards.thread': { + 'Meta': {'object_name': 'Thread'}, + 'archived': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'bump_time': ('django.db.models.fields.DateTimeField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'last_edit_time': ('django.db.models.fields.DateTimeField', [], {}), + 'replies': ('django.db.models.fields.related.ManyToManyField', [], {'blank': 'True', 'related_name': "'tre+'", 'null': 'True', 'symmetrical': 'False', 'to': "orm['boards.Post']"}), + 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['boards.Tag']", 'symmetrical': 'False'}) + } + } + + complete_apps = ['boards'] \ No newline at end of file diff --git a/boards/models/__init__.py b/boards/models/__init__.py --- a/boards/models/__init__.py +++ b/boards/models/__init__.py @@ -5,5 +5,3 @@ from boards.models.thread import Thread from boards.models.post import Post from boards.models.tag import Tag from boards.models.user import Ban -from boards.models.user import Setting -from boards.models.user import User diff --git a/boards/models/post.py b/boards/models/post.py --- a/boards/models/post.py +++ b/boards/models/post.py @@ -45,8 +45,8 @@ logger = logging.getLogger(__name__) class PostManager(models.Manager): - def create_post(self, title, text, image=None, thread=None, - ip=NO_IP, tags=None, user=None): + def create_post(self, title, text, image=None, thread=None, ip=NO_IP, + tags=None): """ Creates new post """ @@ -69,8 +69,7 @@ class PostManager(models.Manager): poster_ip=ip, poster_user_agent=UNKNOWN_UA, # TODO Get UA at # last! - last_edit_time=posting_time, - user=user) + last_edit_time=posting_time) if image: post_image = PostImage.objects.create(image=image) @@ -196,7 +195,6 @@ class Post(models.Model, Viewable): thread_new = models.ForeignKey('Thread', null=True, default=None, db_index=True) last_edit_time = models.DateTimeField() - user = models.ForeignKey('User', null=True, default=None, db_index=True) referenced_posts = models.ManyToManyField('Post', symmetrical=False, null=True, diff --git a/boards/models/user.py b/boards/models/user.py --- a/boards/models/user.py +++ b/boards/models/user.py @@ -1,122 +1,10 @@ from django.db import models -from django.db.models import Count -from boards import settings -from boards.models import Post -from django.core.cache import cache __author__ = 'neko259' -RANK_ADMIN = 0 -RANK_MODERATOR = 10 -RANK_USER = 100 - BAN_REASON_AUTO = 'Auto' BAN_REASON_MAX_LENGTH = 200 -VETERAN_POSTS = 1000 - - -class User(models.Model): - - class Meta: - app_label = 'boards' - - user_id = models.CharField(max_length=50) - rank = models.IntegerField() - - registration_time = models.DateTimeField() - - fav_tags = models.ManyToManyField('Tag', null=True, blank=True) - fav_threads = models.ManyToManyField(Post, related_name='+', null=True, - blank=True) - - hidden_tags = models.ManyToManyField('Tag', null=True, blank=True, - related_name='ht+') - hidden_threads = models.ManyToManyField('Post', null=True, blank=True, - related_name='hth+') - - def save_setting(self, name, value): - setting, created = Setting.objects.get_or_create(name=name, user=self) - setting.value = str(value) - setting.save() - - return setting - - def get_setting(self, name): - if Setting.objects.filter(name=name, user=self).exists(): - setting = Setting.objects.get(name=name, user=self) - setting_value = setting.value - else: - setting_value = None - - return setting_value - - def is_moderator(self): - return RANK_MODERATOR >= self.rank - - def get_sorted_fav_tags(self): - cache_key = self._get_tag_cache_key() - fav_tags = cache.get(cache_key) - if fav_tags: - return fav_tags - - tags = self.fav_tags.annotate(Count('threads')) \ - .filter(threads__count__gt=0).order_by('name') - - if tags: - cache.set(cache_key, tags) - - return tags - - def get_post_count(self): - return Post.objects.filter(user=self).count() - - def __unicode__(self): - return self.user_id + '(' + str(self.rank) + ')' - - def get_last_access_time(self): - """ - Gets user's last post time. - """ - - posts = Post.objects.filter(user=self) - if posts.exists() > 0: - return posts.latest('pub_time').pub_time - - def add_tag(self, tag): - self.fav_tags.add(tag) - cache.delete(self._get_tag_cache_key()) - - def remove_tag(self, tag): - self.fav_tags.remove(tag) - cache.delete(self._get_tag_cache_key()) - - def hide_tag(self, tag): - self.hidden_tags.add(tag) - - def unhide_tag(self, tag): - self.hidden_tags.remove(tag) - - def is_veteran(self): - """ - Returns if a user is old (veteran). - """ - - return self.get_post_count() >= VETERAN_POSTS - - def _get_tag_cache_key(self): - return self.user_id + '_tags' - - -class Setting(models.Model): - - class Meta: - app_label = 'boards' - - name = models.CharField(max_length=50) - value = models.CharField(max_length=50) - user = models.ForeignKey(User) - class Ban(models.Model): diff --git a/boards/templates/boards/base.html b/boards/templates/boards/base.html --- a/boards/templates/boards/base.html +++ b/boards/templates/boards/base.html @@ -46,7 +46,6 @@