Skip to content

Commit

Permalink
* askbot.models.user:
Browse files Browse the repository at this point in the history
 - Group.objects.get_or_create() - adds visibility parameter, returns tuple (group, created)
   to match the behavior of django.db.models.Manager.get_or_create()
   switch to this signature where this method is used
 - PEP8 cleanup
* adds test case for askbot_create_per_email_domain_groups
  • Loading branch information
evgenyfadeev committed Jun 30, 2024
1 parent 5f1a856 commit 8d3d6e2
Show file tree
Hide file tree
Showing 12 changed files with 274 additions and 236 deletions.
39 changes: 28 additions & 11 deletions askbot/management/commands/askbot_create_per_email_domain_groups.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""A management command that creates groups for each email domain in the database."""
from django.core.management.base import BaseCommand
from askbot.conf import settings
from askbot.models import User
from askbot.models.analytics import get_organization_domains
from askbot.conf import settings as askbot_settings
from askbot.models import Group, User
from askbot.models.analytics import get_unique_user_email_domains_qs
from askbot.models.user import get_organization_name_from_domain
from askbot.utils.console import ProgressBar

Expand All @@ -14,14 +14,31 @@ def handle(self, *args, **options): # pylint: disable=missing-docstring, unused-
Creates a group for each domain name, if such group does not exist.
Group visibility is set to the value of settings.PER_EMAIL_DOMAIN_GROUP_DEFAULT_VISIBILITY.
"""
domains = get_organization_domains()
domains = get_unique_user_email_domains_qs()
count = len(domains)
message = 'Initializing groups by the email address domain names'
for domain in ProgressBar(domains, count, message):
organization_name = get_organization_name_from_domain(domain)
group = User.objects.get_or_create_group(
organization_name,
visibility=settings.PER_EMAIL_DOMAIN_GROUP_DEFAULT_VISIBILITY
message = 'Creating groups by the email address domain names'
created_groups = []
unchanged_groups = []
done_lowercased_domains = []
for domain in ProgressBar(domains.iterator(), count, message):

domain_name = domain['domain']
if domain_name.lower in done_lowercased_domains:
continue
else:
done_lowercased_domains.append(domain_name.lower())

organization_name = get_organization_name_from_domain(domain_name)
group, created = Group.objects.get_or_create(
name=organization_name,
visibility=askbot_settings.PER_EMAIL_DOMAIN_GROUP_DEFAULT_VISIBILITY
)
print('Group {0} created.'.format(group.name))
users = User.objects.filter(email__endswith='@' + domain_name)
for user in users.iterator():
user.join_group(group, force=True)

if created:
created_groups.append(group)
else:
unchanged_groups.append(group)

2 changes: 1 addition & 1 deletion askbot/media/js/utils/lang_nav.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ LangNav.prototype.translateUrl = function(url, lang) {
type: 'GET',
url: askbot['urls']['translateUrl'],
data: {'url': url, 'language': lang },
async: false,
async: false, //important!
cache: false,
dataType: 'json',
success: function(data) {
Expand Down
2 changes: 1 addition & 1 deletion askbot/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2946,7 +2946,7 @@ def user_join_default_groups(self):
group = Group.objects.get_global_group()
self.join_group(group, force=True)
group_name = format_personal_group_name(self)
group = Group.objects.get_or_create(name=group_name, user=self)
group, _ = Group.objects.get_or_create(name=group_name, user=self)
self.join_group(group, force=True)

def user_get_personal_group(self):
Expand Down
9 changes: 7 additions & 2 deletions askbot/models/analytics.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def get_non_admins_count():
return non_admins.count()


def get_organization_domains():
def get_unique_user_email_domains_qs():
"""Returns the query set of organization domain names"""
domain_annotation = Substr('email', StrIndex('email', Value('@')) + 1)
return User.objects.annotate(domain=domain_annotation).values('domain').distinct()
Expand All @@ -102,7 +102,12 @@ def get_organizations_count():
"""
if not django_settings.ASKBOT_ANALYTICS_EMAIL_DOMAIN_ORGANIZATIONS_ENABLED:
return 0
return get_organization_domains().count()
return get_unique_user_email_domains_qs().count()


def get_unique_user_email_domains():
"""Returns a list of unique email domain names"""
return list(get_user_organization_domains_qs().values_list('domain', flat=True))


class Session(models.Model):
Expand Down
50 changes: 28 additions & 22 deletions askbot/models/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def remove_email_from_invited_moderators(email):
"""Update the `INVITED_MODERATORS` setting by removing
the matching email entry"""
lines = askbot_settings.INVITED_MODERATORS.strip().split('\n')
clean_lines = list()
clean_lines = []
prefix = email + ' '
for line in lines:
if not line.startswith(prefix):
Expand Down Expand Up @@ -157,15 +157,15 @@ def fetch_content_objects_dict(self):
"""return a dictionary where keys are activity ids
and values - content objects"""
content_object_ids = defaultdict(list)# lists of c.object ids by c.types
activity_type_ids = dict()#links c.objects back to activity objects
activity_type_ids = {} #links c.objects back to activity objects
for act in self:
content_type_id = act.content_type_id
object_id = act.object_id
content_object_ids[content_type_id].append(object_id)
activity_type_ids[(content_type_id, object_id)] = act.id

#3) get links from activity objects to content objects
objects_by_activity = dict()
objects_by_activity = {}
for content_type_id, object_id_list in list(content_object_ids.items()):
content_type = ContentType.objects.get_for_id(content_type_id)
model_class = content_type.model_class()
Expand Down Expand Up @@ -193,7 +193,7 @@ def create_new_mention(
):

#todo: automate this using python inspect module
kwargs = dict()
kwargs = {}

kwargs['activity_type'] = const.TYPE_ACTIVITY_MENTION

Expand Down Expand Up @@ -241,7 +241,7 @@ def get_mentions(
todo: implement better rich field lookups
"""

kwargs = dict()
kwargs = {}

kwargs['activity_type'] = const.TYPE_ACTIVITY_MENTION

Expand Down Expand Up @@ -571,28 +571,34 @@ def create(self, **kwargs):
kwargs['group_ptr'] = group_ptr
except AuthGroup.DoesNotExist:
pass
return super(GroupManager, self).create(**kwargs)
return super().create(**kwargs)

def get_or_create(self, name=None, user=None, openness=None):
def get_or_create(self, name=None, user=None, openness=None, visibility=None):
"""creates a group tag or finds one, if exists"""
#todo: here we might fill out the group profile
try:
#iexact is important!!! b/c we don't want case variants
#of tags
#iexact is important!!! b/c we don't want case variants of groups
group = self.get(name__iexact = name)
created = False
except self.model.DoesNotExist:
default_visibility = askbot_settings.PER_EMAIL_DOMAIN_GROUP_DEFAULT_VISIBILITY
if visibility is None:
visibility = default_visibility

if openness is None:
group = self.create(name=name)
else:
group = self.create(name=name, openness=openness)
return group
openness = self.model.DEFAULT_OPENNESS

group = self.create(name=name, openness=openness, visibility=visibility)
created = True
return group, created


class Group(AuthGroup):
"""group profile for askbot"""
OPEN = 0
MODERATED = 1
CLOSED = 2
DEFAULT_OPENNESS = CLOSED
OPENNESS_CHOICES = (
(OPEN, 'open'),
(MODERATED, 'moderated'),
Expand All @@ -610,7 +616,7 @@ class Group(AuthGroup):
can_upload_attachments = models.BooleanField(default=False)
can_upload_images = models.BooleanField(default=False)

openness = models.SmallIntegerField(default=CLOSED, choices=OPENNESS_CHOICES)
openness = models.SmallIntegerField(default=DEFAULT_OPENNESS, choices=OPENNESS_CHOICES)
visibility = models.SmallIntegerField(default=const.GROUP_VISIBILITY_PUBLIC,
choices=const.GROUP_VISIBILITY_CHOICES)

Expand Down Expand Up @@ -695,27 +701,27 @@ def clean(self):
emails = functions.split_list(self.preapproved_emails)
email_field = EmailField()
try:
list(map(lambda v: email_field.clean(v), emails))
except exceptions.ValidationError:
list(map(email_field.clean, emails))
except exceptions.ValidationError as exc:
raise exceptions.ValidationError(
_('Please give a list of valid email addresses.')
)
) from exc
self.preapproved_emails = ' ' + '\n'.join(emails) + ' '

domains = functions.split_list(self.preapproved_email_domains)
from askbot.forms import DomainNameField
domain_field = DomainNameField()
try:
list(map(lambda v: domain_field.clean(v), domains))
except exceptions.ValidationError:
list(map(domain_field.clean, domains))
except exceptions.ValidationError as exc:
raise exceptions.ValidationError(
_('Please give a list of valid email domain names.')
)
) from exc
self.preapproved_email_domains = ' ' + '\n'.join(domains) + ' '

def save(self, *args, **kwargs):
self.clean()
super(Group, self).save(*args, **kwargs)
super().save(*args, **kwargs)


class BulkTagSubscriptionManager(BaseQuerySetManager): # pylint: disable=too-few-public-methods
Expand All @@ -735,7 +741,7 @@ def create(
user_list = user_list or []
group_list = group_list or []

new_object = super(BulkTagSubscriptionManager, self).create(**kwargs)
new_object = super().create(**kwargs)
tag_name_list = []

if tag_names:
Expand Down
12 changes: 12 additions & 0 deletions askbot/tests/test_management_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -376,3 +376,15 @@ def test_askbot_send_moderation_alerts1(self):
#command sends alerts to three moderators at a time
self.assertEqual(len(mail.outbox), 2)
self.assertTrue('moderation' in mail.outbox[0].subject)


def test_askbot_create_per_email_domain_groups(self):
user1 = self.create_user('org1', '[email protected]')
user2 = self.create_user('org2', '[email protected]')
count = models.Group.objects.filter(name__in=('Org1', 'Org2')).count()
self.assertEqual(count, 0)
management.call_command('askbot_create_per_email_domain_groups')
count = models.Group.objects.filter(name__in=('Org1', 'Org2')).count()
self.assertEqual(count, 2)


2 changes: 0 additions & 2 deletions askbot/tests/test_markup.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,5 @@ def test_convert_mixed_text(self):
"""
"""<a href="http://example.com"><div>http://example.com</div></a>
"""
import pdb
pdb.set_trace()
converted = self.conv(text)
self.assertHTMLEqual(converted, expected)
2 changes: 1 addition & 1 deletion askbot/tests/test_thread_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def setUp(self):
self.user.new_response_count = 0
self.user.seen_response_count = 0
self.user.save()
self.group = models.Group.objects.get_or_create(name='jockeys')
self.group = models.Group.objects.get_or_create(name='jockeys')[0]
self.group.can_post_questions = True
self.group.can_post_answers = True
self.group.can_post_comments = True
Expand Down
4 changes: 1 addition & 3 deletions askbot/tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,9 +316,7 @@ def create_tag(self, tag_name, user = None):
return tag

def create_group(self, group_name=None, openness=models.Group.OPEN):
return models.Group.objects.get_or_create(
name='private', openness=openness
)
return models.Group.objects.get_or_create(name='private', openness=openness)[0]

def post_comment(
self,
Expand Down
2 changes: 1 addition & 1 deletion askbot/utils/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def wrapper(request, *args, **kwargs):
data = view_func(request, *args, **kwargs)
if data is None:
data = {}
except Exception as e:
except Exception as e: # pylint: disable=broad-except
#todo: also check field called "message"
if hasattr(e, 'messages'):
if len(e.messages) > 1:
Expand Down
13 changes: 13 additions & 0 deletions askbot/utils/http.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
"""http-related utilities for askbot
"""
from copy import copy
from askbot.conf import settings as askbot_settings

def is_ajax(request):
"""Returns `True` if request is ajax"""
return request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'


def can_save_draft(request):
"""Returns `True` if the user is allowed to save drafts"""
return not any((
request.user.is_anonymous,
request.user.is_read_only(),
not request.user.is_active,
request.user.is_blocked(),
request.user.is_suspended(),
askbot_settings.READ_ONLY_MODE_ENABLED,
))


def hide_passwords(data):
"""replaces content of values that may contain passsword
with XXXXXX for better security"""
Expand Down
Loading

0 comments on commit 8d3d6e2

Please sign in to comment.