def modify_karma(request): """Add a Karma note to a user profile.""" try: profile_pk = int(request.POST['profile_pk']) except (KeyError, ValueError): raise Http404 profile = get_object_or_404(Profile, pk=profile_pk) if profile.is_private(): raise PermissionDenied note = KarmaNote( user=profile.user, moderator=request.user, note=request.POST.get('note', '').strip()) try: note.karma = int(request.POST['karma']) except (KeyError, ValueError): note.karma = 0 try: if not note.note: raise ValueError('note cannot be empty') elif note.karma > 100 or note.karma < -100: raise ValueError('Max karma amount has to be between -100 and 100, you entered {}'.format(note.karma)) else: note.save() profile.karma += note.karma profile.save() except ValueError as e: logging.getLogger(__name__).warn('ValueError: modifying karma failed because {}'.format(e)) return redirect(reverse('member-detail', args=[profile.user.username]))
def modify_karma(request): """ Add a Karma note to the user profile """ if not request.user.has_perm("member.change_profile"): raise PermissionDenied try: profile_pk = request.POST["profile_pk"] except (KeyError, ValueError): raise Http404 profile = get_object_or_404(Profile, pk=profile_pk) if profile.is_private(): raise PermissionDenied note = KarmaNote() note.user = profile.user note.staff = request.user note.comment = request.POST["warning"] try: note.value = int(request.POST["points"]) except (KeyError, ValueError): note.value = 0 note.save() profile.karma += note.value profile.save() return redirect(reverse("member-detail", args=[profile.user.username]))
def update_profile(self, profile, form): profile.show_email = "show_email" in form.cleaned_data.get("options") new_username = form.cleaned_data.get("username") previous_username = form.cleaned_data.get("previous_username") new_email = form.cleaned_data.get("email") previous_email = form.cleaned_data.get("previous_email") if new_username and new_username != previous_username: # Add a karma message for the staff bot = get_object_or_404( User, username=settings.ZDS_APP["member"]["bot_account"]) KarmaNote( user=profile.user, moderator=bot, note=_("{} s'est renommé {}").format(profile.user.username, new_username), karma=0, ).save() # Change the username profile.user.username = new_username # update skeleton profile.username_skeleton = Profile.find_username_skeleton( new_username) if new_email and new_email != previous_email: profile.user.email = new_email # Create an alert for the staff if it's a new provider provider = provider = new_email.split("@")[-1].lower() if (not NewEmailProvider.objects.filter( provider=provider).exists() and not User.objects.filter( email__iendswith=f"@{provider}").exclude( pk=profile.user.pk).exists()): NewEmailProvider.objects.create(user=profile.user, provider=provider, use=EMAIL_EDIT)
def modify_karma(request): """Add a Karma note to a user profile.""" try: profile_pk = int(request.POST['profile_pk']) except (KeyError, ValueError): raise Http404 profile = get_object_or_404(Profile, pk=profile_pk) if profile.is_private(): raise PermissionDenied note = KarmaNote( user=profile.user, moderator=request.user, note=request.POST.get('note', '').strip()) try: note.karma = int(request.POST['karma']) except (KeyError, ValueError): note.karma = 0 try: if not note.note: raise ValueError('note cannot be empty') elif note.karma > 100 or note.karma < -100: raise ValueError('Max karma amount has to be between -100 and 100, you entered {}'.format(note.karma)) else: note.save() profile.karma += note.karma profile.save() except ValueError as e: logging.getLogger('zds.member').warn('ValueError: modifying karma failed because {}'.format(e)) return redirect(reverse('member-detail', args=[profile.user.username]))
def test_moderation_history(self): user = ProfileFactory().user ban = Ban( user=user, moderator=self.staff, type="Lecture Seule Temporaire", note="Test de LS", pubdate=datetime.now(), ) ban.save() note = KarmaNote( user=user, moderator=self.staff, karma=5, note="Test de karma", pubdate=datetime.now(), ) note.save() # staff rights are required to view the history, check that self.client.logout() self.client.force_login(user) result = self.client.get(user.profile.get_absolute_url(), follow=False) self.assertNotContains(result, "Historique de modération") self.client.logout() self.client.force_login(self.staff) result = self.client.get(user.profile.get_absolute_url(), follow=False) self.assertContains(result, "Historique de modération") # check that the note and the sanction are in the context self.assertIn(ban, result.context["actions"]) self.assertIn(note, result.context["actions"]) # and are displayed self.assertContains(result, "Test de LS") self.assertContains(result, "Test de karma")
def update_profile(self, profile, form): if form.data['username']: # Add a karma message for the staff bot = get_object_or_404(User, username=settings.ZDS_APP['member']['bot_account']) KarmaNote(user=profile.user, staff=bot, comment=_(u"{} s'est renommé {}").format(profile.user.username, form.data['username']), value=0).save() # Change the pseudo profile.user.username = form.data['username'] if form.data['email']: if form.data['email'].strip() != '': profile.user.email = form.data['email']
def modify_karma(request): """ Add a Karma note to the user profile """ if not request.user.has_perm("member.change_profile"): raise PermissionDenied try: profile_pk = int(request.POST["profile_pk"]) except (KeyError, ValueError): raise Http404 profile = get_object_or_404(Profile, pk=profile_pk) if profile.is_private(): raise PermissionDenied note = KarmaNote() note.user = profile.user note.staff = request.user note.comment = request.POST.get("warning", "") try: note.value = int(request.POST["points"]) except (KeyError, ValueError): note.value = 0 try: if note.comment == "": raise ValueError("note.comment must not be empty") elif note.value > 100 or note.value < -100: raise ValueError( "note.value must be between -100 and 100 {} given".format( note.value)) else: note.save() profile.karma += note.value profile.save() except ValueError as e: logging.getLogger("zds.member").warn( "ValueError: modifying karma failed because {}".format(e)) return redirect(reverse("member-detail", args=[profile.user.username]))
def update_profile(self, profile, form): profile.show_email = 'show_email' in form.cleaned_data.get('options') new_username = form.cleaned_data.get('username') previous_username = form.cleaned_data.get('previous_username') new_email = form.cleaned_data.get('email') previous_email = form.cleaned_data.get('previous_email') if new_username and new_username != previous_username: # Add a karma message for the staff bot = get_object_or_404( User, username=settings.ZDS_APP['member']['bot_account']) KarmaNote(user=profile.user, moderator=bot, note=_(u"{} s'est renommé {}").format( profile.user.username, new_username), karma=0).save() # Change the pseudo profile.user.username = new_username if new_email and new_email != previous_email: profile.user.email = new_email
def update_profile(self, profile, form): profile.show_email = 'show_email' in form.cleaned_data.get('options') new_username = form.cleaned_data.get('username') previous_username = form.cleaned_data.get('previous_username') new_email = form.cleaned_data.get('email') previous_email = form.cleaned_data.get('previous_email') if new_username and new_username != previous_username: # Add a karma message for the staff bot = get_object_or_404(User, username=settings.ZDS_APP['member']['bot_account']) KarmaNote(user=profile.user, moderator=bot, note=_("{} s'est renommé {}").format(profile.user.username, new_username), karma=0).save() # Change the username profile.user.username = new_username if new_email and new_email != previous_email: profile.user.email = new_email # Create an alert for the staff if it's a new provider provider = provider = new_email.split('@')[-1].lower() if not NewEmailProvider.objects.filter(provider=provider).exists() \ and not User.objects.filter(email__iendswith='@{}'.format(provider)) \ .exclude(pk=profile.user.pk).exists(): NewEmailProvider.objects.create(user=profile.user, provider=provider, use=EMAIL_EDIT)
def modify_karma(request): """Add a Karma note to a user profile.""" try: profile_pk = int(request.POST["profile_pk"]) except (KeyError, ValueError): raise Http404 profile = get_object_or_404(Profile, pk=profile_pk) if profile.is_private(): raise PermissionDenied note = KarmaNote(user=profile.user, moderator=request.user, note=request.POST.get("note", "").strip()) try: note.karma = int(request.POST["karma"]) except (KeyError, ValueError): note.karma = 0 try: if not note.note: raise ValueError("note cannot be empty") elif note.karma > 100 or note.karma < -100: raise ValueError( f"Max karma amount has to be between -100 and 100, you entered {note.karma}" ) else: note.save() profile.karma += note.karma profile.save() except ValueError as e: logging.getLogger(__name__).warning( f"ValueError: modifying karma failed because {e}") return redirect(reverse("member-detail", args=[profile.user.username]))
def test_unregister(self): """ To test that unregistering user is working. """ # test not logged user can't unregister. self.client.logout() result = self.client.post(reverse("member-unregister"), follow=False) self.assertEqual(result.status_code, 302) # test logged user can unregister. user = ProfileFactory() self.client.force_login(user.user) result = self.client.post(reverse("member-unregister"), follow=False) self.assertEqual(result.status_code, 302) self.assertEqual(User.objects.filter(username=user.user.username).count(), 0) # Attach a user at tutorials, articles, topics and private topics. After that, # unregister this user and check that he is well removed in all contents. user = ProfileFactory() user2 = ProfileFactory() alone_gallery = GalleryFactory() UserGalleryFactory(gallery=alone_gallery, user=user.user) shared_gallery = GalleryFactory() UserGalleryFactory(gallery=shared_gallery, user=user.user) UserGalleryFactory(gallery=shared_gallery, user=user2.user) # first case : a published tutorial with only one author published_tutorial_alone = PublishedContentFactory(type="TUTORIAL") published_tutorial_alone.authors.add(user.user) published_tutorial_alone.save() # second case : a published tutorial with two authors published_tutorial_2 = PublishedContentFactory(type="TUTORIAL") published_tutorial_2.authors.add(user.user) published_tutorial_2.authors.add(user2.user) published_tutorial_2.save() # third case : a private tutorial with only one author writing_tutorial_alone = PublishableContentFactory(type="TUTORIAL") writing_tutorial_alone.authors.add(user.user) writing_tutorial_alone.save() writing_tutorial_alone_galler_path = writing_tutorial_alone.gallery.get_gallery_path() # fourth case : a private tutorial with at least two authors writing_tutorial_2 = PublishableContentFactory(type="TUTORIAL") writing_tutorial_2.authors.add(user.user) writing_tutorial_2.authors.add(user2.user) writing_tutorial_2.save() self.client.force_login(self.staff) # same thing for articles published_article_alone = PublishedContentFactory(type="ARTICLE") published_article_alone.authors.add(user.user) published_article_alone.save() published_article_2 = PublishedContentFactory(type="ARTICLE") published_article_2.authors.add(user.user) published_article_2.authors.add(user2.user) published_article_2.save() writing_article_alone = PublishableContentFactory(type="ARTICLE") writing_article_alone.authors.add(user.user) writing_article_alone.save() writing_article_2 = PublishableContentFactory(type="ARTICLE") writing_article_2.authors.add(user.user) writing_article_2.authors.add(user2.user) writing_article_2.save() # beta content beta_forum = ForumFactory(category=ForumCategoryFactory()) beta_content = BetaContentFactory(author_list=[user.user], forum=beta_forum) beta_content_2 = BetaContentFactory(author_list=[user.user, user2.user], forum=beta_forum) # about posts and topics authored_topic = TopicFactory(author=user.user, forum=self.forum11, solved_by=user.user) answered_topic = TopicFactory(author=user2.user, forum=self.forum11) PostFactory(topic=answered_topic, author=user.user, position=2) edited_answer = PostFactory(topic=answered_topic, author=user.user, position=3) edited_answer.editor = user.user edited_answer.save() upvoted_answer = PostFactory(topic=answered_topic, author=user2.user, position=4) upvoted_answer.like += 1 upvoted_answer.save() CommentVote.objects.create(user=user.user, comment=upvoted_answer, positive=True) private_topic = PrivateTopicFactory(author=user.user) private_topic.participants.add(user2.user) private_topic.save() PrivatePostFactory(author=user.user, privatetopic=private_topic, position_in_topic=1) # add API key self.assertEqual(Application.objects.count(), 0) self.assertEqual(AccessToken.objects.count(), 0) api_application = Application() api_application.client_id = "foobar" api_application.user = user.user api_application.client_type = "confidential" api_application.authorization_grant_type = "password" api_application.client_secret = "42" api_application.save() token = AccessToken() token.user = user.user token.token = "r@d0m" token.application = api_application token.expires = datetime.now() token.save() self.assertEqual(Application.objects.count(), 1) self.assertEqual(AccessToken.objects.count(), 1) # add a karma note and a sanction with this user note = KarmaNote(moderator=user.user, user=user2.user, note="Good!", karma=5) note.save() ban = Ban(moderator=user.user, user=user2.user, type="Ban définitif", note="Test") ban.save() # login and unregister: self.client.force_login(user.user) result = self.client.post(reverse("member-unregister"), follow=False) self.assertEqual(result.status_code, 302) # check that the bot have taken authorship of tutorial: self.assertEqual(published_tutorial_alone.authors.count(), 1) self.assertEqual( published_tutorial_alone.authors.first().username, settings.ZDS_APP["member"]["external_account"] ) self.assertFalse(os.path.exists(writing_tutorial_alone_galler_path)) self.assertEqual(published_tutorial_2.authors.count(), 1) self.assertEqual( published_tutorial_2.authors.filter(username=settings.ZDS_APP["member"]["external_account"]).count(), 0 ) # check that published tutorials remain published and accessible self.assertIsNotNone(published_tutorial_2.public_version.get_prod_path()) self.assertTrue(os.path.exists(published_tutorial_2.public_version.get_prod_path())) self.assertIsNotNone(published_tutorial_alone.public_version.get_prod_path()) self.assertTrue(os.path.exists(published_tutorial_alone.public_version.get_prod_path())) self.assertEqual( self.client.get( reverse("tutorial:view", args=[published_tutorial_alone.pk, published_tutorial_alone.slug]), follow=False, ).status_code, 200, ) self.assertEqual( self.client.get( reverse("tutorial:view", args=[published_tutorial_2.pk, published_tutorial_2.slug]), follow=False ).status_code, 200, ) # test that published articles remain accessible self.assertTrue(os.path.exists(published_article_alone.public_version.get_prod_path())) self.assertEqual( self.client.get( reverse("article:view", args=[published_article_alone.pk, published_article_alone.slug]), follow=True ).status_code, 200, ) self.assertEqual( self.client.get( reverse("article:view", args=[published_article_2.pk, published_article_2.slug]), follow=True ).status_code, 200, ) # check that the tutorial for which the author was alone does not exists anymore self.assertEqual(PublishableContent.objects.filter(pk=writing_tutorial_alone.pk).count(), 0) self.assertFalse(os.path.exists(writing_tutorial_alone.get_repo_path())) # check that bot haven't take the authorship of the tuto with more than one author self.assertEqual(writing_tutorial_2.authors.count(), 1) self.assertEqual( writing_tutorial_2.authors.filter(username=settings.ZDS_APP["member"]["external_account"]).count(), 0 ) # authorship for the article for which user was the only author self.assertEqual(published_article_alone.authors.count(), 1) self.assertEqual( published_article_alone.authors.first().username, settings.ZDS_APP["member"]["external_account"] ) self.assertEqual(published_article_2.authors.count(), 1) self.assertEqual(PublishableContent.objects.filter(pk=writing_article_alone.pk).count(), 0) self.assertFalse(os.path.exists(writing_article_alone.get_repo_path())) # not bot if another author: self.assertEqual( published_article_2.authors.filter(username=settings.ZDS_APP["member"]["external_account"]).count(), 0 ) self.assertEqual(writing_article_2.authors.count(), 1) self.assertEqual( writing_article_2.authors.filter(username=settings.ZDS_APP["member"]["external_account"]).count(), 0 ) # topics, gallery and PMs: self.assertEqual(Topic.objects.filter(author__username=user.user.username).count(), 0) self.assertEqual(Topic.objects.filter(solved_by=user.user).count(), 0) self.assertEqual(Topic.objects.filter(solved_by=self.anonymous).count(), 1) self.assertEqual(Post.objects.filter(author__username=user.user.username).count(), 0) self.assertEqual(Post.objects.filter(editor__username=user.user.username).count(), 0) self.assertEqual(PrivatePost.objects.filter(author__username=user.user.username).count(), 0) self.assertEqual(PrivateTopic.objects.filter(author__username=user.user.username).count(), 0) self.assertIsNotNone(Topic.objects.get(pk=authored_topic.pk)) self.assertIsNotNone(PrivateTopic.objects.get(pk=private_topic.pk)) self.assertIsNotNone(Gallery.objects.get(pk=alone_gallery.pk)) self.assertEqual(alone_gallery.get_linked_users().count(), 1) self.assertEqual(shared_gallery.get_linked_users().count(), 1) self.assertEqual(UserGallery.objects.filter(user=user.user).count(), 0) self.assertEqual(CommentVote.objects.filter(user=user.user, positive=True).count(), 0) self.assertEqual(Post.objects.filter(pk=upvoted_answer.id).first().like, 0) # zep 12, published contents and beta self.assertIsNotNone(PublishedContent.objects.filter(content__pk=published_tutorial_alone.pk).first()) self.assertIsNotNone(PublishedContent.objects.filter(content__pk=published_tutorial_2.pk).first()) self.assertTrue(Topic.objects.get(pk=beta_content.beta_topic.pk).is_locked) self.assertFalse(Topic.objects.get(pk=beta_content_2.beta_topic.pk).is_locked) # check API self.assertEqual(Application.objects.count(), 0) self.assertEqual(AccessToken.objects.count(), 0) # check that the karma note and the sanction were kept self.assertTrue(KarmaNote.objects.filter(pk=note.pk).exists()) self.assertTrue(Ban.objects.filter(pk=ban.pk).exists())
def import_users(self): print("\nImporting users...") with self.connection.cursor(MySQLdb.cursors.DictCursor) as cursor: cursor.execute("SELECT COUNT(*) AS users_count FROM fluxbb_users") users_count = cursor.fetchone()['users_count'] print("{} users to be imported".format(users_count)) # TODO add location support into the new site cursor.execute('SELECT ' 'fluxbb_users.id AS user_id, ' 'fluxbb_users.username AS username, ' 'fluxbb_users.email AS email, ' 'fluxbb_users.url AS website, ' 'fluxbb_users.signature AS signature, ' 'fluxbb_users.show_sig AS show_signature, ' 'fluxbb_users.registered AS registration_date, ' 'fluxbb_users.last_visit AS last_visit, ' 'fluxbb_users.admin_note AS admin_note, ' 'fluxbb_users.title AS title, ' 'fluxbb_groups.g_title AS group_name, ' '(' ' SELECT fluxbb_users.username' ' FROM fluxbb_users' ' WHERE fluxbb_users.id = fluxbb_bans.ban_creator' ') AS ban_creator_username, ' 'fluxbb_bans.expire AS ban_expiration, ' 'fluxbb_bans.message AS ban_message ' 'FROM fluxbb_users ' 'INNER JOIN fluxbb_groups ON fluxbb_groups.g_id = fluxbb_users.group_id ' 'LEFT OUTER JOIN fluxbb_bans ON fluxbb_bans.username = fluxbb_users.username ' 'ORDER BY fluxbb_users.id') imported = 0 for row in cursor.fetchall(): if self.decode(row['username']) is 'Guest': continue user = self.create_user(self.decode(row['username'])) profile = user.profile # User data user.email = self.decode(row['email']) user.date_joined = datetime.datetime.fromtimestamp(row['registration_date']) user.last_login = datetime.datetime.fromtimestamp(row['last_visit']) profile.last_visit = user.last_login # Groups user.groups.add(self.member_group) group_name = unicode(row['group_name'], self.encoding) if group_name == 'Administrateurs': user.groups.add(self.admin_group) user.is_superuser = True elif group_name == 'Gardiens' or group_name == 'Modérateur': user.groups.add(self.staff_group) elif group_name == 'Animateur': user.groups.add(self.animator_group) # Profile profile.title = self.decode(row['title']) if row['title'] is not None else '' profile.site = self.decode(row['website']) if row['website'] is not None else '' # TODO Markdown conversion profile.sign = self.decode(row['signature']) if row['signature'] is not None else '' profile.show_sign = bool(row['show_signature']) # Avatar # FluxBB doesn't store the avatar URL, but retries each time to find the file type, # checking if the file exists for the three allowed extensions. Yes. avatar_url_pattern = 'https://forum.zcraft.fr/img/avatars/{}.{}' extensions = ['jpg', 'png', 'gif'] for extension in extensions: avatar_url = avatar_url_pattern.format(row['user_id'], extension) r = requests.get(avatar_url) if r.status_code == 200: profile.set_avatar_from_file(StringIO(r.content), filename='avatar.{}'.format(extension)) user.save() profile.save() # Administrative note imported as a karma note with score = 0 if row['admin_note']: KarmaNote(user=user, staff=user, comment=self.decode(row['admin_note']), value=0).save() # Bans if row['ban_creator_username']: if row['ban_message']: ban_message = self.decode(row['ban_message']) else: ban_message = 'Bannissement : aucun motif donné' # A ban with an expiration date if row['ban_expiration']: days = (datetime.datetime.fromtimestamp(row['ban_expiration']) - datetime.datetime.now()).days if days > 0: state = TemporaryBanSanction({ 'ban-text': ban_message, 'ban-jrs': days }) karma_score = -10 else: state = None karma_score = 0 else: state = BanSanction({ 'ban-text': ban_message }) karma_score = -20 if state: try: moderator = User.objects.filter(username=self.decode(row['ban_creator_username'])).first() if not moderator: moderator = User.objects.filter(username=ZDS_APP['member']['bot_account']).first() ban = state.get_sanction(moderator, user) state.apply_sanction(profile, ban) KarmaNote(user=user, staff=moderator, comment=ban_message, value=karma_score).save() profile.karma += karma_score profile.save() except ValueError as e: self.stderr.write(' Unable to import ban for {}: error: {}'.format(user.username, e)) imported += 1 percentage = int((float(imported) / float(users_count)) * 100) self.print_progress("[{}% - {}/{}] Importing user {}...".format(percentage, imported, users_count, user.username)) print("\nDone.")