Added password-secure checks for UI, fix usability issues for demo.

This commit is contained in:
Timur Nurlygayanov 2013-03-13 13:31:49 +04:00
parent bb7c3577dc
commit 6046f99369
5 changed files with 134 additions and 117 deletions

View File

@ -24,7 +24,6 @@ import urlparse
from django.utils.decorators import available_attrs from django.utils.decorators import available_attrs
from portasclient.v1.client import Client as windc_client from portasclient.v1.client import Client as windc_client
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -91,9 +90,6 @@ def services_create(request, datacenter, parameters):
def services_list(request, datacenter_id): def services_list(request, datacenter_id):
session_id = request.user.token.token['id']
services = []
session_id = None session_id = None
sessions = windcclient(request).sessions.list(datacenter_id) sessions = windcclient(request).sessions.list(datacenter_id)
for s in sessions: for s in sessions:
@ -114,5 +110,25 @@ def services_get(request, datacenter, service_id):
return windcclient(request).services.get(datacenter, service_id) return windcclient(request).services.get(datacenter, service_id)
def services_delete(request, datacenter, service_id): def services_delete(request, datacenter_id, service_id):
return windcclient(request).services.delete(datacenter, service_id) services = services_list(request, datacenter_id)
session_id = None
sessions = windcclient(request).sessions.list(datacenter_id)
for session in sessions:
if session.state == 'open':
session_id = session.id
if session_id is None:
raise Exception("Sorry, you can not delete this service now.")
for service in services:
if service.id is service_id:
if service.type is 'Active Directory':
windcclient(request).activeDirectories.delete(datacenter_id,
session_id,
service_id)
elif service.type is 'IIS':
windcclient(request).webServers.delete(datacenter_id,
session_id,
service_id)

View File

