Exemplo n.º 1
0
    def get_results(self, request, term, page, context):
        term = term.lower()
        start = (page - 1) * 10
        end = page * 10

        filt = Q(**{f'dynamic_fields__{self.field_name}__icontains': term})
        qs = get_user_profile_model().objects.all().filter(filt)

        count = qs.count()
        if count < start:
            raise Http404
        has_more = count > end

        all_values = qs.values_list(f'dynamic_fields__{self.field_name}',
                                    flat=True)
        # flatten values as some returned values might be items, and some might be lists
        flat_values = []
        for val in all_values:
            flat_values += val if isinstance(val, list) else [val]
        # return only matched values
        matches = [
            item for item in flat_values if item and term in item.lower()
        ]
        text_choices = [(match, match) for match in matches[start:end]]
        return (NO_ERR_RESP, has_more, text_choices)
Exemplo n.º 2
0
def get_user_query_filter_for_search_terms(terms):
    """ Returns a django Q filter for use on USER_MODEL that returns all users with matching
        names, given an array of search terms. Each search term needs to be matched (AND)
        on at least one of the user's name fields (OR). Case is insensitive.
        User name fields are USER_MODEL.first_name, USER_MODEL.last_name, as well as any
        additional fields defined in the user profile model (``ADDITIONAL_USERNAME_FIELDS``).
        @param terms: An array of string search terms.
        @return: A django Q object.
    """
    from cosinnus.models.profile import get_user_profile_model
    ADDITIONAL_USERNAME_FIELDS = get_user_profile_model(
    ).ADDITIONAL_USERNAME_FIELDS
    first_term, other_terms = terms[0], terms[1:]

    # username is not used as filter for the term for now, might confuse
    # users why a search result is found
    q = Q(first_name__icontains=first_term) | Q(
        last_name__icontains=first_term)
    for field_name in ADDITIONAL_USERNAME_FIELDS:
        q |= Q(**{'cosinnus_profile__%s__icontains' % field_name: first_term})
    for other_term in other_terms:
        add_q = Q(first_name__icontains=other_term) | Q(
            last_name__icontains=other_term)
        for field_name in ADDITIONAL_USERNAME_FIELDS:
            add_q |= Q(
                **{'cosinnus_profile__%s__icontains' % field_name: first_term})
        q &= add_q

    return q
Exemplo n.º 3
0
 def get_data(self, *kwargs):
     profile_ct = ContentType.objects.get_for_model(
         get_user_profile_model())
     likeobjects = LikeObject.objects.filter(user=self.request.user,
                                             content_type=profile_ct,
                                             starred=True)
     liked_users_ids = likeobjects.values_list('object_id', flat=True)
     liked_users = get_user_profile_model().objects.filter(
         id__in=liked_users_ids, user__is_active=True)
     users = []
     for user in liked_users:
         dashboard_item = DashboardItem(user)
         dashboard_item['id'] = user.id
         dashboard_item['ct'] = user.get_content_type()
         users.append(dashboard_item)
     return {'items': users}
Exemplo n.º 4
0
    def get_data(self, offset=0):
        """ Returns a tuple (data, rows_returned, has_more) of the rendered data and how many items were returned.
            if has_more == False, the receiving widget will assume no further data can be loaded.
         """
        group = self.config.group
        if group is None:
            return ''

        # how many members display. it's -1 because the last tile is always the "+72 members"
        count = getattr(settings, 'COSINNUS_GROUP_MEMBER_WIDGET_USER_COUNT',
                        15)

        admin_ids = CosinnusGroupMembership.objects.get_admins(group=group)
        member_ids = CosinnusGroupMembership.objects.get_members(group=group)
        all_ids = set(admin_ids + member_ids)

        userprofile_table = get_user_profile_model()._meta.db_table
        qs = get_user_model()._default_manager.filter(is_active=True) \
            .exclude(last_login__exact=None) \
            .filter(cosinnus_profile__settings__contains='tos_accepted') \
            .select_related('cosinnus_profile') \
            .extra(select={
                'has_avatar': 'LENGTH(%s.avatar) > 0' % userprofile_table
            }) \
            .order_by('-has_avatar', 'first_name', 'last_name')
        qs = qs.filter(id__in=all_ids)

        self.member_count = qs.count()
        hidden_member_count = 0

        is_member_of_this_group = self.request.user.pk in all_ids
        if not self.request.user.is_authenticated:
            visibility_level = BaseTagObject.VISIBILITY_ALL
        elif not is_member_of_this_group:
            visibility_level = BaseTagObject.VISIBILITY_GROUP
        else:
            visibility_level = -1

        # show VISIBILITY_ALL users to anonymous users, VISIBILITY_GROUP to logged in users,
        # and all members to group-members
        if visibility_level != -1:
            qs = qs.filter(
                cosinnus_profile__media_tag__visibility__gte=visibility_level)
            hidden_member_count = self.member_count - len(qs)

        has_more = len(qs) > offset + count or hidden_member_count > 0
        more_count = max(0, len(qs) - (offset + count)) + hidden_member_count

        if count != 0:
            qs = qs[offset:offset + count]

        data = {
            'group': group,
            'members': qs,
            'has_more': has_more,
            'more_count': more_count,
        }
        return (render_to_string('cosinnus/widgets/group_members.html',
                                 data), len(qs), has_more)
