def clean(self): try: password = self.cleaned_data['password'] password_2 = self.cleaned_data['password_2'] except KeyError: pass else: if password != password_2: raise forms.ValidationError("Passwords do not match") if self.password_format == 'n' and not password.isnumeric(): raise forms.ValidationError("Password is not numeric") try: username = self.cleaned_data['username'] except KeyError: pass else: if len(username) > CommCareAccountForm.max_len_username: raise forms.ValidationError( "Username %s is too long. Must be under %d characters." % (username, CommCareAccountForm.max_len_username)) validate_username('*****@*****.**' % username) domain = self.cleaned_data['domain'] username = format_username(username, domain) num_couch_users = len(CouchUser.view("users/by_username", key=username, reduce=False)) if num_couch_users > 0: raise forms.ValidationError("CommCare user already exists") # set the cleaned username to [email protected] self.cleaned_data['username'] = username return self.cleaned_data
def clean(self): try: password = self.cleaned_data['password'] password_2 = self.cleaned_data['password_2'] except KeyError: pass else: if password != password_2: raise forms.ValidationError("Passwords do not match") if self.password_format == 'n' and not password.isnumeric(): raise forms.ValidationError("Password is not numeric") try: username = self.cleaned_data['username'] except KeyError: pass else: if len(username) > CommCareAccountForm.max_len_username: raise forms.ValidationError( "Username %s is too long. Must be under %d characters." % (username, CommCareAccountForm.max_len_username)) validate_username('*****@*****.**' % username) domain = self.cleaned_data['domain'] username = format_username(username, domain) num_couch_users = len( CouchUser.view("users/by_username", key=username)) if num_couch_users > 0: raise forms.ValidationError("CommCare user already exists") # set the cleaned username to [email protected] self.cleaned_data['username'] = username return self.cleaned_data
def handle_changed_mailchimp_email(user, old_email, new_email): """ Checks whether there are other users with old_email who are also subscribed to any mailchimp lists. If not, it safely unsubscribes that email from mailchimp. Then, adds new_email to mailchimp. """ users_with_old_email = User.objects.filter(email=old_email).values_list('username', flat=True) couch_users = CouchUser.view('users/by_username', keys=list(users_with_old_email), include_docs=True, reduce=False, ).all() if user.subscribed_to_commcare_users: users_subscribed_with_old_email = [couch_user.get_id for couch_user in couch_users if couch_user.subscribed_to_commcare_users] if (len(users_subscribed_with_old_email) == 1 and users_subscribed_with_old_email[0] == user.get_id): safe_unsubscribe_user_from_mailchimp_list(user, settings.MAILCHIMP_COMMCARE_USERS_ID, email=old_email) if not user.email_opt_out: users_subscribed_with_old_email = [couch_user.get_id for couch_user in couch_users if not couch_user.email_opt_out] if (len(users_subscribed_with_old_email) == 1 and users_subscribed_with_old_email[0] == user.get_id): safe_unsubscribe_user_from_mailchimp_list(user, settings.MAILCHIMP_MASS_EMAIL_ID, email=old_email) # subscribe new_email to lists if user.subscribed_to_commcare_users: safe_subscribe_user_to_mailchimp_list(user, settings.MAILCHIMP_COMMCARE_USERS_ID, email=new_email) if not user.email_opt_out: safe_subscribe_user_to_mailchimp_list(user, settings.MAILCHIMP_MASS_EMAIL_ID, email=new_email)
def group_members(request, domain, group_id, template="groups/group_members.html"): context = _users_context(request, domain) all_groups = _get_sorted_groups(domain) try: group = Group.get(group_id) except ResourceNotFound: raise Http404("Group %s does not exist" % group_id) member_ids = group.get_user_ids() members = CouchUser.view("_all_docs", keys=member_ids, include_docs=True).all() members.sort(key=lambda user: user.username) all_users = CommCareUser.by_domain(domain) member_ids = set(member_ids) nonmembers = [user for user in all_users if user.user_id not in member_ids] context.update({ "domain": domain, "group": group, "all_groups": all_groups, "members": members, "nonmembers": nonmembers, }) return render(request, template, context)
def get_user_id(self, username, domain): cc_username = format_username(username, domain) result = CouchUser.view( 'users/by_username', key=cc_username, include_docs=False, ) row = result.one() if row: return row["id"]
def run(): users = CouchUser.view('users/all_users', include_docs=True) for user in users: save = False for dm in user.web_account.domain_memberships: if not dm.is_admin: save = True user.set_permission(dm.domain, OldPermissions.EDIT_APPS, True, save=False) if save: user.save()
def get_user_id(self, username, domain): cc_username = format_username(username, domain) result = CouchUser.view( 'users/by_username', key=cc_username, include_docs=False, reduce=False, ) row = result.one() if row: return row["id"]
def get_user_id_by_username(username): result = CouchUser.view( 'users/by_username', key=username, include_docs=False, reduce=False, stale=stale_ok(), ) row = result.one() if row: return row["id"] return None
def get_user_id_and_doc_type_by_domain(domain): key = ['active', domain] return [ {"id": u['id'], "doc_type":u['key'][2]} for u in CouchUser.view( 'users/by_domain', reduce=False, startkey=key, endkey=key + [{}], include_docs=False, ).all() ]
def get_sms_autocomplete_context(request, domain): """A helper view for sms autocomplete""" phone_users = CouchUser.view("users/phone_users_by_domain", startkey=[domain], endkey=[domain, {}], include_docs=True ) groups = Group.view("groups/by_domain", key=domain, include_docs=True) contacts = ["[send to all]"] contacts.extend(['%s [group]' % group.name for group in groups]) user_id = None for user in phone_users: if user._id == user_id: continue contacts.append(user.username) user_id = user._id return {"sms_contacts": contacts}
def get_sms_autocomplete_context(request, domain): """A helper view for sms autocomplete""" phone_users = CouchUser.view("users/phone_users_by_domain", startkey=[domain], endkey=[domain, {}], include_docs=True) groups = Group.view("groups/by_domain", key=domain, include_docs=True) contacts = ["[send to all]"] contacts.extend(['%s [group]' % group.name for group in groups]) user_id = None for user in phone_users: if user._id == user_id: continue contacts.append(user.username) user_id = user._id return {"sms_contacts": contacts}
def handle_changed_mailchimp_email(user, old_email, new_email): """ Checks whether there are other users with old_email who are also subscribed to any mailchimp lists. If not, it safely unsubscribes that email from mailchimp. Then, adds new_email to mailchimp. """ users_with_old_email = User.objects.filter(email=old_email).values_list( 'username', flat=True) couch_users = CouchUser.view( 'users/by_username', keys=list(users_with_old_email), include_docs=True, reduce=False, ).all() if user.subscribed_to_commcare_users: users_subscribed_with_old_email = [ couch_user.get_id for couch_user in couch_users if couch_user.subscribed_to_commcare_users ] if (len(users_subscribed_with_old_email) == 1 and users_subscribed_with_old_email[0] == user.get_id): safe_unsubscribe_user_from_mailchimp_list( user, settings.MAILCHIMP_COMMCARE_USERS_ID, email=old_email) if not user.email_opt_out: users_subscribed_with_old_email = [ couch_user.get_id for couch_user in couch_users if not couch_user.email_opt_out ] if (len(users_subscribed_with_old_email) == 1 and users_subscribed_with_old_email[0] == user.get_id): safe_unsubscribe_user_from_mailchimp_list( user, settings.MAILCHIMP_MASS_EMAIL_ID, email=old_email) # subscribe new_email to lists if user.subscribed_to_commcare_users: safe_subscribe_user_to_mailchimp_list( user, settings.MAILCHIMP_COMMCARE_USERS_ID, email=new_email) if not user.email_opt_out: safe_subscribe_user_to_mailchimp_list(user, settings.MAILCHIMP_MASS_EMAIL_ID, email=new_email)
def process_username(username, domain): """ Loosely based on code from apps/users/forms.py:255 """ from corehq.apps.users.forms import validate_username max_len_username = 80 if len(username) > max_len_username: raise forms.ValidationError(get_message(MSG_USERNAME_TOO_LONG, context=(username, max_len_username))) # Check if the username contains invalid characters w/ django checker validate_username('*****@*****.**' % username) username = format_username(username, domain) num_couch_users = len(CouchUser.view("users/by_username", key=username, reduce=False)) if num_couch_users > 0: raise forms.ValidationError(get_message(MSG_DUPLICATE_USERNAME, context=(username,))) return username
def group_members(request, domain, group_id, template="groups/group_members.html"): context = _users_context(request, domain) all_groups = _get_sorted_groups(domain) group = Group.get(group_id) if group is None: raise Http404("Group %s does not exist" % group_id) member_ids = group.get_user_ids() members = CouchUser.view("_all_docs", keys=member_ids, include_docs=True).all() members.sort(key=lambda user: user.username) all_users = CommCareUser.by_domain(domain) member_ids = set(member_ids) nonmembers = [user for user in all_users if user.user_id not in member_ids] context.update({"domain": domain, "group": group, "all_groups": all_groups, "members": members, "nonmembers": nonmembers, }) return render(request, template, context)
def process_username(username, domain): """ Loosely based on code from apps/users/forms.py:255 """ from corehq.apps.users.forms import validate_username max_len_username = 80 if len(username) > max_len_username: raise forms.ValidationError( get_message(MSG_USERNAME_TOO_LONG, context=(username, max_len_username))) # Check if the username contains invalid characters w/ django checker validate_username('*****@*****.**' % username) username = format_username(username, domain) num_couch_users = len( CouchUser.view("users/by_username", key=username, reduce=False)) if num_couch_users > 0: raise forms.ValidationError( get_message(MSG_DUPLICATE_USERNAME, context=(username, ))) return username
def send_to_recipients(request, domain): recipients = request.POST.get('recipients') message = request.POST.get('message') if not recipients: messages.error(request, _("You didn't specify any recipients")) elif not message: messages.error(request, _("You can't send an empty message")) else: recipients = [x.strip() for x in recipients.split(',') if x.strip()] phone_numbers = [] # formats: GroupName (group), "Username", +15555555555 group_names = [] usernames = [] phone_numbers = [] unknown_usernames = [] GROUP = "[group]" send_to_all_checked = False for recipient in recipients: if recipient == "[send to all]": send_to_all_checked = True phone_users = CouchUser.view("users/phone_users_by_domain", startkey=[domain], endkey=[domain, {}], include_docs=True ) for user in phone_users: usernames.append(user.username) group_names = [] break elif (not send_to_all_checked) and recipient.endswith(GROUP): name = recipient[:-len(GROUP)].strip() group_names.append(name) elif re.match(r'^\+\d+', recipient): # here we expect it to have a plus sign def wrap_user_by_type(u): return getattr(user_models, u['doc']['doc_type']).wrap(u['doc']) phone_users = CouchUser.view("users/by_default_phone", # search both with and w/o the plus keys=[recipient, recipient[1:]], include_docs=True, wrapper=wrap_user_by_type).all() phone_users = filter(lambda u: u.is_member_of(domain), phone_users) if len(phone_users) > 0: phone_numbers.append((phone_users[0], recipient)) else: phone_numbers.append((None, recipient)) elif (not send_to_all_checked) and re.match(r'[\w\.]+', recipient): usernames.append(recipient) else: unknown_usernames.append(recipient) login_ids = dict([(r['key'], r['id']) for r in get_db().view("users/by_username", keys=usernames).all()]) for username in usernames: if username not in login_ids: unknown_usernames.append(username) login_ids = login_ids.values() users = [] empty_groups = [] if len(group_names) > 0: users.extend(CouchUser.view('users/by_group', keys=[[domain, gn] for gn in group_names], include_docs=True).all()) if len(users) == 0: empty_groups = group_names users.extend(CouchUser.view('_all_docs', keys=login_ids, include_docs=True).all()) users = [user for user in users if user.is_active and not user.is_deleted()] phone_numbers.extend([(user, user.phone_number) for user in users]) failed_numbers = [] no_numbers = [] sent = [] for user, number in phone_numbers: if not number: no_numbers.append(user.raw_username) elif send_sms(domain, user.user_id if user else "", number, message): sent.append("%s" % (user.raw_username if user else number)) else: failed_numbers.append("%s (%s)" % ( number, user.raw_username if user else "<no username>" )) if empty_groups or failed_numbers or unknown_usernames or no_numbers: if empty_groups: messages.error(request, _("The following groups don't exist: ") + (', '.join(empty_groups))) if no_numbers: messages.error(request, _("The following users don't have phone numbers: ") + (', '.join(no_numbers))) if failed_numbers: messages.error(request, _("Couldn't send to the following number(s): ") + (', '.join(failed_numbers))) if unknown_usernames: messages.error(request, _("Couldn't find the following user(s): ") + (', '.join(unknown_usernames))) if sent: messages.success(request, _("Successfully sent: ") + (', '.join(sent))) else: messages.info(request, _("No messages were sent.")) else: messages.success(request, _("Message sent")) return HttpResponseRedirect( request.META.get('HTTP_REFERER') or reverse(compose_message, args=[domain]) )
def send_to_recipients(request, domain): recipients = request.POST.get('recipients') message = request.POST.get('message') if not recipients: messages.error(request, "You didn't specify any recipients") elif not message: messages.error(request, "You can't send an empty message") else: recipients = [x.strip() for x in recipients.split(',') if x.strip()] phone_numbers = [] # formats: GroupName (group), "Username", +15555555555 group_names = [] usernames = [] phone_numbers = [] unknown_usernames = [] GROUP = "[group]" send_to_all_checked = False for recipient in recipients: if recipient == "[send to all]": send_to_all_checked = True phone_users = CouchUser.view("users/phone_users_by_domain", startkey=[domain], endkey=[domain, {}], include_docs=True) for user in phone_users: usernames.append(user.username) group_names = [] break elif (not send_to_all_checked) and recipient.endswith(GROUP): name = recipient[:-len(GROUP)].strip() group_names.append(name) elif re.match(r'^\+\d+', recipient): # here we expect it to have a plus sign def wrap_user_by_type(u): return getattr(user_models, u['doc']['doc_type']).wrap(u['doc']) phone_users = CouchUser.view( "users/by_default_phone", # search both with and w/o the plus keys=[recipient, recipient[1:]], include_docs=True, wrapper=wrap_user_by_type).all() phone_users = filter(lambda u: u.is_member_of(domain), phone_users) if len(phone_users) > 0: phone_numbers.append((phone_users[0], recipient)) else: phone_numbers.append((None, recipient)) elif (not send_to_all_checked) and re.match(r'[\w\.]+', recipient): usernames.append(recipient) else: unknown_usernames.append(recipient) login_ids = dict([ (r['key'], r['id']) for r in get_db().view("users/by_username", keys=usernames).all() ]) for username in usernames: if username not in login_ids: unknown_usernames.append(username) login_ids = login_ids.values() users = [] empty_groups = [] if len(group_names) > 0: users.extend( CouchUser.view('users/by_group', keys=[[domain, gn] for gn in group_names], include_docs=True).all()) if len(users) == 0: empty_groups = group_names users.extend( CouchUser.view('_all_docs', keys=login_ids, include_docs=True).all()) users = [ user for user in users if user.is_active and not user.is_deleted() ] phone_numbers.extend([(user, user.phone_number) for user in users]) failed_numbers = [] no_numbers = [] sent = [] for user, number in phone_numbers: if not number: no_numbers.append(user.raw_username) elif send_sms(domain, user.user_id if user else "", number, message): sent.append("%s" % (user.raw_username if user else number)) else: failed_numbers.append( "%s (%s)" % (number, user.raw_username if user else "<no username>")) if empty_groups or failed_numbers or unknown_usernames or no_numbers: if empty_groups: messages.error( request, "The following groups don't exist: %s" % (', '.join(empty_groups))) if no_numbers: messages.error( request, "The following users don't have phone numbers: %s" % (', '.join(no_numbers))) if failed_numbers: messages.error( request, "Couldn't send to the following number(s): %s" % (', '.join(failed_numbers))) if unknown_usernames: messages.error( request, "Couldn't find the following user(s): %s" % (', '.join(unknown_usernames))) if sent: messages.success(request, "Successfully sent: %s" % (', '.join(sent))) else: messages.info(request, "No messages were sent.") else: messages.success(request, "Message sent") return HttpResponseRedirect( request.META.get('HTTP_REFERER') or reverse(compose_message, args=[domain]))
def testPhoneUsersViewNoNumberSet(self): phone_users_count = CouchUser.view("users/phone_users_by_domain", key=self.domain).count() self.assertEquals(phone_users_count, 0)
def testPhoneUsersViewNoNumberSet(self): phone_users_count = CouchUser.view("users/phone_users_by_domain", key=self.domain).count() self.assertEqual(phone_users_count, 0)
def handle(self, *args, **options): django_domains = OldDomain.objects.all() django_domain_names = set([domain.name for domain in django_domains]) couch_domain_names = set([x['key'][0] for x in get_db().view('domain/docs', group_level=1).all()]) couch_user_domain_names = set([x['key'] for x in get_db().view('users/by_domain', group=True).all()]) print get_db().view('users/by_domain').all() normalized_names = {} domains_that_need_to_change = set() # print some warnings if things are fishy for domain in couch_domain_names.union(couch_user_domain_names): if domain not in django_domain_names: print "Warning: domain '%s' not in SQL" % domain normalized = normalize_domain_name(domain) if normalized in normalized_names: print "Warning: domains '%s' and '%s' both exist" % (domain, normalized_names[normalized]) normalized_names[normalized] = domain if normalized != domain: domains_that_need_to_change.add(domain) print "Going to change the following domains:" for domain in domains_that_need_to_change: print " %s" % domain print if raw_input("Are you sure you want to continue? (Y/n)") != 'Y': print "Mission aborted" return print "Migrating SQL domains" for django_domain in django_domains: django_domain.name = normalize_domain_name(django_domain.name) django_domain.save() print "Migrating domains in Couch docs" class MyDoc(Document): class Meta: app_label = 'domain' def get_docs(domain): chunk_size = 500 i = 0 while True: docs = MyDoc.view('domain/docs', startkey=[domain], endkey=[domain, {}], reduce=False, include_docs=True, skip=i*chunk_size, limit=chunk_size) for doc in docs: yield doc if not len(docs): break i += 1 for domain in domains_that_need_to_change: print "%s:" % domain for doc in get_docs(domain): print '.', if 'domain' in doc: doc['domain'] = normalize_domain_name(doc['domain']) if 'domains' in doc: for i,domain in enumerate(doc['domains']): doc['domains'][i] = normalize_domain_name(doc['domains'][i]) doc.save() print print "Patching users" for domain in domains_that_need_to_change: print '.', couch_users = CouchUser.view('users/by_domain', key=domain, include_docs=True, reduce=False) for user in couch_users: for dm in user.web_account.domain_memberships: dm.domain = normalize_domain_name(dm.domain) for account in user.commcare_accounts: if account.domain: account.domain = normalize_domain_name(account.domain) user.save()