Signup Panel

* Accessible at /signup/
* Link placed on bottom of login page.
* Submits a simple signup request to Adjutant.
* Added overextends to based Adjutant enabled file.
* Added back button to match login form to forgot password.
* Change forgot password to match signup autofocus logic.

Change-Id: I1628495a3c35186a45061d07d5e392dc63121ee9
This commit is contained in:
Amelia Cordwell 2017-05-25 16:01:28 +12:00 committed by adrian-turjak
parent 490a16c08b
commit dfa0388152
21 changed files with 357 additions and 8 deletions

View File

@ -3,6 +3,7 @@ include setup.py
recursive-include adjutant_ui/content/default/templates *
recursive-include adjutant_ui/content/forgotpassword/templates *
recursive-include adjutant_ui/content/project_users/templates *
recursive-include adjutant_ui/content/signup/templates *
recursive-include adjutant_ui/content/tasks/templates *
recursive-include adjutant_ui/content/token/templates *
recursive-include adjutant_ui/static *

View File

@ -258,6 +258,17 @@ def forgotpassword_submit(request, data):
raise
def signup_submit(request, data):
headers = {"Content-Type": "application/json"}
try:
return post(request, 'openstack/sign-up',
data=json.dumps(data),
headers=headers)
except Exception as e:
LOG.error(e)
raise
def task_list(request, filters={}, page=1):
tasks_per_page = utils.get_page_size(request)
tasklist = []

View File

@ -27,17 +27,18 @@ USERNAME_IS_EMAIL = True
class ForgotPasswordForm(hforms.SelfHandlingForm):
username = forms.CharField(max_length=255, label=_("User Name"))
email = forms.EmailField(
label=_("Email"),
widget=forms.TextInput(attrs={"autofocus": "autofocus"})
)
username = forms.CharField(
max_length=255, label=_("User Name"),
widget=forms.TextInput(attrs={"autofocus": "autofocus"}))
email = forms.EmailField(label=_("Email"))
def __init__(self, *args, **kwargs):
super(ForgotPasswordForm, self).__init__(*args, **kwargs)
if (hasattr(settings, 'USERNAME_IS_EMAIL') and
getattr(settings, 'USERNAME_IS_EMAIL')):
self.fields.pop('username')
self.fields['email'].widget = forms.TextInput(
attrs={"autofocus": "autofocus"})
def clean(self, *args, **kwargs):
# validate username and email?

View File

@ -42,6 +42,9 @@
<span ng-show="auth_type==='credentials'">{% trans "Submit" %}</span>
<span ng-hide="auth_type==='credentials'" ng-cloak>{% trans "Submit" %}</span>
</button>
<a href="/" class="btn btn-default cancel">
{% trans "Back to login" %}
</a>
<div class="clearfix"></div>
{% endblock %}
</div>

View File

@ -55,7 +55,7 @@ class UpdateUserView(forms.ModalFormView):
def get_object(self):
try:
return adjutant.user_get(self.request,
self.kwargs['user_id'])
self.kwargs['user_id'])
except Exception:
msg = _('Unable to retrieve user.')
url = reverse('horizon:management:project_users:index')

View File

View File

@ -0,0 +1,58 @@
# Copyright (c) 2016 Catalyst IT Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from django.conf import settings
from django import forms
from django import http
from django.utils.translation import ugettext_lazy as _
from horizon import forms as hforms
from horizon.utils import functions as utils
from adjutant_ui.api import adjutant
class SignupForm(hforms.SelfHandlingForm):
username = forms.CharField(
max_length=255, label=_("User Name"),
widget=forms.TextInput(attrs={"autofocus": "autofocus"}))
email = forms.EmailField(label=_("Email"))
project_name = forms.CharField(label=_("Project Name"), max_length=64)
setup_network = forms.BooleanField(
label=_("Create Default Network"),
help_text=_("Create a basic network during account creation so that "
"you can deploy VMs immediately."),
required=False,
initial=True)
def __init__(self, *args, **kwargs):
super(SignupForm, self).__init__(*args, **kwargs)
if (hasattr(settings, 'USERNAME_IS_EMAIL') and
getattr(settings, 'USERNAME_IS_EMAIL')):
self.fields.pop('username')
self.fields['email'].widget = forms.TextInput(
attrs={"autofocus": "autofocus"})
def handle(self, request, data):
submit_response = adjutant.signup_submit(
request, data)
if submit_response.ok:
return True
# Send the user back to the login page.
msg = _("The signup service is currently unavailable. "
"Please try again later.")
response = http.HttpResponseRedirect(settings.LOGOUT_URL)
utils.add_logout_reason(self.request, response, msg)
return response

View File

@ -0,0 +1,23 @@
# Copyright (c) 2016 Catalyst IT Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from django.utils.translation import ugettext_lazy as _
import horizon
class SignupPanel(horizon.Panel):
name = _('Sign Up')
slug = 'signup'
nav = False

View File

@ -0,0 +1,7 @@
{% overextends 'auth/_login_page.html' %}
{% load i18n %}
{% block login_footer %}
{{ block.super }}
<p>Don't have an account? <a href="{% url 'horizon:signup:signup:index' %}">Sign up</a>.</p>
{% endblock %}

View File