Exemplo n.º 5
0
    def save(self, commit=True):
        """ Assign the extra fields to the user's cosinnus_profile's `dynamic_fields` 
        JSON field instead of model fields, after user form save """
        ret = super().save(commit=commit)
        if commit:
            if hasattr(self, 'cleaned_data'):
                # sanity check, retrieve the user's profile (will create it if it doesnt exist)
                if not self.instance.cosinnus_profile:
                    get_user_profile_model()._default_manager.get_for_user(
                        self.instance)

                profile = self.instance.cosinnus_profile
                for field_name in self.DYNAMIC_FIELD_SETTINGS.keys():
                    profile.dynamic_fields[field_name] = self.cleaned_data.get(
                        field_name, None)
                    profile.save()
        return ret
Exemplo n.º 6
0
class UserProfileObjectMixin(SingleObjectMixin):
    model = get_user_profile_model()

    def get_object(self):
        return self.model._default_manager.get_for_user(self.request.user)

    @method_decorator(login_required)
    def dispatch(self, request, *args, **kwargs):
        return super(UserProfileObjectMixin,
                     self).dispatch(request, *args, **kwargs)
def set_last_action_to_created(apps, schema_editor):
    """ One-Time sets all CosinnusIdeas' `last_updated` field value 
        to its `created` field value.  """

    UserProfile = get_user_profile_model()
    for userprofile in UserProfile.objects.all():
        if userprofile.extra_fields:
            userprofile.dynamic_fields = userprofile.extra_fields
            # Update profile without triggering signals to prevent triggers during migrations
            UserProfile.objects.filter(pk=userprofile.pk).update(
                dynamic_fields=userprofile.extra_fields)
Exemplo n.º 8
0
 def filter_user_qs(self, user_qs, terms):
     user_qs = super(ManagedTagsMembersView,
                     self).filter_user_qs(user_qs, terms)
     if self.managed_tag_slug:
         profile_assignments_qs = CosinnusManagedTagAssignment.objects.get_for_model(
             get_user_profile_model())
         assigned_profile_ids = profile_assignments_qs.filter(
             managed_tag__slug=self.managed_tag_slug).values_list(
                 'object_id', flat=True)
         user_qs = user_qs.filter(
             cosinnus_profile__id__in=assigned_profile_ids)
     return user_qs
Exemplo n.º 9
0
def create_user(email,
                username=None,
                first_name=None,
                last_name=None,
                tos_checked=True):
    """ Creates a user with a random password, and adds proper PortalMemberships for this portal.
        @param email: Email is required because it's basically our pk
        @param username: Can be left blank and will then be set to the user's id after creation.
        @param tos_checked: Set to False if the user should have to check the Terms of Services upon first login.
        @return: A <USER_MODEL> instance if creation successful, False if failed to create (was the username taken?)
    """
    from cosinnus.forms.user import UserCreationForm
    from cosinnus.models.profile import get_user_profile_model  # leave here because of cyclic imports

    pwd = get_random_string()
    data = {
        'username': username or get_random_string(),
        'email': email,
        'password1': pwd,
        'password2': pwd,
        'first_name': first_name,
        'last_name': last_name,
        'tos_check':
        True,  # needs to be True for form validation, may be reset later
    }
    # use Cosinnus' UserCreationForm to apply all usual user-creation-related effects
    form = UserCreationForm(data)
    if form.is_valid():
        user = form.save()
    else:
        logger.warning('Manual user creation failed because of form errors!',
                       extra={
                           'data': data,
                           'form-errors': form.errors
                       })
        return False
    # always retrieve this to make sure the profile was created, we had a Heisenbug here
    profile = get_user_profile_model()._default_manager.get_for_user(user)

    if not tos_checked:
        profile.settings['tos_accepted'] = False
        profile.save()

    # username is always its id
    user.username = user.id

    user.backend = 'cosinnus.backends.EmailAuthBackend'
    user.save()

    return user
