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)
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
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}
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)
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
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)
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
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
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'), '']
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}
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)
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)
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
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
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)
def get_model(self): return get_user_profile_model()
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))
# -*- 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()
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', )
class Meta(BaseUserProfileSerializer.Meta): model = get_user_profile_model()
}) 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
class Meta(object): model = get_user_profile_model() fields = ('id', 'avatar')
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
class Meta(BaseUserProfileSerializer.Meta): model = get_user_profile_model() fields = BaseUserProfileSerializer.Meta.fields + ('avatar', )
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
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)
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
class Meta: model = get_user_profile_model() fields = model.get_optional_fieldnames()
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