예제 #1
0
 def testChangeUsername(self):
     new_username = '******'
     self.assertEqual(CouchUser.get_by_username(self.username).user_id, self.couch_user.user_id)
     self.assertEqual(User.objects.filter(username=self.username).count(), 1)
     self.couch_user.change_username(new_username)
     self.assertEqual(CouchUser.get_by_username(self.username), None)
     self.assertEqual(CouchUser.get_by_username(new_username).user_id, self.couch_user.user_id)
     self.assertEqual(self.couch_user.get_django_user().username, new_username)
     self.assertEqual(User.objects.filter(username=new_username).count(), 1)
     self.assertEqual(User.objects.get(username=new_username).id, self.couch_user.get_django_user().id)
     self.assertEqual(User.objects.filter(username=self.username).count(), 0)
예제 #2
0
파일: v0_4.py 프로젝트: ekush/commcare-hq
    def post_list(self, request, **kwargs):
        domain = kwargs.get('domain')
        request.domain = domain
        username = request.POST.get('username')
        password = request.POST.get('password')

        if username is None:
            return HttpResponseBadRequest('Missing required parameter: username')

        if password is None:
            return HttpResponseBadRequest('Missing required parameter: password')

        if '@' not in username:
            username = format_username(username, domain)

        # Convert to the appropriate type of user
        couch_user = CouchUser.get_by_username(username)
        if couch_user is None or not couch_user.is_member_of(domain) or not couch_user.check_password(password):
            return HttpResponseForbidden()

        if couch_user.is_commcare_user():
            user_resource = v0_1.CommCareUserResource()
        elif couch_user.is_web_user():
            user_resource = v0_1.WebUserResource()
        else:
            return HttpResponseForbidden()

        bundle = user_resource.build_bundle(obj=couch_user, request=request)
        bundle = user_resource.full_dehydrate(bundle)
        return user_resource.create_response(request, bundle, response_class=HttpResponse)
예제 #3
0
    def handle(self, *args, **options):
        self.last_submitter = options.get('last_submitter', False)
        if not len(args):
            print "Usage: ./manage.py delete_cases <user>"
            return
        try:
            self.user = CouchUser.get_by_username(args[0])
            if not self.user:
                self.user = CouchUser.get(args[0])
        except ResourceNotFound:
            print "Could not find user {}".format(args[0])
            return

        if not options.get('no_prompt'):
            msg = "Delete all {} cases {} by {}? (y/n)\n".format(
                self.get_case_count(),
                "submitted" if self.last_submitter else "owned",
                self.user.username,
            )
            if not raw_input(msg) == 'y':
                print "cancelling"
                return

        self.delete_all()
        print "Cases successfully deleted, you monster!"
예제 #4
0
    def handle(self, path, app_id, **options):
        if options['deploy'] and not options['user']:
            raise CommandError('Deploy argument requires a user')
        elif options['deploy']:
            user = CouchUser.get_by_username(options['user'])
            if not user:
                raise CommandError("Couldn't find user with username {}".format(options['user']))

        app = Application.get(app_id)
        for module_dir in os.listdir(path):
            module_index, name = module_dir.split(' - ')
            module = app.get_module(int(module_index))
            for form_name in os.listdir(os.path.join(path, module_dir)):
                form_index, name = form_name.split(' - ')
                form = module.get_form(int(form_index))
                with open(os.path.join(path, module_dir, form_name), 'rb') as f:
                    save_xform(app, form, f.read())

        app.save()
        print('successfully updated {}'.format(app.name))
        if options['deploy']:
            # make build and star it
            comment = options.get('comment', 'form changes from {0}'.format(datetime.utcnow().strftime(SERVER_DATETIME_FORMAT_NO_SEC)))
            copy = app.make_build(
                comment=comment,
                user_id=user._id,
            )
            copy.is_released = True
            copy.save(increment_version=False)
            print('successfully released new version')
예제 #5
0
    def post(self, request, *args, **kwargs):
        if self.invite_web_user_form.is_valid():
            # If user exists and has already requested access, just add them to the project
            # Otherwise, send an invitation
            create_invitation = True
            data = self.invite_web_user_form.cleaned_data
            domain_request = DomainRequest.by_email(self.domain, data["email"])
            if domain_request is not None:
                domain_request.is_approved = True
                domain_request.save()
                user = CouchUser.get_by_username(domain_request.email)
                if user is not None:
                    domain_request.send_approval_email()
                    create_invitation = False
                    user.add_as_web_user(self.domain, role=data["role"],
                                         location_id=data.get("supply_point", None),
                                         program_id=data.get("program", None))
                messages.success(request, "%s added." % data["email"])
            else:
                messages.success(request, "Invitation sent to %s" % data["email"])

            if create_invitation:
                data["invited_by"] = request.couch_user.user_id
                data["invited_on"] = datetime.utcnow()
                data["domain"] = self.domain
                invite = DomainInvitation(**data)
                invite.save()
                invite.send_activation_email()
            return HttpResponseRedirect(reverse(
                ListWebUsersView.urlname,
                args=[self.domain]
            ))
        return self.get(request, *args, **kwargs)
예제 #6
0
def claim(request, domain):
    """
    Allows a user to claim a case that they don't own.
    """
    as_user = request.POST.get('commcare_login_as', None)
    as_user_obj = CouchUser.get_by_username(as_user) if as_user else None
    restore_user = get_restore_user(domain, request.couch_user, as_user_obj)

    case_id = request.POST.get('case_id', None)
    if case_id is None:
        return HttpResponse('A case_id is required', status=400)

    try:
        if get_first_claim(domain, restore_user.user_id, case_id):
            return HttpResponse('You have already claimed that {}'.format(request.POST.get('case_type', 'case')),
                                status=409)

        claim_case(domain, restore_user.user_id, case_id,
                   host_type=request.POST.get('case_type'),
                   host_name=request.POST.get('case_name'),
                   device_id=__name__ + ".claim")
    except CaseNotFound:
        return HttpResponse('The case "{}" you are trying to claim was not found'.format(case_id),
                            status=410)
    return HttpResponse(status=200)