Exemplo n.º 10
0
    def create_account(self, data, groups):

        username = self.get_unique_workshop_name(data[0])
        first_name = data[1]
        last_name = data[2]

        try:
            name_string = '"{}":"{}"'.format(
                PROFILE_SETTING_WORKSHOP_PARTICIPANT_NAME, username)
            profile = UserProfile.objects.get(settings__contains=name_string)
            user = profile.user
            user.first_name = first_name
            user.last_name = last_name
            user.save()
            self.create_or_update_memberships(user, data, groups)
            return data + [user.email, '']
        except ObjectDoesNotExist:
            random_email = '{}@wechange.de'.format(get_random_string())
            pwd = get_random_string()
            user = create_base_user(random_email,
                                    password=pwd,
                                    first_name=first_name,
                                    last_name=last_name)

            if user:
                profile = get_user_profile_model(
                )._default_manager.get_for_user(user)
                profile.settings[
                    PROFILE_SETTING_WORKSHOP_PARTICIPANT_NAME] = username
                profile.settings[PROFILE_SETTING_WORKSHOP_PARTICIPANT] = True
                profile.add_redirect_on_next_page(redirect_with_next(
                    group_aware_reverse('cosinnus:group-dashboard',
                                        kwargs={'group': self.group}),
                    self.request),
                                                  message=None,
                                                  priority=True)
                profile.save()

                unique_email = 'User{}.C{}@wechange.de'.format(
                    str(user.id), str(self.group.id))
                user.email = unique_email
                user.is_active = False
                user.save()

                self.create_or_update_memberships(user, data, groups)
                return data + [unique_email, pwd]
            else:
                return data + [_('User was not created'), '']
Exemplo n.º 11
0
 def get_data(self, *kwargs):
     profile_ct = ContentType.objects.get_for_model(
         get_user_profile_model())
     exclude_ids = [profile_ct.id]
     liked = LikeObject.objects.filter(
         user=self.request.user,
         starred=True).exclude(content_type_id__in=exclude_ids)
     objects = []
     for like in liked:
         ct = ContentType.objects.get_for_id(like.content_type.id)
         obj = ct.get_object_for_this_type(pk=like.object_id)
         dashboard_item = DashboardItem(obj)
         dashboard_item['id'] = obj.id
         dashboard_item['ct'] = obj.get_content_type()
         objects.append(dashboard_item)
     return {'items': objects}
Exemplo n.º 12
0
def managed_tag_sync_paired_group_memebership_deletion(sender, instance,
                                                       **kwargs):
    """ If a managed tag has a paired group and has been unassigned from a user profile,
        delete the user's group membership in the paired group (unless the user is a group admin) """
    try:
        target_object = instance.target_object
        if target_object and type(target_object) is get_user_profile_model():
            tag = instance.managed_tag
            if tag.paired_group:
                membership = get_object_or_None(CosinnusGroupMembership,
                                                group=tag.paired_group,
                                                user=target_object.user)
                if membership and not membership.status == MEMBERSHIP_ADMIN:
                    membership.delete()
    except Exception as e:
        logger.exception(e)
Exemplo n.º 13
0
def reset_user_tos_flags(request=None):
    if request and not request.user.is_superuser:
        return HttpResponseForbidden('Not authenticated')

    if not request.GET.get('confirm', False) == '1':
        active_users = filter_active_users(get_user_model().objects.all())
        ret = '********** This will reset all %d active users\' ToS accepted flag! Use param ?confirm=1 to delete the flags! ***********' % active_users.count()
    else:
        count = 0
        active_users = filter_active_users(get_user_model().objects.all())
        for profile in get_user_profile_model().objects.all().filter(user__in=active_users):
            del profile.settings['tos_accepted']
            profile.save(update_fields=['settings'])
            count += 1
        ret = 'Successfully reset the ToS flag for %d users.' % count
        
    return HttpResponse(ret)
Exemplo n.º 14
0
    def get_models(self):
        """ Return the models of types user has selected to filter search on """
        search_models = []

        if self.is_valid():
            # we either use the models given to us from the form, or if empty,
            # all models available for search
            model_aliases_query = self.cleaned_data.get('models', [])
            if not model_aliases_query:
                model_aliases_query = list(MODEL_ALIASES.keys())
            for model_alias in model_aliases_query:
                if model_alias in list(MODEL_ALIASES.keys()):
                    model_string = MODEL_ALIASES[model_alias]
                    if model_string == '<userprofile>':
                        model = get_user_profile_model()
                    else:
                        model = apps.get_model(*model_string.split('.'))
                    search_models.append(model)
        
        return search_models