@ -19,6 +19,7 @@
# under the License. # under the License.
import logging import logging
import string
from django import forms from django import forms
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
@ -30,13 +31,54 @@ from horizon import forms
from horizon import exceptions from horizon import exceptions
from horizon import messages from horizon import messages
import pdb
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
class PasswordField(forms.CharField):
# Setup the Field
def __init__(self, label, *args, **kwargs):
super(PasswordField, self).__init__(min_length=7, required=True,
label=label,
widget=forms.PasswordInput(render_value=False),
*args, **kwargs)
def clean(self, value):
# Setup Our Lists of Characters and Numbers
characters = list(string.letters)
special_characters = '!@#$%^&*()_+|\/.,~?><:{}'
numbers = [str(i) for i in range(10)]
# Assume False until Proven Otherwise
numCheck = False
charCheck = False
specCharCheck = False
# Loop until we Match
for char in value:
if not charCheck:
if char in characters:
charCheck = True
if not specCharCheck:
if char in special_characters:
specCharCheck = True
if not numCheck:
if char in numbers:
numCheck = True
if numCheck and charCheck and specCharCheck:
break
if not numCheck or not charCheck or not specCharCheck:
raise forms.ValidationError(u'Your password must include at least \
one letter, at least one number and \
at least one special character.')
return super(PasswordField, self).clean(value)
class WizardFormServiceType(forms.Form): class WizardFormServiceType(forms.Form):
service = forms.ChoiceField(label=_("Service Type"), service = forms.ChoiceField(label=_('Service Type'),
choices=[ choices=[
('Active Directory', 'Active Directory'), ('Active Directory', 'Active Directory'),
('IIS', 'Internet Information Services') ('IIS', 'Internet Information Services')
@ -44,62 +86,35 @@ class WizardFormServiceType(forms.Form):
class WizardFormConfiguration(forms.Form): class WizardFormConfiguration(forms.Form):
"The functions for this class will dynamically create in views.py" 'The functions for this class will dynamically create in views.py'
pass pass
class WizardFormADConfiguration(forms.Form): class WizardFormADConfiguration(forms.Form):
dc_name = forms.CharField(label=_("Domain Name"), dc_name = forms.CharField(label=_('Domain Name'),
required=False) required=True)
dc_count = forms.IntegerField(label=_("Instances Count"), dc_count = forms.IntegerField(label=_('Instances Count'),
required=True, required=True,
min_value=1, min_value=1,
max_value=100, max_value=100,
initial=1) initial=1)
adm_password = forms.CharField(widget=forms.PasswordInput, adm_password = PasswordField(_('Administrator password'))
label=_("Administrator password"),
required=False)
recovery_password = forms.CharField(widget=forms.PasswordInput, recovery_password = PasswordField(_('Recovery password'))
label=_("Recovery password"),
required=False)
class WizardFormIISConfiguration(forms.Form): class WizardFormIISConfiguration(forms.Form):
iis_name = forms.CharField(label=_("IIS Server Name"), iis_name = forms.CharField(label=_('IIS Server Name'),
required=False) required=True)
adm_password = forms.CharField(widget=forms.PasswordInput, adm_password = PasswordField(_('Administrator password'))
label=_("Administrator password"),
required=False)
iis_domain = forms.CharField(label=_("Member of the Domain"), iis_domain = forms.CharField(label=_('Member of the Domain'),
required=False) required=True)
domain_user_name = forms.CharField(label=_("Domain User Name"), domain_user_name = forms.CharField(label=_('Domain User Name'),
required=False) required=True)
domain_user_password = forms.CharField(widget=forms.PasswordInput, domain_user_password = PasswordField(_('Domain User Password'))
label=_("Domain User Password"),
required=False)
class UpdateWinDC(forms.SelfHandlingForm):
tenant_id = forms.CharField(widget=forms.HiddenInput)
data_center = forms.CharField(widget=forms.HiddenInput)
name = forms.CharField(required=True)
def handle(self, request, data):
try:
server = api.nova.server_update(request, data['data_center'],
data['name'])
messages.success(request,
_('Data Center "%s" updated.') % data['name'])
return server
except:
redirect = reverse("horizon:project:windc:index")
exceptions.handle(request,
_('Unable to update data center.'),
redirect=redirect)

View File

@ -43,24 +43,23 @@ LOG = logging.getLogger(__name__)
class CreateService(tables.LinkAction): class CreateService(tables.LinkAction):
name = "CreateService" name = 'CreateService'
verbose_name = _("Create Service") verbose_name = _('Create Service')
url = "horizon:project:windc:create" url = 'horizon:project:windc:create'
classes = ("btn-launch", "ajax-modal") classes = ('btn-launch', 'ajax-modal')
def allowed(self, request, datum): def allowed(self, request, datum):
return True return True
def action(self, request, service): def action(self, request, service):
# FIX ME
api.windc.services_create(request, service) api.windc.services_create(request, service)
class CreateDataCenter(tables.LinkAction): class CreateDataCenter(tables.LinkAction):
name = "CreateDataCenter" name = 'CreateDataCenter'
verbose_name = _("Create Windows Data Center") verbose_name = _('Create Windows Data Center')
url = "horizon:project:windc:create_dc" url = 'horizon:project:windc:create_dc'
classes = ("btn-launch", "ajax-modal") classes = ('btn-launch', 'ajax-modal')
def allowed(self, request, datum): def allowed(self, request, datum):
return True return True
@ -70,11 +69,11 @@ class CreateDataCenter(tables.LinkAction):
class DeleteDataCenter(tables.BatchAction): class DeleteDataCenter(tables.BatchAction):
name = "delete" name = 'delete'
action_present = _("Delete") action_present = _('Delete')
action_past = _("Delete") action_past = _('Delete')
data_type_singular = _("Data Center") data_type_singular = _('Data Center')
data_type_plural = _("Data Center") data_type_plural = _('Data Center')
classes = ('btn-danger', 'btn-terminate') classes = ('btn-danger', 'btn-terminate')
def allowed(self, request, datum): def allowed(self, request, datum):
@ -85,62 +84,52 @@ class DeleteDataCenter(tables.BatchAction):
class DeleteService(tables.BatchAction): class DeleteService(tables.BatchAction):
name = "delete" name = 'delete'
action_present = _("Delete") action_present = _('Delete')
action_past = _("Delete") action_past = _('Delete')
data_type_singular = _("Service") data_type_singular = _('Service')
data_type_plural = _("Service") data_type_plural = _('Service')
classes = ('btn-danger', 'btn-terminate') classes = ('btn-danger', 'btn-terminate')
def allowed(self, request, datum): def allowed(self, request, datum):
return True return True
def action(self, request, service_id): def action(self, request, service_id):
############## FIX ME:
link = request.__dict__['META']['HTTP_REFERER'] link = request.__dict__['META']['HTTP_REFERER']
datacenter_id = re.search('windc/(\S+)', link).group(0)[6:-1] datacenter_id = re.search('windc/(\S+)', link).group(0)[6:-1]
##############
api.windc.services_delete(request, datacenter_id, service_id) try:
api.windc.services_delete(request, datacenter_id, service_id)
except:
messages.error(request,
_('Sorry, you can not delete this service right now.'))
class DeployDataCenter(tables.BatchAction): class DeployDataCenter(tables.BatchAction):
name = "deploy" name = 'deploy'
action_present = _("Deploy") action_present = _('Deploy')
action_past = _("Deploy") action_past = _('Deploy')
data_type_singular = _("Data Center") data_type_singular = _('Data Center')
data_type_plural = _("Data Center") data_type_plural = _('Data Center')
classes = ("btn-launch") classes = ('btn-launch')
def allowed(self, request, datum): def allowed(self, request, datum):
return True return True
def action(self, request, datacenter_id): def action(self, request, datacenter_id):
#link = request.__dict__['META']['HTTP_REFERER']
#datacenter_id = re.search('windc/(\S+)', link).group(0)[6:-1]
return api.windc.datacenters_deploy(request, datacenter_id) return api.windc.datacenters_deploy(request, datacenter_id)
class EditService(tables.LinkAction):
name = "edit"
verbose_name = _("Edit")
url = "horizon:project:windc:update"
classes = ("ajax-modal", "btn-edit")
def allowed(self, request, instance):
return True
class ShowDataCenterServices(tables.LinkAction): class ShowDataCenterServices(tables.LinkAction):
name = "edit" name = 'edit'
verbose_name = _("Services") verbose_name = _('Services')
url = "horizon:project:windc:services" url = 'horizon:project:windc:services'
def allowed(self, request, instance): def allowed(self, request, instance):
return True return True
class UpdateRow(tables.Row): class UpdateDCRow(tables.Row):
ajax = True ajax = True
def get_data(self, request, datacenter_id): def get_data(self, request, datacenter_id):
@ -164,16 +153,16 @@ class WinDCTable(tables.DataTable):
STATUS_CHOICES = ( STATUS_CHOICES = (
(None, True), (None, True),
("Ready to deploy", False), ('Ready to deploy', False),
("deploying", True), ('deploying', True),
("deployed", True), ('deployed', True),
("ready", True), ('ready', True),
("error", False), ('error', False),
) )
name = tables.Column("name", name = tables.Column('name',
link=("horizon:project:windc:services"), link=('horizon:project:windc:services'),
verbose_name=_("Name")) verbose_name=_('Name'))
status = tables.Column(get_datacenter_status, verbose_name=_('Status'), status = tables.Column(get_datacenter_status, verbose_name=_('Status'),
status=True, status=True,
@ -181,9 +170,9 @@ class WinDCTable(tables.DataTable):
display_choices=STATUS_DISPLAY_CHOICES) display_choices=STATUS_DISPLAY_CHOICES)
class Meta: class Meta:
name = "windc" name = 'windc'
verbose_name = _("Windows Data Centers") verbose_name = _('Windows Data Centers')
row_class = UpdateRow row_class = UpdateDCRow
table_actions = (CreateDataCenter,) table_actions = (CreateDataCenter,)
status_columns = ['status'] status_columns = ['status']
row_actions = (ShowDataCenterServices, DeleteDataCenter, row_actions = (ShowDataCenterServices, DeleteDataCenter,
@ -193,12 +182,11 @@ class WinDCTable(tables.DataTable):
class WinServicesTable(tables.DataTable): class WinServicesTable(tables.DataTable):
name = tables.Column('name', verbose_name=_('Name'), name = tables.Column('name', verbose_name=_('Name'),
link=("horizon:project:windc:service_details"),) link=('horizon:project:windc:service_details'),)
_type = tables.Column('service_type', verbose_name=_('Type')) _type = tables.Column('service_type', verbose_name=_('Type'))
class Meta: class Meta:
name = "services" name = 'services'
verbose_name = _("Services") verbose_name = _('Services')
row_class = UpdateRow
table_actions = (CreateService,) table_actions = (CreateService,)
row_actions = (EditService, DeleteService) row_actions = (DeleteService,)

View File

@ -50,9 +50,9 @@
{% block modal-footer %} {% block modal-footer %}
{% if wizard.steps.prev %} {% if wizard.steps.prev %}
<button name="wizard_goto_step" class="btn btn-small" type="submit" value="{{ wizard.steps.prev }}">{% trans "Back" %}</button> <input type="submit" class="btn btn-primary pull-right" value="{% trans 'Create' %}"/>
<input type="submit" class="btn btn-primary pull-right" value="{% trans 'Deploy' %}"/> <button name="wizard_goto_step" class="btn btn-small" type="submit" value="{{ wizard.steps.prev }}">{% trans "< Back" %}</button>
{% else %} {% else %}
<button name="wizard_goto_step" class="btn btn-small" type="submit" value="{{ wizard.steps.next }}">{% trans "Next" %}</button> <button name="wizard_goto_step" class="btn btn-small" type="submit" value="{{ wizard.steps.next }}">{% trans "Next >" %}</button>
{% endif %} {% endif %}
{% endblock %} {% endblock %}

View File

@ -109,7 +109,6 @@ class Wizard(ModalFormMixin, SessionWizardView, generic.FormView):
def get_form(self, step=None, data=None, files=None): def get_form(self, step=None, data=None, files=None):
form = super(Wizard, self).get_form(step, data, files) form = super(Wizard, self).get_form(step, data, files)
LOG.debug("********" + str(self.form_list))
if data: if data:
service_type = data.get('0-service', '') service_type = data.get('0-service', '')
self.service_type = service_type self.service_type = service_type
@ -139,7 +138,6 @@ class IndexView(tables.DataTableView):
try: try:
data_centers = api.windc.datacenters_list(self.request) data_centers = api.windc.datacenters_list(self.request)
for dc in data_centers: for dc in data_centers:
# get the information about session status for each dc
dc.status = api.windc.datacenters_get_status(self.request, dc.status = api.windc.datacenters_get_status(self.request,
dc.id) dc.id)
except: except:
@ -156,7 +154,7 @@ class WinServices(tables.DataTableView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(WinServices, self).get_context_data(**kwargs) context = super(WinServices, self).get_context_data(**kwargs)
data = self.get_data() data = self.get_data()
context["dc_name"] = self.dc_name context['dc_name'] = self.dc_name
return context return context
def get_data(self): def get_data(self):
@ -175,7 +173,7 @@ class WinServices(tables.DataTableView):
class CreateWinDCView(workflows.WorkflowView): class CreateWinDCView(workflows.WorkflowView):
workflow_class = CreateWinDC workflow_class = CreateWinDC
template_name = "project/windc/create_dc.html" template_name = 'project/windc/create_dc.html'
def get_initial(self): def get_initial(self):
initial = super(CreateWinDCView, self).get_initial() initial = super(CreateWinDCView, self).get_initial()