예제 #7
0
def get_id_from_name(uploaded_name, domain, cache):
    '''
    :param uploaded_name: A username or group name
    :param domain:
    :param cache:
    :return: Looks for the given name and returns the corresponding id if the
    user or group exists and None otherwise. Searches for user first, then
    group.
    '''
    if uploaded_name in cache:
        return cache[uploaded_name]
    try:
        name_as_address = uploaded_name
        if '@' not in name_as_address:
            name_as_address = format_username(uploaded_name, domain)
        user = CouchUser.get_by_username(name_as_address)
        id = getattr(user, 'couch_id', None)
    except NoResultFound:
        id = None
    if not id:
        group = Group.by_name(domain, uploaded_name, one=True)
        id = getattr(group, 'get_id', None)

    cache[uploaded_name] = id
    return id
예제 #8
0
    def handle(self, *args, **options):
        if not len(args):
            print "Usage: ./manage.py delete_cases <user>"
            return
        try:
            self.user = CouchUser.get_by_username(args[0])
            if not self.user:
                self.user = CouchUser.get(args[0])
        except ResourceNotFound:
            print "Could not find user {}".format(args[0])
            return

        if not isinstance(self.user, CommCareUser):
            print ("Sorry, the user you specify has to be a mobile worker. "
                   "This changed when delete_cases was refactored to use "
                   "cases_by_owner/view instead of case/by_owner. "
                   "The new view needs an explicit domain, "
                   "and I didn't implement that for WebUsers who can belong "
                   "to multiple domains, but usually do not own cases.")
            exit(1)

        self.domain = self.user.domain

        if not options.get('no_prompt'):
            msg = "Delete all cases owned by {}? (y/n)\n".format(
                self.user.username,
            )
            if not raw_input(msg) == 'y':
                print "cancelling"
                return

        self.delete_all()
        print "Cases successfully deleted, you monster!"
예제 #9
0
def is_permitted_to_restore(domain, couch_user, as_user, has_data_cleanup_privilege):
    """
    This function determines if the couch_user is permitted to restore
    for the domain and/or as_user
    :param domain: Domain of restore
    :param couch_user: The couch user attempting authentication
    :param as_user: a string username that the couch_user is attempting to get
        a restore for. If None will get restore of the couch_user.
    :param has_data_cleanup_privelege: Whether the user has permissions to do DATA_CLEANUP
    :returns: a tuple - first a boolean if the user is permitted,
        secondly a message explaining why a user was rejected if not permitted
    """
    try:
        _ensure_valid_domain(domain, couch_user)
        if as_user is not None and not _restoring_as_yourself(couch_user, as_user):
            as_user_obj = CouchUser.get_by_username(as_user)
            if not as_user_obj:
                raise RestorePermissionDenied(_(u'Invalid restore as user {}').format(as_user))

            _ensure_cleanup_permission(domain, couch_user, as_user_obj, has_data_cleanup_privilege)
            _ensure_valid_restore_as_user(domain, couch_user, as_user_obj)
            _ensure_accessible_location(domain, couch_user, as_user_obj)
            _ensure_edit_data_permission(domain, couch_user)
    except RestorePermissionDenied as e:
        return False, unicode(e)
    else:
        return True, None
예제 #10
0
 def _inner(request, *args, **kwargs):
     username = _get_username_from_request(request)
     user = CouchUser.get_by_username(username)
     if user and user.is_web_user() and user.is_locked_out():
         return json_response({_("error"): _("maximum password attempts exceeded")}, status_code=401)
     else:
         return fn(request, *args, **kwargs)
예제 #11
0
 def check_username_availability(self, data):
     email = data['email'].strip()
     duplicate = CouchUser.get_by_username(email)
     is_existing = User.objects.filter(username__iexact=email).count() > 0 or duplicate
     return {
         'isValid': not is_existing,
     }
예제 #12
0
    def filter_context(self):
        api_root = reverse('api_dispatch_list', kwargs={'domain': self.domain,
                                                        'resource_name': 'location',
                                                        'api_name': 'v0.3'})
        selected_loc_id = self.request.GET.get('location_id')
        user = CouchUser.get_by_username(unicode(self.request.user))
        domain = Domain.get_by_name(self.domain)

        context = {}
        location_id = None

        domain_membership = user.get_domain_membership(self.domain)
        if domain_membership:
            location_id = domain_membership.location_id

        if not selected_loc_id and location_id and domain.commtrack_enabled:
            selected_loc_id = location_id
            if domain.location_restriction_for_users:
                context.update({'restriction': domain.location_restriction_for_users})

        context.update({
            'api_root': api_root,
            'control_name': self.label, # todo: cleanup, don't follow this structure
            'control_slug': self.slug, # todo: cleanup, don't follow this structure
            'loc_id': selected_loc_id,
            'locations': json.dumps(load_locs_json(self.domain, selected_loc_id)),
            'hierarchy': location_hierarchy_config(self.domain)
        })

        return context
예제 #13
0
    def handle(self, user, **options):
        try:
            self.user = CouchUser.get_by_username(user)
            if not self.user:
                self.user = CouchUser.get(user)
        except ResourceNotFound:
            print("Could not find user {}".format(user))
            return

        if not isinstance(self.user, CommCareUser):
            print ("Sorry, the user you specify has to be a mobile worker. "
                   "This changed when delete_cases was refactored to use "
                   "cases_by_owner/view instead of case/by_owner. "
                   "The new view needs an explicit domain, "
                   "and I didn't implement that for WebUsers who can belong "
                   "to multiple domains, but usually do not own cases.")
            exit(1)

        self.domain = self.user.domain

        if should_use_sql_backend(self.domain):
            raise CommandError('This command only works for couch-based domains.')

        if not options.get('no_prompt'):
            msg = "Delete all cases owned by {}? (y/n)\n".format(
                self.user.username,
            )
            if not input(msg) == 'y':
                print("cancelling")
                return

        self.delete_all()
        print("Cases successfully deleted, you monster!")
예제 #14
0
파일: views.py 프로젝트: dimagi/commcare-hq
    def get_restore_as_user(request, domain):
        """
        returns (user, set_cookie), where set_cookie is a function to be called on
        the eventual response
        """

        if not hasattr(request, 'couch_user'):
            raise Http404()

        def set_cookie(response):  # set_coookie is a noop by default
            return response

        cookie_name = six.moves.urllib.parse.quote(
            'restoreAs:{}:{}'.format(domain, request.couch_user.username))
        username = request.COOKIES.get(cookie_name)
        if username:
            user = CouchUser.get_by_username(format_username(username, domain))
            if user:
                return user, set_cookie
            else:
                def set_cookie(response):  # overwrite the default noop set_cookie
                    response.delete_cookie(cookie_name)
                    return response

        return request.couch_user, set_cookie