Exemplo n.º 15
0
class UserProfileObjectMixin(SingleObjectMixin):
    model = get_user_profile_model()
    slug_field = 'username'
    slug_url_kwarg = 'username'

    def get_object(self, queryset=None):
        """ Return the userprofile for the current logged in user if no kwarg slug is given,
            or the userprofile for the username slug given """

        pk = self.kwargs.get(self.pk_url_kwarg, None)
        slug = self.kwargs.get(self.slug_url_kwarg, None)

        # return the current user's userprofile if no slug is given
        if not pk and not slug:
            if not self.request.user.is_authenticated:
                return None
            return self.model._default_manager.get_for_user(self.request.user)

        if queryset is None:
            queryset = self.get_queryset()
        if pk is not None:
            queryset = queryset.filter(user__pk=pk)
        # Next, try looking up by slug.
        elif slug is not None:
            slug_field = self.get_slug_field()
            queryset = queryset.filter(**{'user__' + slug_field: slug})
        # If none of those are defined, it's an error.
        else:
            raise AttributeError("Generic detail view %s must be called with "
                                 "either an object pk or a slug." %
                                 self.__class__.__name__)
        try:
            # Get the single item from the filtered queryset
            obj = queryset.get()
        except ObjectDoesNotExist:
            raise Http404(
                _("No %(verbose_name)s found matching the query") %
                {'verbose_name': queryset.model._meta.verbose_name})

        return obj
Exemplo n.º 16
0
def managed_tag_sync_paired_group_memebership_creation(sender, instance,
                                                       created, **kwargs):
    """ If a managed tag has a paired group and has been assigned (and approved) to a user profile,
        create the user's group membership in the paired group if it doesn't exist yet """
    try:
        target_object = instance.target_object
        if instance.approved and target_object and isinstance(
                target_object, get_user_profile_model()):
            tag = instance.managed_tag
            if tag.paired_group:
                membership = get_object_or_None(CosinnusGroupMembership,
                                                group=tag.paired_group,
                                                user=target_object.user)
                if membership and not membership.status in MEMBER_STATUS:
                    membership.status = MEMBERSHIP_MEMBER
                    membership.save()
                elif not membership:
                    CosinnusGroupMembership.objects.create(
                        group=tag.paired_group,
                        user=target_object.user,
                        status=MEMBERSHIP_MEMBER)
    except Exception as e:
        logger.exception(e)
Exemplo n.º 17
0
 def get_model(self):
     return get_user_profile_model()
Exemplo n.º 18
0
def callback(request):
    if request.user.is_authenticated():
        return redirect(_get_redirect_url(request))
    try:
        user_info = do_oauth1_receive(request)
    except Exception as e:
        logger.error('Exception during SSO callback, exception was "%s"' %
                     str(e),
                     extra={'trace': traceback.format_exc()})
        messages.error(
            request,
            force_text(
                _('Sorry, we could not connect your user account because of an internal error. Please contact a system administrator!'
                  )) + ' (sso:2)')
        if settings.DEBUG:
            raise
        return redirect(reverse('sso-error'))

    # these properties are required and thus guarenteed to be in the user_info dict in the following code
    if not all(
        [bool(prop in user_info) for prop in ['username', 'email', 'id']]):
        logger.error(
            'Exception during SSO login, not all expected properties in returned user info JSON!',
            extra={'user_info': user_info})
        messages.error(
            request,
            force_text(
                _('Sorry, we could not connect your user account, because we could not retrieve important user account infos. Please contact a system administrator!'
                  )) + ' (sso:3)')
        return redirect('sso-error')

    # match user over ID, never email! this could be used to take over other user accounts if the SSO server does not enforce email validation
    # because of this, we actually may end up with non-unique emails in cosinnus, but since regular authentication is disabled,  this should not cause problems
    # Note: using a raw query here for actual safe JSON-matching
    try:
        if getattr(settings, 'COSINNUS_DO_ALL_SERVERS_HAVE_PSQL_9_3', False):
            # psql 9.3 does JSON right
            profile = get_user_profile_model().objects.all().extra(where=[
                "settings::json->>'%s' = '%d'" %
                (SSO_USERPROFILE_FIELD_ID, user_info['id'])
            ]).get()
        else:
            # fall back to a bad method for JSON field filtering
            attr = '"%s":%d' % (SSO_USERPROFILE_FIELD_ID, user_info['id'])
            profile = get_user_profile_model().objects.all().filter(
                Q(settings__icontains='%s,' % attr)
                | Q(settings__icontains='%s}' % attr)).get()

        user = profile.user
        if not user.is_active:
            messages.error(
                request,
                force_text(
                    _('Sorry, you cannot log in because your account is suspended. Please contact a system administrator!'
                      )) + ' (sso:4)')
            return redirect('sso-error')

    except get_user_profile_model().DoesNotExist:
        # if the user doesn't exist yet, create a user acount and portal membership for him
        # we create the user with a random email to get around cosinnus' unique-email validation,
        # because we cannot be sure if the SSO server has unique emails we will replace the email here later on
        user = create_user('*****@*****.**' % get_random_string(),
                           first_name=user_info.get('first_name',
                                                    user_info.get('username')),
                           last_name=user_info.get('last_name', None))
        if not user:
            logger.error(
                'Exception during SSO login, User could not be created!',
                extra={'user_info': user_info})
            messages.error(
                request,
                force_text(
                    _('Sorry, we could not connect your user account because of an internal error. Please contact a system administrator!'
                      )) + ' (sso:5)')
            return redirect('sso-error')

        profile = user.cosinnus_profile
        profile.settings[SSO_USERPROFILE_FIELD_ID] = user_info['id']

    # update the user's profile info and email and oauth_token and oauth_secret in settings
    user.first_name = user_info.get('first_name', user_info.get('username'))
    user.last_name = user_info.get('last_name', user_info.get('username'))
    user.email = user_info.get('email')

    profile.settings[SSO_USERPROFILE_FIELD_OAUTH_TOKEN] = user_info[
        'oauth_token']
    profile.settings[SSO_USERPROFILE_FIELD_OAUTH_SECRET] = user_info[
        'oauth_secret']
    profile.language = 'de' if user_info.get(
        'locale', None
    ) == 'de_DE' else 'en'  # if "locale" == de_DE -> language german, else english
    profile.website = user_info.get('link', None)

    # set user avatar to largest available
    try:
        # avatars are listed in a dictionary of 'size_in_px' --> 'avatar_url'
        avatar_url = sorted(list(user_info.get('avatar_urls', {}).items()),
                            reverse=True)[0][1]

        img_temp = NamedTemporaryFile(delete=True)
        img_temp.write(urllib.request.urlopen(avatar_url).read())
        img_temp.flush()

        profile.avatar.save(
            get_avatar_filename(img_temp,
                                avatar_url.split('/')[-1]), File(img_temp))
    except (IndexError, Exception):
        if settings.DEBUG:
            raise

    profile.save()
    user.cosinnus_profile = profile
    user.save()

    # log user in and switch request language to locale
    user.backend = 'cosinnus.backends.EmailAuthBackend'
    django_login(request, user)
    translation.activate(getattr(profile, 'language',
                                 settings.LANGUAGES[0][0]))

    return redirect(_get_redirect_url(request))
