Skip to content

Commit

Permalink
BLUEBUTTON-934 New User Self-Identification (#730)
Browse files Browse the repository at this point in the history
* WIP - Adds messages and new select box

* Removes old message include to be redone and adds icon to new messages and removes whitespace

* Adds styles to forgot password flow.

* Move email down in form and remove help text

* Split bootstrapform in to signup and mfa forms

* Add UserIdentificationLabel model and migration

* Add admin view for UserIdentificationLabel

* Add identification choice to signup form

* Update create account tests

* Add test for user identification label

* Switch to use ModelChoiceField for self identification
  • Loading branch information
johnfrenchxyz authored and dtisza1 committed Jun 4, 2019
1 parent fbd7a2c commit 99725de
Show file tree
Hide file tree
Showing 19 changed files with 335 additions and 336 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,5 @@ ENV/
*.css.map
.sass-cache/*
bluebutton-css/

.vscode
14 changes: 13 additions & 1 deletion apps/accounts/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
ValidPasswordResetKey,
UserProfile,
ActivationKey,
MFACode)
MFACode,
UserIdentificationLabel)


admin.site.register(ActivationKey)
Expand Down Expand Up @@ -48,6 +49,17 @@ def get_user_joined(selfself, obj):
admin.site.register(UserProfile, UserProfileAdmin)


class UserIdentificationLabelAdmin(admin.ModelAdmin):
model = UserIdentificationLabel
filter_horizontal = ('users',)
list_display = ("name", "slug", "weight")
list_filter = ("name", "slug")
ordering = ("weight", )


admin.site.register(UserIdentificationLabel, UserIdentificationLabelAdmin)


class MFACodeAdmin(admin.ModelAdmin):
list_display = ('user', 'code',
'tries_counter',
Expand Down
26 changes: 16 additions & 10 deletions apps/accounts/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,22 @@
from django.utils.translation import ugettext_lazy as _
from apps.fhir.bluebutton.models import Crosswalk
from apps.fhir.bluebutton.utils import get_resourcerouter
from .models import UserProfile, create_activation_key
from .models import UserProfile, create_activation_key, UserIdentificationLabel
from .models import MFA_CHOICES
from django.contrib.auth.forms import AuthenticationForm, UsernameField


logger = logging.getLogger('hhs_server.%s' % __name__)


class IdentificationModelChoiceField(forms.ModelChoiceField):
def label_from_instance(self, obj):
return obj.name


class SignupForm(UserCreationForm):
email = forms.EmailField(max_length=255,
label=_("Email"),
help_text=_("Your email address is needed for "
"password reset and other "
"notifications."))
label=_("Email"))
first_name = forms.CharField(max_length=100,
label=_("First Name"))
last_name = forms.CharField(max_length=100,
Expand All @@ -34,16 +36,15 @@ class SignupForm(UserCreationForm):
label=_("Password"))
password2 = forms.CharField(widget=forms.PasswordInput,
max_length=120,
label=_("Password (again)"),
help_text=_("We are asking you to re-enter "
"your chosen password to make "
"sure it was entered correctly."))
label=_("Password (again)"))
identification_choice = IdentificationModelChoiceField(label="Your Role", empty_label=None,
queryset=UserIdentificationLabel.objects.order_by('weight').all())

required_css_class = 'required'

class Meta:
model = User
fields = ('email', 'first_name', 'last_name', 'organization_name', 'password1', 'password2')
fields = ('first_name', 'last_name', 'email', 'organization_name', 'password1', 'password2', 'identification_choice')

def clean_email(self):
email = self.cleaned_data.get('email', "")
Expand Down Expand Up @@ -73,6 +74,11 @@ def save(self):
group = Group.objects.get(name='BlueButton')
user.groups.add(group)

# Assign user to identification label
ident = self.cleaned_data['identification_choice']
ident.users.add(user)
ident.save()

# Send a verification email
create_activation_key(user)

Expand Down
27 changes: 27 additions & 0 deletions apps/accounts/migrations/0038_auto_20190528_1637.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 2.1.7 on 2019-05-28 16:37

from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('accounts', '0037_auto_20171016_1542'),
]

operations = [
migrations.CreateModel(
name='UserIdentificationLabel',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, unique=True)),
('slug', models.SlugField(unique=True)),
('weight', models.IntegerField(default=0,
help_text='Integer value controlling the position of the label in lists.',
verbose_name='List Weight')),
('users', models.ManyToManyField(blank=True, null=True, to=settings.AUTH_USER_MODEL)),
],
),
]
11 changes: 11 additions & 0 deletions apps/accounts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,17 @@ def save(self, commit=True, **kwargs):
super(ValidPasswordResetKey, self).save(**kwargs)


class UserIdentificationLabel(models.Model):
"""
Provides identification labels that map to developer users.
"""
name = models.CharField(max_length=255, unique=True)
slug = models.SlugField(db_index=True, unique=True)
weight = models.IntegerField(verbose_name="List Weight", null=False, default=0,
help_text="Integer value controlling the position of the label in lists.")
users = models.ManyToManyField(settings.AUTH_USER_MODEL, null=True, blank=True)


def random_key_id(y=20):
return ''.join(random.choice('ABCDEFGHIJKLM'
'NOPQRSTUVWXYZ') for x in range(y))
Expand Down
61 changes: 33 additions & 28 deletions apps/accounts/templates/registration/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,51 @@

{% block messages %}

<div class="row">
<div class="col-lg-8">
{% include "include/messages.html" %}
</div>
</div>

{% endblock %}

{% block Content %}
<div class="sandbox-gradient-bg">
<div class="gradient-content-container">
<h1>Sandbox Login</h1>
<p>Register applications, make sample API calls, manage tokens, and more.</p>

<!-- Messages Container -->
<div class="gradient-messages-container">
<span>
Your account was created! Please check your email to verify your account before logging in.
<span>
</div>

<section class="ds-l-container preview__grid ds-u-margin-y--7 sandbox-login-container">
<div class="ds-l-row ds-u-justify-content--center">
<div class="ds-l-lg-col--6 ds-l-md-col--8 ds-l-sm-col--12">
<div class="hero-unit">
<!-- Title and Context Message -->
<h1>Blue Button 2.0 Sandbox Login</h1>
<p class="ds-u-font-size--base">Register applications, make sample API calls, manage tokens, and more.</p>
<div class="gradient-messages-container">
<i data-feather="check-circle"></i>
<span>
Success! Your account has been activated! Now you can log in and get started.
</span>
</div>

<!-- Content Card -->
<div class="gradient-content-card">
<div class="content">
<!-- Login Form -->
<form class="well ds-u-margin-y--3" method="post" action="">
<form class="" method="post" action="">
{% csrf_token %}
<table>
{% load bootstrap %}
{{ form|bootstrap }}
</table>
<input type="submit" class="ds-c-button ds-c-button--primary" value="Login" />
<div class="ds-u-margin-top--2">
<a href="{% url 'forgot_password' %}">Forgot Password?</a> |
<a href="{% url 'accounts_create_account' %}"> Create an Account</a>
</div>
<input type="submit" class="ds-c-button ds-u-margin-y--2 ds-c-button--primary" value="Login" />
</form>
</div>
<!-- Usage Notice / Warning -->
<div class="login-message-container">
<div class="content">
{{ settings.DISCLOSURE_TEXT }}
</div>
</div>
</div>
</div>
</section>
<div class="action-container">
<a href="{% url 'forgot_password' %}">Forgot Password?</a>
<a href="{% url 'accounts_create_account' %}"> Create an Account</a>
</div>
</div>
<div class="sub-card">
{{ settings.DISCLOSURE_TEXT }}
</div>
</div>
</div>

{% endblock %}

Expand Down
30 changes: 30 additions & 0 deletions apps/accounts/templates/registration/mfa.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{% extends "base.html" %}
{% load i18n %}
{% block Content %}

<div class="sandbox-gradient-bg">
<div class="gradient-content-container">
<h1>MFA VERIFICATION</h1>
<p>Enter the code you received to login.</p>

<!-- Messages Container -->
<div class="gradient-messages-contianer">
{% include "include/messages.html" %}
<!-- Not Sure how we'd like to do messages, but I'd like them to be in this format, if possible. -->
</div>

<!-- Content Card -->
<div class="gradient-content-card">
<div class="content">
<!-- Create Account Form -->
<form class="well" method="post" action="" enctype="multipart/form-data">
{% csrf_token %}
{% load bootstrap %}
{{ form|bootstrap }}
<a href="javascript:history.go(-1)">{% trans "Go Back" %}</a>
</form>
</div>
</div>
</div>
</div>
{% endblock %}
110 changes: 47 additions & 63 deletions apps/accounts/templates/registration/passwd_change_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,76 +13,60 @@


{% block Content %}
<div class="sandbox-gradient-bg">
<div class="gradient-content-container">
<h1>Enter New Password</h1>
<p>Reset your password below. Please enter your new password twice so we can verify you typed it in correctly.</p>

<section class="ds-l-container preview__grid ds-u-margin-y--7 sandbox-login-container">
<div class="ds-l-row ds-u-justify-content--center">
<div class="ds-l-lg-col--6 ds-l-md-col--8 ds-l-sm-col--12">


<!-- Title and Context Message -->
<h1>{{ title }}</h1>


<!-- Password Set Form -->
<form class="well ds-u-margin-y--3" method="post" action="">{% csrf_token %}
<div class="gradient-messages-container">
{% if form.errors %}
<p class="errornote">
{% if form.errors.items|length == 1 %}Please correct the error below.{% else %}Please correct the errors below.{% endif %}
</p>
<span>
{% if form.errors.items|length == 1 %}Please correct the error below.{% else %}Please correct the errors below.{% endif %}
</span>
{% endif %}
</div>


<p class="ds-u-font-size--base">Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly.</p>


<fieldset class="module aligned wide">

<div class="form-row">
{{ form.old_password.errors }}
{{ form.old_password.label_tag }} {{ form.old_password }}
</div>

<div class="form-row">
{{ form.new_password1.errors }}
<p class="ds-u-margin-y--1"> </p>
{{ form.new_password1.label_tag }} {{ form.new_password1 }}
{% if form.new_password1.help_text %}
<p class="ds-u-margin-y--1"> </p>
<div class="help">{{ form.new_password1.help_text|safe }}</div>
{% endif %}
</div>

<div class="form-row">
{{ form.new_password2.errors }}
<p class="ds-u-margin-y--1"> </p>
{{ form.new_password2.label_tag }} {{ form.new_password2 }}
{% if form.new_password2.help_text %}
<div class="help">{{ form.new_password2.help_text|safe }}</div>
<p class="ds-u-margin-y--1"> </p>
{% endif %}
</div>

</fieldset>

<div class="submit-row">
<input type="submit" class="ds-c-button ds-c-button--primary" value="Change my password" class="default">
</div>

</form>

<p class="ds-u-margin-y--7"> </p>

</div>
<!--- Usage Notice / Warning --->
<div class="login-message-container">
<!-- Content Card -->
<div class="gradient-content-card">
<div class="content">
{{ settings.DISCLOSURE_TEXT }}
<!-- Password Set Form -->
<form class="well ds-u-margin-y--3" method="post" action="">{% csrf_token %}
<p>Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly.</p>

<div class="form-row">
{{ form.old_password.errors }}
{{ form.old_password.label_tag }} {{ form.old_password }}
</div>

<div class="form-row">
{{ form.new_password1.errors }}
<p class="ds-u-margin-y--1"> </p>
{{ form.new_password1.label_tag }} {{ form.new_password1 }}
{% if form.new_password1.help_text %}
<p class="ds-u-margin-y--1"> </p>
<div class="help">{{ form.new_password1.help_text|safe }}</div>
{% endif %}
</div>

<div class="form-row">
{{ form.new_password2.errors }}
<p class="ds-u-margin-y--1"> </p>
{{ form.new_password2.label_tag }} {{ form.new_password2 }}
{% if form.new_password2.help_text %}
<div class="help">{{ form.new_password2.help_text|safe }}</div>
<p class="ds-u-margin-y--1"> </p>
{% endif %}
</div>

<div class="submit-row">
<input type="submit" class="ds-c-button ds-c-button--primary" value="Change my password" class="default">
</div>

</form>
</div>
</div>
</div>
</div>
</section>

</div>
</div>
{% endblock %}

{% block ExtraJSFoot %}
Expand Down
Loading

0 comments on commit 99725de

Please sign in to comment.