예제 #15
0
파일: api.py 프로젝트: sheelio/commcare-hq
    def add_language_to_user(self, logistics_sms_user):
        domain_part = "%s.commcarehq.org" % self.domain
        username_part = "%s%d" % (logistics_sms_user.name.strip().replace(' ', '.').lower(),
                                  logistics_sms_user.id)
        username = "******" % (username_part[:(128 - (len(domain_part) + 1))], domain_part)
        user = CouchUser.get_by_username(username)
        if not user:
            return

        if user.language != logistics_sms_user.language:
            user.language = logistics_sms_user.language
            user.save()

        logistics_numbers = {apply_leniency(phone_number) for phone_number in logistics_sms_user.phone_numbers}
        if set(user.phone_numbers) == logistics_numbers:
            return

        for phone_number in user.phone_numbers:
            user.delete_phone_number(phone_number)

        if logistics_sms_user.phone_numbers:
            phone_number = apply_leniency(logistics_sms_user.phone_numbers[0])
            if not phone_number:
                return
            user.set_default_phone_number(phone_number)
            self._save_verified_number(user, phone_number)
예제 #16
0
    def post(self, request, *args, **kwargs):
        try:
            data = json.loads(request.body)
        except ValueError:
            return HttpResponseBadRequest()

        if not data or not isinstance(data, dict):
            return HttpResponseBadRequest()

        session_id = data.get('sessionId', None)
        if not session_id:
            return HttpResponseBadRequest()

        user = get_django_user_from_session_key(session_id)
        if user:
            couch_user = CouchUser.get_by_username(user.username)
            if not couch_user:
                raise Http404
        else:
            raise Http404

        return JsonResponse({
            'username': user.username,
            'djangoUserId': user.pk,
            'superUser': user.is_superuser,
            'authToken': None,
            'domains': couch_user.domains,
            'anonymous': False
        })
예제 #17
0
def claim(request, domain):
    """
    Allows a user to claim a case that they don't own.
    """
    as_user = unquote(request.POST.get('commcare_login_as', ''))
    as_user_obj = CouchUser.get_by_username(as_user) if as_user else None
    restore_user = get_restore_user(domain, request.couch_user, as_user_obj)

    case_id = unquote(request.POST.get('case_id', ''))
    if not case_id:
        return HttpResponse('A case_id is required', status=400)

    try:
        if get_first_claim(domain, restore_user.user_id, case_id):
            return HttpResponse('You have already claimed that {}'.format(
                request.POST.get('case_type', 'case')),
                                status=409)

        claim_case(domain,
                   restore_user.user_id,
                   case_id,
                   host_type=unquote(request.POST.get('case_type', '')),
                   host_name=unquote(request.POST.get('case_name', '')),
                   device_id=__name__ + ".claim")
    except CaseNotFound:
        return HttpResponse(
            'The case "{}" you are trying to claim was not found'.format(
                case_id),
            status=410)
    return HttpResponse(status=200)