Exemplo n.º 19
0
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import datetime

from django.contrib.auth import get_user_model
from django.test import TestCase
from django.utils.encoding import force_text

from cosinnus.models.profile import get_user_profile_model

from tests.utils import skipIfCustomUserProfile, skipUnlessCustomUserProfile


User = get_user_model()
UserProfile = get_user_profile_model()


class UserProfileTest(TestCase):

    def test_user_profile_create_signal(self):
        self.assertEqual(User.objects.all().count(), 0)
        self.assertEqual(UserProfile.objects.all().count(), 0)
        User.objects.create_user('somebody')
        self.assertEqual(User.objects.all().count(), 1)
        self.assertEqual(UserProfile.objects.all().count(), 1)

    def test_user_profile_save(self):
        u1 = User.objects.create_user('somebody')
        p1 = u1.cosinnus_profile
        p1.save()
Exemplo n.º 20
0
admin.site.register(CosinnusMicropage, CosinnusMicropageAdmin)


class CosinnusReportedObjectAdmin(admin.ModelAdmin):
    list_display = ('text', 'target_object', 'creator', 'created')
    list_filter = ('creator', )
    change_form_template = 'admin/cosinnusreportedobject/change_form.html'


admin.site.register(CosinnusReportedObject, CosinnusReportedObjectAdmin)

admin.site.register(AttachedObject)

# user / user profile related admin

USER_PROFILE_MODEL = get_user_profile_model()
USER_MODEL = get_user_model()


class UserProfileAdmin(admin.ModelAdmin):
    readonly_fields = ('settings', )


admin.site.register(get_user_profile_model(), UserProfileAdmin)


class UserProfileInline(admin.StackedInline):
    model = USER_PROFILE_MODEL
    readonly_fields = ('settings', )

Exemplo n.º 21
0
 class Meta(BaseUserProfileSerializer.Meta):
     model = get_user_profile_model()
Exemplo n.º 22
0
        })
        ret = super(DetailedIdeaMapResult, self).__init__(haystack_result, obj, user, *args, **kwargs)
        return ret



SHORTENED_ID_MAP = {
    'cosinnus.cosinnusproject': 1,
    'cosinnus.cosinnussociety': 2,
    'cosinnus.userprofile': 3,
    'cosinnus_event.event': 4,
    'cosinnus.cosinnusidea': 5,
}

SEARCH_MODEL_NAMES = {
    get_user_profile_model(): 'people',
    CosinnusProject: 'projects',
    CosinnusSociety: 'groups',
}
SHORT_MODEL_MAP = {
    1: CosinnusProject,
    2: CosinnusSociety,
    3: get_user_profile_model(),
}
SEARCH_RESULT_DETAIL_TYPE_MAP = {
    'people': DetailedUserMapResult,
    'projects': DetailedProjectMapResult,
    'groups': DetailedSocietyMapResult,
}
try:
    from cosinnus_event.models import Event #noqa