@ -0,0 +1,23 @@
{% extends 'signup/_signup_form.html' %}
{% load url from future %}
{% load i18n %}
{% block pre_login %}
<div class="container login">
<div class="row">
<div class="col-xs-11 col-sm-8 col-md-6 col-lg-5 horizontal-center">
{{ block.super }}
{% endblock %}
{% block login_header %}
{% include 'auth/_splash.html' %}
{{ block.super }}
{% endblock %}
{% block post_login %}
{{ block.super }}
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,54 @@
{% load i18n %}
{% block pre_login %}
<form id="" class="ng-pristine ng-valid ng-scope"
method="POST"
action="{% url 'horizon:signup:signup:index' %}"
autocomplete="off"
ng-controller="hzLoginController">
{% csrf_token %}
{% endblock %}
<div class="panel panel-default">
<div class="panel-heading">
{% block login_header %}
<h3 class="login-title">
{% trans 'Sign Up' %}
</h3>
{% endblock %}
</div>
<div class="panel-body">
{% block login_body %}
{% comment %}
These fake fields are required to prevent Chrome v34+ from autofilling form.
{% endcomment %}
{% if HORIZON_CONFIG.password_autocomplete != "on" %}
<div class="fake_credentials" style="display: none">
<input type="text" name="fake_email" value="" />
<input type="password" name="fake_password" value="" />
</div>
{%endif%}
<fieldset hz-login-finder>
{% include "horizon/common/_form_fields.html" %}
</fieldset>
{% endblock %}
</div>
<div class="panel-footer">
{% block login_footer %}
<button id="loginBtn" type="submit" class="btn btn-primary pull-right">
<span>{% trans "Submit" %}</span>
</button>
<a href="/" class="btn btn-default cancel">
{% trans "Back to login" %}
</a>
<div class="clearfix"></div>
{% endblock %}
</div>
</div>
{% block post_login%}
</form>
{% endblock %}

View File

@ -0,0 +1,20 @@
{% extends 'signup/_sent_text.html' %}
{% block pre_login %}
<div class="container login">
<div class="row">
<div class="col-xs-11 col-sm-8 col-md-6 col-lg-5 horizontal-center">
{{ block.super }}
{% endblock %}
{% block login_header %}
{% include 'auth/_splash.html' %}
{{ block.super }}
{% endblock %}
{% block post_login %}
{{ block.super }}
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,34 @@
{% load i18n %}
{% block pre_login %}
<form>
{% csrf_token %}
{% endblock %}
<div class="panel panel-default">
<div class="panel-heading">
{% block login_header %}
<h3 class="login-title">
{% trans 'Sign Up' %}
</h3>
{% endblock %}
</div>
<div class="panel-body">
{% block login_body %}
{% trans "Your signup request has been submitted. An email will be sent once an administator approves your request." %}
{% endblock %}
</div>
<div class="panel-footer">
{% block login_footer %}
<a href="/" class="pull-right">{% trans "Back to log in" %}</a>
<div class="clearfix"></div>
{% endblock %}
</div>
</div>
{% block post_login%}
</form>
{% endblock %}

View File

@ -0,0 +1,11 @@
{% extends "base.html" %}
{% load i18n %}
{% block title %}{% trans "Sign Up" %}{% endblock %}
{% block body_id %}splash{% endblock %}
{% block content %}
{% include 'signup/_index.html' %}
{% endblock %}

View File

@ -0,0 +1,9 @@
{% extends "base.html" %}
{% load i18n %}
{% block title %}{% trans "Signup Submitted" %}{% endblock %}
{% block body_id %}splash{% endblock %}
{% block content %}
{% include 'signup/_sent.html' %}
{% endblock %}

View File

@ -0,0 +1,24 @@
# Copyright (c) 2016 Catalyst IT Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from django.conf.urls import patterns
from django.conf.urls import url
from adjutant_ui.content.signup import views
urlpatterns = patterns(
'',
url(r'^/?$', views.SignupFormView.as_view(), name='index'),
url(r'^submitted/?$', views.signup_sent_view, name='submitted'),
)

View File

@ -0,0 +1,31 @@
# Copyright (c) 2016 Catalyst IT Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from django.shortcuts import render
from django.core.urlresolvers import reverse_lazy
from horizon import forms
from adjutant_ui.content.signup import forms as su_forms
class SignupFormView(forms.ModalFormView):
form_class = su_forms.SignupForm
submit_url = reverse_lazy("horizon:signup:signup:index")
success_url = reverse_lazy("horizon:signup:signup:submitted")
template_name = 'signup/index.html'
def signup_sent_view(request):
return render(request, 'signup/submitted.html')

View File

@ -0,0 +1,31 @@
# Copyright (c) 2014 Catalyst IT Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from django.utils.translation import ugettext_lazy as _
import horizon
from adjutant_ui.content.signup import panel
class SignupDashboard(horizon.Dashboard):
name = _("Sign Up")
slug = "signup"
default_panel = 'signup'
nav = False
public = True
horizon.register(SignupDashboard)
SignupDashboard.register(panel.SignupPanel)

View File

@ -4,5 +4,6 @@ FEATURE = "adjutant-ui-base"
# A list of applications to be added to INSTALLED_APPS.
ADD_INSTALLED_APPS = [
'adjutant_ui'
'adjutant_ui',
'overextends',
]

View File

@ -5,5 +5,4 @@ DASHBOARD = 'forgot_password'
ADD_INSTALLED_APPS = [
'adjutant_ui.dashboards.forgot_password_dash',
'adjutant_ui.content.forgot_password',
'overextends',
]

View File

@ -0,0 +1,8 @@
# The name of the dashboard to be added to HORIZON['dashboards']. Required.
DASHBOARD = 'signup'
# A list of applications to be added to INSTALLED_APPS.
ADD_INSTALLED_APPS = [
'adjutant_ui.dashboards.signup_dash',
'adjutant_ui.content.signup',
]