예제 #18
0
    def handle(self, account_id, username, **kwargs):
        self.couch_user = CouchUser.get_by_username(username)
        self.account_id = account_id

        if not self.couch_user:
            raise CommandError("Option: '--username' must be specified")

        self.now = datetime.utcnow()
        account = BillingAccount.objects.get(id=account_id)
        message = ''
        if kwargs.get('message'):
            message += kwargs.get('message') + "\n"
        message += "Report run {}\n".format(datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S'))

        attachments = []
        for slug in (
            EnterpriseReport.DOMAINS,
            EnterpriseReport.WEB_USERS,
            EnterpriseReport.MOBILE_USERS,
            EnterpriseReport.FORM_SUBMISSIONS,
        ):
            (attachment, count) = self._write_file(slug)
            attachments.append(attachment)
            message += "{}: {}\n".format(slug, count)

        cc = []
        if kwargs.get('cc'):
            cc = kwargs.get('cc').split(",")
        send_html_email_async(
            "Report on enterprise account {}".format(account.name), self.couch_user.username,
            linebreaksbr(message), cc=cc, text_content=message, file_attachments=attachments,
        )
        print('Emailed {}{}{}'.format(self.couch_user.username, " and " if cc else "", ", ".join(cc)))
예제 #19
0
def clear_login_attempts(user):
    if user and user.login_attempts > 0:
        try:
            user.login_attempts = 0
            user.save()
        except ResourceConflict:
            updated_user = CouchUser.get_by_username(user.username)
            clear_login_attempts(updated_user)
예제 #20
0
 def check_username_availability(self, data):
     email = data['email'].strip()
     duplicate = CouchUser.get_by_username(email)
     is_existing = User.objects.filter(
         username__iexact=email).count() > 0 or duplicate
     return {
         'isValid': not is_existing,
     }
예제 #21
0
 def clean(self):
     lockout_message = mark_safe(_('Sorry - you have attempted to login with an incorrect password too many times. Please <a href="/accounts/password_reset_email/">click here</a> to reset your password.'))
     username = self.cleaned_data.get('username')
     if username is None:
         raise ValidationError(_('Please enter a valid email address.'))
     try:
         cleaned_data = super(EmailAuthenticationForm, self).clean()
     except ValidationError:
         user = CouchUser.get_by_username(username)
         if user and user.is_web_user() and user.is_locked_out():
             raise ValidationError(lockout_message)
         else:
             raise
     user = CouchUser.get_by_username(username)
     if user and user.is_web_user() and user.is_locked_out():
         raise ValidationError(lockout_message)
     return cleaned_data
예제 #22
0
 def get_user(name):
     try:
         name_as_address = name
         if '@' not in name_as_address:
             name_as_address = format_username(name, self.domain)
         return CouchUser.get_by_username(name_as_address)
     except NoResultFound:
         return None
예제 #23
0
 def clean(self):
     try:
         cleaned_data = super(HQBackupTokenForm, self).clean()
     except ValidationError:
         user_login_failed.send(
             sender=__name__, credentials={'username': self.user.username})
         couch_user = CouchUser.get_by_username(self.user.username)
         if couch_user and couch_user.is_locked_out(
         ) and couch_user.supports_lockout():
             raise ValidationError(LOCKOUT_MESSAGE)
         else:
             raise
     couch_user = CouchUser.get_by_username(self.user.username)
     if couch_user and couch_user.is_locked_out(
     ) and couch_user.supports_lockout():
         raise ValidationError(LOCKOUT_MESSAGE)
     return cleaned_data
예제 #24
0
def _login(req, domain_name, custom_login_page, extra_context=None):
    extra_context = extra_context or {}
    if req.user.is_authenticated and req.method == "GET":
        redirect_to = req.GET.get('next', '')
        if redirect_to:
            return HttpResponseRedirect(redirect_to)
        if not domain_name:
            return HttpResponseRedirect(reverse('homepage'))
        else:
            return HttpResponseRedirect(reverse('domain_homepage', args=[domain_name]))

    if req.method == 'POST' and domain_name and '@' not in req.POST.get('auth-username', '@'):
        with mutable_querydict(req.POST):
            req.POST['auth-username'] = format_username(req.POST['auth-username'], domain_name)

    if 'auth-username' in req.POST:
        couch_user = CouchUser.get_by_username(req.POST['auth-username'].lower())
        if couch_user:
            new_lang = couch_user.language
            old_lang = req.session.get(LANGUAGE_SESSION_KEY)
            update_session_language(req, old_lang, new_lang)

    req.base_template = settings.BASE_TEMPLATE

    context = {}
    template_name = custom_login_page if custom_login_page else 'login_and_password/login.html'
    if not custom_login_page and domain_name:
        domain_obj = Domain.get_by_name(domain_name)
        req_params = req.GET if req.method == 'GET' else req.POST
        context.update({
            'domain': domain_name,
            'hr_name': domain_obj.display_name(),
            'next': req_params.get('next', '/a/%s/' % domain_name),
            'allow_domain_requests': domain_obj.allow_domain_requests,
            'current_page': {'page_name': _('Welcome back to %s!') % domain_obj.display_name()},
        })
    else:
        commcare_hq_name = commcare_hq_names(req)['commcare_hq_names']["COMMCARE_HQ_NAME"]
        context.update({
            'current_page': {'page_name': _('Welcome back to %s!') % commcare_hq_name},
        })
    if settings.SERVER_ENVIRONMENT in settings.ICDS_ENVS:
        auth_view = CloudCareLoginView
    else:
        auth_view = HQLoginView if not domain_name else CloudCareLoginView

    demo_workflow_ab_v2 = ab_tests.SessionAbTest(ab_tests.DEMO_WORKFLOW_V2, req)

    if settings.IS_SAAS_ENVIRONMENT:
        context['demo_workflow_ab_v2'] = demo_workflow_ab_v2.context

    context.update(extra_context)
    response = auth_view.as_view(template_name=template_name, extra_context=context)(req)

    if settings.IS_SAAS_ENVIRONMENT:
        demo_workflow_ab_v2.update_response(response)

    return response
예제 #25
0
파일: views.py 프로젝트: soitun/commcare-hq
    def get_restore_as_user(request, domain):
        """
        returns (user, set_cookie), where set_cookie is a function to be called on
        the eventual response
        """

        if not hasattr(request, 'couch_user'):
            raise Http404()

        def set_cookie(response):  # set_coookie is a noop by default
            return response

        cookie_name = urllib.parse.quote('restoreAs:{}:{}'.format(
            domain, request.couch_user.username))
        username = request.COOKIES.get(cookie_name)
        if username:
            user = CouchUser.get_by_username(format_username(username, domain))
            if user:
                return user, set_cookie
            else:

                def set_cookie(
                        response):  # overwrite the default noop set_cookie
                    response.delete_cookie(cookie_name)
                    return response

        elif request.couch_user.has_permission(domain, 'limited_login_as'):
            login_as_users = login_as_user_query(domain,
                                                 request.couch_user,
                                                 search_string='',
                                                 limit=1,
                                                 offset=0).run()
            if login_as_users.total == 1:

                def set_cookie(response):
                    response.set_cookie(cookie_name,
                                        user.raw_username,
                                        secure=settings.SECURE_COOKIES)
                    return response

                user = CouchUser.get_by_username(
                    login_as_users.hits[0]['username'])
                return user, set_cookie

        return request.couch_user, set_cookie
예제 #26
0
def add_failed_attempt(sender, credentials, **kwargs):
    user = CouchUser.get_by_username(credentials['username'])
    if user and not user.is_locked_out() and user.supports_lockout():
        if user.attempt_date == date.today():
            user.login_attempts += 1
        else:
            user.login_attempts = 1
            user.attempt_date = date.today()
        user.save()
예제 #27
0
 def get_from_user(name):
     try:
         name_as_address = name
         if '@' not in name_as_address:
             name_as_address = format_username(name, domain)
         user = CouchUser.get_by_username(name_as_address)
         return getattr(user, 'couch_id', None)
     except NoResultFound:
         return None
예제 #28
0
def check_user_access(domain, username, allow_mirroring=False):
    from corehq.apps.users.util import format_username
    from corehq.apps.users.models import CouchUser
    if '@' not in username:
        username = format_username(username, domain)
    user = CouchUser.get_by_username(username)
    if not user.is_member_of(domain, allow_mirroring=allow_mirroring):
        raise FormplayerAPIException(f"User '{username}' does not have access to domain '{domain}'")
    return user
예제 #29
0
파일: api.py 프로젝트: johan--/commcare-hq
 def _set_in_charges(self, ews_user_id, location):
     ews_sms_user = self.endpoint.get_smsuser(ews_user_id)
     sms_user = CouchUser.get_by_username(self.get_username(ews_sms_user)[0])
     if not sms_user:
         sms_user = self.sms_user_sync(ews_sms_user)
     FacilityInCharge.objects.get_or_create(
         location=location,
         user_id=sms_user.get_id
     )
예제 #30
0
 def _inner(request, *args, **kwargs):
     username = _get_username_from_request(request)
     user = CouchUser.get_by_username(username)
     if user and user.is_web_user() and user.is_locked_out():
         return json_response(
             {_("error"): _("maximum password attempts exceeded")},
             status_code=401)
     else:
         return fn(request, *args, **kwargs)
예제 #31
0
 def process_response(self, request, response):
     if is_login_page(
             request) and request.user.is_authenticated and is_icds_domain(
                 request):
         couch_user = CouchUser.get_by_username(request.user.username)
         ICDSAuditEntryRecord.create_entry(request,
                                           couch_user,
                                           is_login_page=True)
     return response
예제 #32
0
 def get_from_user(name):
     try:
         name_as_address = name
         if '@' not in name_as_address:
             name_as_address = format_username(name, domain)
         user = CouchUser.get_by_username(name_as_address)
         return getattr(user, 'couch_id', None)
     except NoResultFound:
         return None
예제 #33
0
def add_failed_attempt(sender, credentials, **kwargs):
    user = CouchUser.get_by_username(credentials['username'])
    if user and not user.is_locked_out() and user.supports_lockout():
        if user.attempt_date == date.today():
            user.login_attempts += 1
        else:
            user.login_attempts = 1
            user.attempt_date = date.today()
        user.save()
예제 #34
0
def validate_row(row, domain, data_cols):
    """pre-validate the information in a particular import row: valid location,
    reporting user, and data formats
    """
    # identify location
    loc_code = row.get('outlet_code') or row.get('site_code')
    row['loc'] = get_supply_point(domain, loc_code)['case']
    if row['loc'] is None:
        set_error(row, 'ERROR location code is invalid')
        return

    # identify user
    phone = row.get('phone')
    owner = None
    if phone:
        vn = VerifiedNumber.by_phone(phone)
        if not vn:
            set_error(row, 'ERROR phone number is not verified with any user')
            return
        owner = vn.owner
        row['phone'] = strip_plus(phone)

    username = row.get('reporter')
    if username:
        user = CouchUser.get_by_username('%s@%s.commcarehq.org' % (username, domain))
        if not user:
            set_error(row, 'ERROR reporter user does not exist')
            return

    if owner:
        if user and user._id != owner._id:
            set_error(row, 'ERROR phone number does not belong to user')
            return
        user = owner
    row['user'] = user

    # validate other fields

    try:
        row['timestamp'] = datetime.strptime(row['date'], '%Y-%m-%d') # TODO: allow time?
    except ValueError:
        set_error(row, 'ERROR invalid date format')
        return

    for k in data_cols:
        val = row[k]
        if val:
            try:
                int(val)
            except ValueError:
                set_error(row, 'ERROR invalid data value "%s" in column "%s"' % (val, k))
                return

    if all(not row[k] for k in data_cols):
        set_error(row, 'ERROR stock report is empty')
        return
예제 #35
0
파일: tasks.py 프로젝트: soitun/commcare-hq
def upload(dropbox_helper_id, access_token, size, max_retries):
    from .models import DropboxUploadHelper
    helper = DropboxUploadHelper.objects.get(id=dropbox_helper_id)

    def progress_callback(bytes_uploaded, helper=helper, size=size):
        helper.progress = float(bytes_uploaded) / size
        helper.save()

    try:
        dropbox_path = '/{}'.format(os.path.basename(helper.src))
        path_display = upload_to_dropbox(access_token, dropbox_path,
                                         helper.src, progress_callback)
    except Exception as e:
        helper.failure_reason = str(e)
        helper.save()

    couch_user = CouchUser.get_by_username(helper.user.username)
    if helper.failure_reason is None:
        dbx = Dropbox(access_token)
        path_link_metadata = dbx.sharing_create_shared_link_with_settings(
            path_display,
            SharedLinkSettings(
                requested_visibility=RequestedVisibility.team_only, ),
        )
        context = {
            'share_url':
            path_link_metadata.url,
            'path':
            os.path.join(
                'Apps',
                settings.DROPBOX_APP_NAME,
                path_link_metadata.name,
            )
        }
        with localize(couch_user.get_language_code()):
            subject = _('{} has been uploaded to dropbox!'.format(helper.dest))
            html_content = render_to_string(
                'dropbox/emails/upload_success.html', context)
            text_content = render_to_string(
                'dropbox/emails/upload_success.txt', context)
    else:
        context = {'reason': helper.failure_reason, 'path': helper.dest}
        with localize(couch_user.get_language_code()):
            subject = _('{} has failed to upload to dropbox'.format(
                helper.dest))
            html_content = render_to_string('dropbox/emails/upload_error.html',
                                            context)
            text_content = render_to_string('dropbox/emails/upload_error.txt',
                                            context)

    send_HTML_email(
        subject,
        helper.user.email,
        html_content,
        text_content=text_content,
    )
예제 #36
0
def validate_row(row, domain, data_cols):
    """pre-validate the information in a particular import row: valid location,
    reporting user, and data formats
    """
    # identify location
    loc_code = row.get('outlet_code') or row.get('site_code')
    row['loc'] = get_supply_point(domain, loc_code)['case']
    if row['loc'] is None:
        set_error(row, 'ERROR location code is invalid')
        return

    # identify user
    phone = row.get('phone')
    owner = None
    if phone:
        vn = VerifiedNumber.by_phone(phone)
        if not vn:
            set_error(row, 'ERROR phone number is not verified with any user')
            return
        owner = vn.owner
        row['phone'] = strip_plus(phone)

    username = row.get('reporter')
    if username:
        user = CouchUser.get_by_username('%s@%s.commcarehq.org' % (username, domain))
        if not user:
            set_error(row, 'ERROR reporter user does not exist')
            return

    if owner:
        if user and user._id != owner._id:
            set_error(row, 'ERROR phone number does not belong to user')
            return
        user = owner
    row['user'] = user

    # validate other fields

    try:
        row['timestamp'] = datetime.strptime(row['date'], '%Y-%m-%d') # TODO: allow time?
    except ValueError:
        set_error(row, 'ERROR invalid date format')
        return

    for k in data_cols:
        val = row[k]
        if val:
            try:
                int(val)
            except ValueError:
                set_error(row, 'ERROR invalid data value "%s" in column "%s"' % (val, k))
                return

    if all(not row[k] for k in data_cols):
        set_error(row, 'ERROR stock report is empty')
        return
예제 #37
0
 def clean_email(self):
     data = super().clean_email()
     # web user login emails should be globally unique
     duplicate = CouchUser.get_by_username(data)
     if duplicate:
         # sync django user
         duplicate.save()
     if User.objects.filter(username__iexact=data).count() > 0 or duplicate:
         raise forms.ValidationError('Username already taken; please try another')
     return data
예제 #38
0
 def clean_email(self):
     data = self.cleaned_data['email'].strip().lower()
     validate_email(data)
     duplicate = CouchUser.get_by_username(data)
     if duplicate:
         # sync django user
         duplicate.save()
     if User.objects.filter(username__iexact=data).count() > 0 or duplicate:
         raise forms.ValidationError('Username already taken; please try another')
     return data
예제 #39
0
    def _inner(request, *args, **kwargs):
        username, password = get_username_and_password_from_request(request)
        if not username or username.endswith('.commcarehq.org'):
            return fn(request, *args, **kwargs)

        user = CouchUser.get_by_username(username)
        if user and user.is_web_user() and user.is_locked_out():
            return json_response({_("error"): _("maximum password attempts exceeded")}, status_code=401)
        else:
            return fn(request, *args, **kwargs)
예제 #40
0
    def _inner(request, *args, **kwargs):
        username, password = get_username_and_password_from_request(request)
        if not username:
            return fn(request, *args, **kwargs)

        user = CouchUser.get_by_username(username)
        if user and user.is_locked_out() and user.supports_lockout():
            return json_response({"error": _("maximum password attempts exceeded")}, status_code=401)
        else:
            return fn(request, *args, **kwargs)
예제 #41
0
 def clean_email(self):
     data = self.cleaned_data['email'].strip().lower()
     validate_email(data)
     duplicate = CouchUser.get_by_username(data)
     if duplicate:
         # sync django user
         duplicate.save()
     if User.objects.filter(username__iexact=data).count() > 0 or duplicate:
         raise forms.ValidationError('Username already taken; please try another')
     return data
예제 #42
0
    def _inner(request, *args, **kwargs):
        username, password = get_username_and_password_from_request(request)
        if not username:
            return fn(request, *args, **kwargs)

        user = CouchUser.get_by_username(username)
        if user and user.is_locked_out() and user.supports_lockout():
            return json_response({"error": _("maximum password attempts exceeded")}, status_code=401)
        else:
            return fn(request, *args, **kwargs)
예제 #43
0
 def testChangeUsername(self):
     new_username = '******'
     self.assertEqual(
         CouchUser.get_by_username(self.username).user_id,
         self.couch_user.user_id)
     self.assertEqual(
         User.objects.filter(username=self.username).count(), 1)
     self.couch_user.change_username(new_username)
     self.assertEqual(CouchUser.get_by_username(self.username), None)
     self.assertEqual(
         CouchUser.get_by_username(new_username).user_id,
         self.couch_user.user_id)
     self.assertEqual(self.couch_user.get_django_user().username,
                      new_username)
     self.assertEqual(User.objects.filter(username=new_username).count(), 1)
     self.assertEqual(
         User.objects.get(username=new_username).id,
         self.couch_user.get_django_user().id)
     self.assertEqual(
         User.objects.filter(username=self.username).count(), 0)
예제 #44
0
def add_failed_attempt(sender, credentials, **kwargs):
    user = CouchUser.get_by_username(credentials['username'])
    if user and (user.is_web_user() or toggles.MOBILE_LOGIN_LOCKOUT.enabled(user.domain)):
        if user.is_locked_out():
            return
        if user.attempt_date == date.today():
            user.login_attempts += 1
        else:
            user.login_attempts = 1
            user.attempt_date = date.today()
        user.save()
예제 #45
0
    def get_payload(self, repeat_record, payload_doc):

        case_ids_to_forward = payload_doc.get_case_property('cases_to_forward')
        if not case_ids_to_forward:
            raise ReferralError(
                f'No cases included in transfer. Please add case ids to "cases_to_forward" property'
            )
        else:
            case_ids_to_forward = case_ids_to_forward.split(' ')
        new_owner = payload_doc.get_case_property('new_owner')
        cases_to_forward = CaseAccessors(
            payload_doc.domain).get_cases(case_ids_to_forward)
        case_ids_to_forward = set(case_ids_to_forward)
        included_case_types = payload_doc.get_case_property(
            'case_types').split(' ')
        case_type_configs = {}
        for case_type in included_case_types:
            constant_properties = []
            for key, value in payload_doc.case_json.items():
                constant_prefix = f'{case_type}_setter_'
                if key.startswith(constant_prefix):
                    property_name = key[len(constant_prefix):]
                    constant_properties.append((property_name, value))
            whitelist = payload_doc.case_json.get(f'{case_type}_whitelist')
            blacklist = payload_doc.case_json.get(f'{case_type}_blacklist')
            if blacklist and whitelist:
                raise ReferralError(
                    f'both blacklist and whitelist included for {case_type}')
            if not blacklist and not whitelist:
                raise ReferralError(
                    f'blacklist or whitelist not included for {case_type}')
            if blacklist:
                listed_properties = blacklist.split(' ')
                use_blacklist = True
            else:
                listed_properties = whitelist.split(' ')
                use_blacklist = False
            case_type_configs[case_type] = CaseTypeReferralConfig(
                use_blacklist, listed_properties, constant_properties)

        case_blocks = self._get_case_blocks(cases_to_forward,
                                            case_ids_to_forward,
                                            case_type_configs, new_owner)
        return render_to_string(
            'hqcase/xml/case_block.xml', {
                'xmlns': SYSTEM_FORM_XMLNS,
                'case_block': case_blocks,
                'time': datetime.utcnow(),
                'uid': uuid4().hex,
                'username': self.repeater.username,
                'user_id': CouchUser.get_by_username(
                    self.repeater.username).user_id,
                'device_id': "ReferCaseRepeater",
            })
예제 #46
0
    def clean_email(self):
        data = self.cleaned_data["email"].strip().lower()
        validate_email(data)

        existing_member = CouchUser.get_by_username(data)
        if existing_member:
            org = Organization.get_by_name(self.org_name)
            for member in org.get_members():
                if member.get_id == existing_member.get_id:
                    raise forms.ValidationError("User is already part of this organization!")

        return data
예제 #47
0
def _get_user_info(username):
    user = CouchUser.get_by_username(username)
    if not user:
        return {"error": "User not found"}

    return {
        "user_is_dimagi": "@dimagi.com" in username,
        "user_is_mobile": "commcarehq.org" in username,
        "user_is_active": user.is_active,
        "user_last_login": user.last_login,
        "user_is_superuser": user.is_superuser,
    }
예제 #48
0
def _login(req, domain_name, template_name):

    if req.user.is_authenticated and req.method == "GET":
        redirect_to = req.GET.get('next', '')
        if redirect_to:
            return HttpResponseRedirect(redirect_to)
        if not domain_name:
            return HttpResponseRedirect(reverse('homepage'))
        else:
            return HttpResponseRedirect(
                reverse('domain_homepage', args=[domain_name]))

    if req.method == 'POST' and domain_name and '@' not in req.POST.get(
            'auth-username', '@'):
        with mutable_querydict(req.POST):
            req.POST['auth-username'] = format_username(
                req.POST['auth-username'], domain_name)

    if 'auth-username' in req.POST:
        couch_user = CouchUser.get_by_username(
            req.POST['auth-username'].lower())
        if couch_user:
            new_lang = couch_user.language
            old_lang = req.session.get(LANGUAGE_SESSION_KEY)
            update_session_language(req, old_lang, new_lang)

    req.base_template = settings.BASE_TEMPLATE

    context = {}
    custom_landing_page = getattr(settings, 'CUSTOM_LANDING_TEMPLATE', False)
    if custom_landing_page:
        template_name = custom_landing_page
    elif domain_name:
        domain = Domain.get_by_name(domain_name)
        req_params = req.GET if req.method == 'GET' else req.POST
        context.update({
            'domain': domain_name,
            'hr_name': domain.display_name() if domain else domain_name,
            'next': req_params.get('next', '/a/%s/' % domain),
            'allow_domain_requests': domain.allow_domain_requests,
            'current_page': {
                'page_name': _('Welcome back to %s!') % domain.display_name()
            }
        })
    else:
        context.update(
            {'current_page': {
                'page_name': _('Welcome back to CommCare HQ!')
            }})

    auth_view = HQLoginView if not domain_name else CloudCareLoginView
    return auth_view.as_view(template_name=template_name,
                             extra_context=context)(req)
예제 #49
0
    def clean(self):
        try:
            cleaned_data = super(HQBackupTokenForm, self).clean()
        except ValidationError:
            user_login_failed.send(sender=__name__, credentials={'username': self.user.username},
                request=self.request,
                token_failure=True)
            couch_user = CouchUser.get_by_username(self.user.username)
            if couch_user and couch_user.is_locked_out():
                metrics_counter('commcare.auth.token_lockout')
                raise ValidationError(LOCKOUT_MESSAGE)
            else:
                raise

        # Handle the edge-case where the user enters a correct token
        # after being locked out
        couch_user = CouchUser.get_by_username(self.user.username)
        if couch_user and couch_user.is_locked_out():
            metrics_counter('commcare.auth.lockouts')
            raise ValidationError(LOCKOUT_MESSAGE)
        return cleaned_data
예제 #50
0
    def clean(self):
        username = self.cleaned_data.get('username')
        if username is None:
            raise ValidationError(_('Please enter a valid email address.'))

        password = self.cleaned_data.get('password')
        if not password:
            raise ValidationError(_("Please enter a password."))

        try:
            cleaned_data = super(EmailAuthenticationForm, self).clean()
        except ValidationError:
            user = CouchUser.get_by_username(username)
            if user and user.is_locked_out() and user.supports_lockout():
                raise ValidationError(LOCKOUT_MESSAGE)
            else:
                raise
        user = CouchUser.get_by_username(username)
        if user and user.is_locked_out() and user.supports_lockout():
            raise ValidationError(LOCKOUT_MESSAGE)
        return cleaned_data
예제 #51
0
파일: tasks.py 프로젝트: dimagi/commcare-hq
def upload(dropbox_helper_id, access_token, size, max_retries):
    from .models import DropboxUploadHelper
    helper = DropboxUploadHelper.objects.get(id=dropbox_helper_id)

    def progress_callback(bytes_uploaded, helper=helper, size=size):
        helper.progress = float(bytes_uploaded) / size
        helper.save()

    try:
        dropbox_path = '/{}'.format(os.path.basename(helper.src))
        path_display = upload_to_dropbox(access_token, dropbox_path, helper.src, progress_callback)
    except Exception as e:
        helper.failure_reason = str(e)
        helper.save()

    couch_user = CouchUser.get_by_username(helper.user.username)
    if helper.failure_reason is None:
        dbx = Dropbox(access_token)
        path_link_metadata = dbx.sharing_create_shared_link_with_settings(
            path_display,
            SharedLinkSettings(
                requested_visibility=RequestedVisibility.team_only,
            ),
        )
        context = {
            'share_url': path_link_metadata.url,
            'path': os.path.join(
                'Apps',
                settings.DROPBOX_APP_NAME,
                path_link_metadata.name,
            )
        }
        with localize(couch_user.get_language_code()):
            subject = _('{} has been uploaded to dropbox!'.format(helper.dest))
            html_content = render_to_string('dropbox/emails/upload_success.html', context)
            text_content = render_to_string('dropbox/emails/upload_success.txt', context)
    else:
        context = {
            'reason': helper.failure_reason,
            'path': helper.dest
        }
        with localize(couch_user.get_language_code()):
            subject = _('{} has failed to upload to dropbox'.format(helper.dest))
            html_content = render_to_string('dropbox/emails/upload_error.html', context)
            text_content = render_to_string('dropbox/emails/upload_error.txt', context)

    send_HTML_email(
        subject,
        helper.user.email,
        html_content,
        text_content=text_content,
    )
예제 #52
0
    def clean_email(self):
        data = self.cleaned_data['email'].strip().lower()
        validate_email(data)

        existing_member = CouchUser.get_by_username(data)
        if existing_member:
            org = Organization.get_by_name(self.org_name)
            for member in org.get_members():
                if member.get_id == existing_member.get_id:
                    raise forms.ValidationError(
                        'User is already part of this organization!')

        return data
예제 #53
0
파일: views.py 프로젝트: mchampanis/core-hq
def orgs_add_member(request, org):
    if request.method == "POST":
        form = AddMemberForm(org, request.POST)
        if form.is_valid():
            username = form.cleaned_data['member_email']
            user_id = CouchUser.get_by_username(username).userID
            organization = Organization.get_by_name(org)
            organization.add_member(user_id)
            messages.success(request, "Member Added!")
        else:
            messages.error(request, "Unable to add member")
            return orgs_landing(request, org, add_member_form=form)
    return HttpResponseRedirect(reverse('orgs_landing', args=[org]))
예제 #54
0
    def clean(self):
        lockout_message = mark_safe(_('Sorry - you have attempted to login with an incorrect password too many times. Please <a href="/accounts/password_reset_email/">click here</a> to reset your password or contact the domain administrator.'))

        username = self.cleaned_data.get('username')
        if username is None:
            raise ValidationError(_('Please enter a valid email address.'))

        password = self.cleaned_data.get('password')
        if not password:
            raise ValidationError(_("Please enter a password."))

        try:
            cleaned_data = super(EmailAuthenticationForm, self).clean()
        except ValidationError:
            user = CouchUser.get_by_username(username)
            if user and user.is_locked_out() and user.supports_lockout():
                raise ValidationError(lockout_message)
            else:
                raise
        user = CouchUser.get_by_username(username)
        if user and user.is_locked_out() and user.supports_lockout():
            raise ValidationError(lockout_message)
        return cleaned_data
예제 #55
0
파일: api.py 프로젝트: johan--/commcare-hq
    def sms_user_sync(self, ilsgateway_smsuser, username_part=None, password=None, first_name="", last_name=""):
        username, username_part = self.get_username(ilsgateway_smsuser, username_part)
        # sanity check
        assert len(username) <= 128
        user = CouchUser.get_by_username(username)
        splitted_value = ilsgateway_smsuser.name.split(" ", 1)
        if not first_name:
            first_name = splitted_value[0][:30] if splitted_value else ""

        if not last_name:
            last_name = splitted_value[1][:30] if len(splitted_value) > 1 else ""

        language = ilsgateway_smsuser.language

        user_dict = {
            "first_name": first_name,
            "last_name": last_name,
            "is_active": bool(ilsgateway_smsuser.is_active),
            "email": ilsgateway_smsuser.email,
            "user_data": {},
        }

        if ilsgateway_smsuser.role:
            user_dict["user_data"]["role"] = ilsgateway_smsuser.role

        if user is None and username_part:
            try:
                user_password = password or User.objects.make_random_password()
                user = CommCareUser.create(
                    domain=self.domain,
                    username=username,
                    password=user_password,
                    email=ilsgateway_smsuser.email,
                    commit=False,
                    password_hashed=bool(password),
                )
                user.first_name = first_name
                user.last_name = last_name
                user.language = language
                user.is_active = bool(ilsgateway_smsuser.is_active)
                user.user_data = user_dict["user_data"]
                user.save()
                self.add_phone_numbers(ilsgateway_smsuser, user)
                user.save()
            except Exception as e:
                logging.error(e)
        else:
            self.edit_phone_numbers(ilsgateway_smsuser, user)
            user.save()
        return user
예제 #56
0
파일: forms.py 프로젝트: mchampanis/core-hq
    def clean_member_email(self):
        data = self.cleaned_data['member_email'].strip().lower()
        validate_email(data)
        exists = CouchUser.get_by_username(data)

        if not exists:
            raise forms.ValidationError('User not found!')

        org = Organization.get_by_name(self.org_name)
        for id in org.members:
            if id == exists.get_id:
                raise forms.ValidationError('User is already part of this organization!')

        return data
예제 #57
0
    def post(self, request, *args, **kwargs):
        try:
            data = json.loads(request.body.decode('utf-8'))
        except ValueError:
            return HttpResponseBadRequest()

        if not data or not isinstance(data, dict):
            return HttpResponseBadRequest()

        session_id = data.get('sessionId', None)
        if not session_id:
            return HttpResponseBadRequest()

        session = get_session(session_id)
        user = get_django_user_from_session(session)
        if user:
            couch_user = CouchUser.get_by_username(user.username)
            if not couch_user:
                raise Http404
        else:
            raise Http404

        domain = data.get('domain')
        if domain and DISABLE_WEB_APPS.enabled(domain):
            return HttpResponse('Service Temporarily Unavailable',
                                content_type='text/plain',
                                status=503)

        # reset the session's expiry if there's some formplayer activity
        secure_session = session.get('secure_session')
        TimeoutMiddleware.update_secure_session(session,
                                                secure_session,
                                                couch_user,
                                                domain=data.get('domain'))
        session.save()

        domains = set()
        for domain in couch_user.domains:
            domains.add(domain)
            mirror_domains = DomainPermissionsMirror.mirror_domains(domain)
            domains.update(mirror_domains)

        return JsonResponse({
            'username': user.username,
            'djangoUserId': user.pk,
            'superUser': user.is_superuser,
            'authToken': None,
            'domains': list(domains),
            'anonymous': False
        })
예제 #58
0
 def get_success_url(self):
     if self.user:
         # redirect mobile worker password reset to a domain-specific login with their username already set
         couch_user = CouchUser.get_by_username(self.user.username)
         if couch_user.is_commcare_user():
             messages.success(
                 self.request,
                 _('Password for {} has successfully been reset. You can now login.'
                   ).format(couch_user.raw_username))
             return '{}?username={}'.format(
                 reverse('domain_login', args=[couch_user.domain]),
                 couch_user.raw_username,
             )
     return super().get_success_url()
예제 #59
0
파일: auth.py 프로젝트: dimagi/commcare-hq
    def _inner(request, *args, **kwargs):
        with mutable_querydict(request.GET):
            as_user = request.GET.pop('as', None)

        if not as_user:
            return HttpResponse('User required', status=401)

        couch_user = CouchUser.get_by_username(as_user[-1])
        if not couch_user:
            return HttpResponse('Unknown user', status=401)

        request.user = couch_user.get_django_user()
        request.couch_user = couch_user

        return view(request, *args, **kwargs)