Exemplo n.º 23
0
 class Meta(object):
     model = get_user_profile_model()
     fields = ('id', 'avatar')
Exemplo n.º 24
0
 def setup_profile(self, user):
     if not user.cosinnus_profile:
         return get_user_profile_model()._default_manager.get_for_user(user)
     return user.cosinnus_profile
Exemplo n.º 25
0
 class Meta(BaseUserProfileSerializer.Meta):
     model = get_user_profile_model()
     fields = BaseUserProfileSerializer.Meta.fields + ('avatar', )
Exemplo n.º 26
0
    def form_valid(self, form):
        ret = super(UserCreateView, self).form_valid(form)
        user = self.object
        
        # sanity check, retrieve the user's profile (will create it if it doesnt exist)
        profile = user.cosinnus_profile or get_user_profile_model()._default_manager.get_for_user(user)
        
        # set current django language during signup as user's profile language
        lang = get_language()
        if not profile.language == lang:
            profile.language = lang
            profile.save(update_fields=['language']) 
        
        # set user inactive if this portal needs user approval and send an email to portal admins
        if CosinnusPortal.get_current().users_need_activation:
            user.is_active = False
            user.save()
            data = get_common_mail_context(self.request)
            data.update({
                'user': user,
            })
            # message portal admins of request
            subject = render_to_string('cosinnus/mail/user_register_notification_subj.txt', data)
            email_portal_admins(subject, 'cosinnus/mail/user_register_notification.html', data)
            # message user for pending request
            subj_user = render_to_string('cosinnus/mail/user_registration_pending_subj.txt', data)
            send_mail_or_fail_threaded(user.email, subj_user, 'cosinnus/mail/user_registration_pending.html', data)
            
            messages.success(self.request, self.message_success_inactive % {'user': user.email, 'email': user.email})
        
        # scramble this users email so he cannot log in until he verifies his email, if the portal has this enabled
        if CosinnusPortal.get_current().email_needs_verification:
            
            with transaction.atomic():
                # scramble actual email so the user cant log in but can be found in the admin
                original_user_email = user.email  # don't show the scrambled emai later on
                user.email = '__unverified__%s__%s' % (str(uuid1())[:8], original_user_email)
                user.save()
                set_user_email_to_verify(user, original_user_email, self.request)
            
            messages.success(self.request, self.message_success_email_verification % {'user': original_user_email, 'email': original_user_email})

        if not CosinnusPortal.get_current().users_need_activation and not CosinnusPortal.get_current().email_needs_verification:
            messages.success(self.request, self.message_success % {'user': user.email})
            user.backend = 'cosinnus.backends.EmailAuthBackend'
            login(self.request, user)
        
        # send user registration signal
        signals.user_registered.send(sender=self, user=user)
        
        # check if there was a token group invite associated with the signup
        invite_token = self.request.POST.get('invite_token', None)
        if invite_token:
            invite = get_object_or_None(CosinnusGroupInviteToken, token__iexact=invite_token, portal=CosinnusPortal.get_current())
            if not invite:
                messages.warning(self.request, _('The invite token you have used does not exist!'))
            elif not invite.is_active:
                messages.warning(self.request, _('Sorry, but the invite token you have used is not active yet or not active anymore!'))
            else:
                success = apply_group_invite_token_for_user(invite, user)
                if success:
                    messages.success(self.request, _('Token invitations applied. You are now a member of the associated projects/groups!'))
                else:
                    messages.error(self.request, _('There was an error while processing your invites. Some of your invites may not have been applied.'))
        
        if getattr(settings, 'COSINNUS_SHOW_WELCOME_SETTINGS_PAGE', True):
            # add redirect to the welcome-settings page, with priority so that it is shown as first one
            profile.add_redirect_on_next_page(redirect_with_next(reverse('cosinnus:welcome-settings'), self.request), message=None, priority=True)
        
        return ret
Exemplo n.º 27
0
def map_detail_endpoint(request):
    """ Maps API object detail endpoint using pSQL results. For parameters see ``MAP_DETAIL_PARAMETERS``
        returns JSON with the contents of type ``DetailedMapResult``
    """
    params = _collect_parameters(request.GET, MAP_DETAIL_PARAMETERS)
    portal = params['portal']
    slug = params['slug']
    model_type = params['type']

    if not is_number(portal) or portal < 0:
        return HttpResponseBadRequest(
            '``portal`` param must be a positive number!')
    if not slug:
        return HttpResponseBadRequest('``slug`` param must be supplied!')
    slug = force_text(slug)  # stringify is necessary for number-only slugs
    if not model_type or not isinstance(model_type, six.string_types):
        return HttpResponseBadRequest(
            '``type`` param must be supplied and be a string!')

    if portal == 0:
        portal = CosinnusPortal.get_current().id

    # try to retrieve the requested object
    model = SEARCH_MODEL_NAMES_REVERSE.get(model_type, None)
    if model is None:
        return HttpResponseBadRequest(
            '``type`` param indicated an invalid data model type!')

    # TODO: for groups/projects we should really use the cache here.
    if model_type == 'people':
        # UserProfiles are retrieved independent of the portal
        obj = get_object_or_None(get_user_profile_model(), user__username=slug)
    elif model_type == 'events':
        group_slug, event_slug = slug.split('*', 1)
        obj = get_object_or_None(model,
                                 group__portal__id=portal,
                                 group__slug=group_slug,
                                 slug=event_slug)
    else:
        obj = get_object_or_None(model, portal__id=portal, slug=slug)
    if obj is None:
        return HttpResponseNotFound(
            'No item found that matches the requested type and slug (obj: %s, %s, %s).'
            % (escape(force_text(model)), portal, slug))

    # check read permission
    if not model_type in SEARCH_MODEL_TYPES_ALWAYS_READ_PERMISSIONS and not check_object_read_access(
            obj, request.user):
        return HttpResponseForbidden(
            'You do not have permission to access this item.')

    # get the basic result data from the search index (as it is already prepared and faster to access there)
    haystack_result = get_searchresult_by_args(portal, model_type, slug)
    if not haystack_result:
        return HttpResponseNotFound(
            'No item found that matches the requested type and slug (index: %s, %s, %s).'
            % (portal, model_type, slug))

    # format data
    result_model = SEARCH_RESULT_DETAIL_TYPE_MAP[model_type]
    result = result_model(haystack_result, obj, request.user)

    data = {
        'result': result,
    }
    return JsonResponse(data)
Exemplo n.º 28
0
def create_user_integrated(request):
    if request.method == "POST":
        # spam protection
        # TODO: FIXME: not working right now, because of different session keys for each ajax cross-site POST :/
        session_key = request.session._get_or_create_session_key()
        if cache.get(CREATE_INTEGRATED_USER_SESSION_CACHE_KEY % session_key):
            return HttpResponseBadRequest(
                'You have been doing this too often. Slow down!')

        user_email = request.POST.get('user_email', None)
        existing_username = request.POST.get('existing_username', None)
        # this is actually the hashed password of the remote user
        user_password = request.POST.get('user_password', None)
        if not user_email or not user_password:
            return HttpResponseBadRequest('Missing POST parameters!')
        first_name = request.POST.get('first_name', '')
        last_name = request.POST.get('last_name', '')

        # handshake on the integrating server, url from settings, NEVER FROM REQUEST!
        handshake_url = getattr(settings,
                                'COSINNUS_INTEGRATED_PORTAL_HANDSHAKE_URL',
                                None)
        if not handshake_url:
            raise ImproperlyConfigured(
                'Cannot create integrated user: COSINNUS_INTEGRATED_PORTAL_HANDSHAKE_URL is not configured in settings!'
            )

        data = {
            'user_email': user_email,
        }
        logger.warn('Sending handshake request.',
                    extra={
                        'data': data,
                        'url': handshake_url
                    })

        req = requests.post(handshake_url, data=data, verify=False)
        logger.warn('Handshake request returned.',
                    extra={
                        'status': req.status_code,
                        'content': req._content
                    })

        if not req.status_code == 200:
            logger.error(
                'Failed to send handshake! Have you configured the correct COSINNUS_INTEGRATED_PORTAL_HANDSHAKE_URL?',
                extra={
                    'returned_request': req,
                    'handshake_url': handshake_url,
                    'content': req._content
                })
            return HttpResponseBadRequest(
                'Could not create integrated user: Handshake could not be established! Code: %d'
                % req.status_code)

        response = req.json()
        if not response['status'] == 'ok':
            return HttpResponseBadRequest(
                'Could not create integrated user: Handshake failed!')

        # handshake succeeded, either create new user or connect to existing one
        user = None
        if existing_username:
            try:
                user = USER_MODEL.objects.get(username=existing_username)
                # we had already connected to a useraccount, so take this one
                # (the external mail might be different, so do not try to match over that,
                # as it would switch the user on the cosinnus side!)
            except USER_MODEL.DoesNotExist:
                logger.error(
                    'Cosinnus integration tried to retrieve a previously connected user, but user with username "%s" could not be found! Aborting user integration!'
                    % existing_username)
                return HttpResponseBadRequest(
                    'Cosinnus integration tried to retrieve a previously connected user, but user with username "%s" could not be found! Aborting user integration!'
                    % existing_username)

        if not user:
            try:
                user = USER_MODEL.objects.get(email=user_email)
                # user already exists for this email, but wasn't connected
                # since we trust both servers, we connect the existing user account
            except USER_MODEL.DoesNotExist:
                user = None

        logger.warn('Finding existing user.', extra={'user': user})

        # create new user if not existed
        if user is None:
            password = '******'
            data = {
                'username': user_email,
                'email': user_email,
                'password1': password,
                'password2': password,
                'first_name': first_name,
                'last_name': last_name,
                'tos_check': True,
            }
            # use Cosinnus' UserCreationForm to apply all usual user-creation-related effects
            form = UserCreationForm(data)
            if form.is_valid():
                user = form.save()
            else:
                logger.warn('User form invalid.',
                            extra={'errors': force_text(form.errors)})
                return JSONResponse(data={
                    'status': 'fail',
                    'reason': force_text(form.errors)
                })
            get_user_profile_model()._default_manager.get_for_user(user)

            # set the new user's password's hash to that of the connected user.
            user.password = user_password
            user.save()
            logger.warn('Cosinnus integration: User saved.',
                        extra={'user': user})
        else:
            # user existed before, update first_name, last_name.
            # NEVER update the password to prevent account hijacking through a faked email!

            user.first_name = first_name
            user.last_name = last_name
            user.save()
            logger.warn('Cosinnus integration: User names updated.',
                        extra={'user': user})

        # if we got an avatar sent with the request, always update/save it to the new user's profile
        if request.FILES and 'avatar' in request.FILES:
            user.cosinnus_profile.avatar = request.FILES.get('avatar')
            logger.warn('Cosinnus integration: Avatar saved/updated.',
                        extra={'user': user})

        # always accept terms of service automatically in integrated portals
        accept_user_tos_for_portal(user)

        # retransmit a hashed version of the hashed password.
        # yes, we double hash the original password. because then the first password hash
        # is only exposed once, during user creation, and never again after that.
        # all that is exposed to the client afterwards is a double hash, making this a bit cleaner.
        remote_password = IntegratedHasher.encode(user.password, salt)

        # set session key into cache
        cache.set(CREATE_INTEGRATED_USER_SESSION_CACHE_KEY % session_key,
                  'True',
                  settings.COSINNUS_INTEGRATED_CREATE_USER_CACHE_TIMEOUT)

        logger.warn('User creation success, returning ok',
                    extra={'username': user.username})

        return JSONResponse(
            data={
                'status': 'ok',
                'remote_username': user.username,
                'remote_password': remote_password
            })

    else:
        raise Http404
Exemplo n.º 29
0
 class Meta:
     model = get_user_profile_model()
     fields = model.get_optional_fieldnames()
Exemplo n.º 30
0
def create_base_user(email,
                     username=None,
                     password=None,
                     first_name=None,
                     last_name=None,
                     no_generated_password=False):
    """ :param no_generated_password: set password generation behaviour. If False Password will be kept with None
        :type no_generated_password: bool | default False
    """

    from django.contrib.auth.forms import UserCreationForm
    from cosinnus.models.profile import get_user_profile_model
    from cosinnus.models.group import CosinnusPortalMembership, CosinnusPortal
    from cosinnus.models.membership import MEMBERSHIP_MEMBER
    from cosinnus.views.user import email_first_login_token_to_user
    from django.contrib.auth import get_user_model
    from django.core.exceptions import ObjectDoesNotExist

    try:
        user_model = get_user_model()
        user_model.objects.get(email__iexact=email)
        logger.warning(
            'Manual user creation failed because email already exists!')
        return False
    except ObjectDoesNotExist:
        pass

    if not password and no_generated_password:
        # special handling for user without password
        user_model = get_user_model()
        temp_username = email if not username else username

        # check if user with that password already exist
        user, created = user_model.objects.get_or_create(
            username=temp_username, email=email)

        email_first_login_token_to_user(user=user)
        if not created:
            logger.error(
                'Manual user creation failed. A user with tha username already exists!'
            )

    else:
        password = get_random_string()

        user_data = {
            'username': username or get_random_string(),
            'password1': password,
            'password2': password
        }

        form = UserCreationForm(user_data)
        if form.is_valid():
            user = form.save()
        else:
            logger.warning(
                'Manual user creation failed because of form errors!',
                extra={
                    'data': user_data,
                    'form-errors': form.errors
                })
            return False

    user.email = email
    if not username:
        user.username = user.id
    if first_name:
        user.first_name = first_name
    if last_name:
        user.last_name = last_name
    user.backend = 'cosinnus.backends.EmailAuthBackend'
    user.save()

    CosinnusPortalMembership.objects.get_or_create(
        group=CosinnusPortal.get_current(),
        user=user,
        defaults={'status': MEMBERSHIP_MEMBER})

    profile = get_user_profile_model()._default_manager.get_for_user(user)
    profile.settings['tos_accepted'] = False
    profile.save()

    return user