From cb49170d330ee2af36b6e317fde2914e0a9a9315 Mon Sep 17 00:00:00 2001 From: Andrew Williams Date: Fri, 12 Mar 2010 12:16:07 +0000 Subject: [PATCH] Restricts service account usernames to charnames * Forms now show a character selection box * Once created, user is sent to a template with a generated password * Will not display a service if a account already exists on it. --- sso/forms.py | 36 ++++++----------------- sso/models.py | 12 ++++++-- sso/views.py | 12 +++++--- templates/sso/serviceaccount_created.html | 29 ++++++++++++++++++ 4 files changed, 55 insertions(+), 34 deletions(-) create mode 100644 templates/sso/serviceaccount_created.html diff --git a/sso/forms.py b/sso/forms.py index 1678715..da81a07 100644 --- a/sso/forms.py +++ b/sso/forms.py @@ -25,44 +25,26 @@ class EveAPIForm(forms.Form): else: raise forms.ValidationError("This API User ID is already registered") -class ServiceUsernameField(forms.CharField): - """ Extension of a CharField, does extra validation on username format and - also checks the username is free with ServiceAccount model """ - - def clean(self, request, initial=None): - field = super(ServiceUsernameField, self).clean(request) - - # Checks that usernames consist of letters and numbers only - if not re.match("^[A-Za-z0-9_-]*$", field): - raise forms.ValidationError("Invalid character in username, use letters and numbers only") - - return field - def UserServiceAccountForm(user): """ Generate a Service Account form based on the user's permissions """ current_services = [] for sa in ServiceAccount.objects.filter(user=user): current_services.append(sa.service) - services = set(Service.objects.filter(groups__in=user.groups.all())) - set(current_services) + eveacc = EVEAccount.objects.filter(user=user) + chars = [] + for srv in services: + for char in eveacc.characters.all(): + if char.corporation.group = srv.group and not char in chars: + chars.append(char) + class ServiceAccountForm(forms.Form): """ Service Account Form """ - service = forms.ModelChoiceField(queryset=services) - username = ServiceUsernameField(min_length=4,max_length=50) - password = forms.CharField(label = u'Password',widget = forms.PasswordInput(render_value=False)) - - def clean(self): - try: - acc = ServiceAccount.objects.get(service_uid=self.cleaned_data['username'],service=self.cleaned_data['service']) - except ServiceAccount.DoesNotExist: - pass - else: - raise forms.ValidationError("That username is already taken") - return self.cleaned_data - + character = forms.ChoiceField(chars) + service = forms.ChoiceField(services) return ServiceAccountForm diff --git a/sso/models.py b/sso/models.py index d7fe891..492fddc 100644 --- a/sso/models.py +++ b/sso/models.py @@ -1,3 +1,5 @@ +import unicodedata + from django.db import models from django.db.models import signals from django.contrib.auth.models import User, UserManager, Group @@ -93,6 +95,7 @@ class ServiceAccount(models.Model): service_uid = models.CharField("Service UID", max_length=200, blank=False) active = models.BooleanField(default=True) + character = None username = None password = None @@ -102,9 +105,12 @@ class ServiceAccount(models.Model): def save(self): """ Override default save to setup accounts as needed """ - # If no username has been specified, use the default - if not self.username: - self.username = self.user.username + # Force username to be the same as their selected character + # Fix unicode first of all + name = unicodedata.normalize('NFKD', self.character.name).encode('ASCII', 'ignore') + + # Remove spaces and non-acceptable characters + self.username = re.sub('[^a-zA-Z0-9_-]+', '', name) # Grab the API class api = self.service.api_class diff --git a/sso/views.py b/sso/views.py index 0514610..b7e5b24 100644 --- a/sso/views.py +++ b/sso/views.py @@ -1,3 +1,5 @@ +import hashlib + from django.http import HttpResponseRedirect from django.shortcuts import render_to_response from django.core.urlresolvers import reverse @@ -97,14 +99,16 @@ def service_add(request): acc.user = request.user acc.service = form.cleaned_data['service'] - acc.username = form.cleaned_data['username'] - acc.password = form.cleaned_data['password'] + acc.password = hashlib.sha1('%s%s' % form.cleaned_data['service'].name, request.user.username).hexdigest() try: acc.save() except ExistingUser: - pass - return HttpResponseRedirect(reverse('sso.views.profile')) # Redirect after POST + error = "User by this name already exists, your account has not been created" + else: + error = None + + return render_to_response('sso/serviceaccount_created.html', { 'account': acc, 'error': error }) else: #defaults = { 'username': request.user.username, 'password': request.user.get_profile().default_service_passwd } form = clsform() # An unbound form diff --git a/templates/sso/serviceaccount_created.html b/templates/sso/serviceaccount_created.html new file mode 100644 index 0000000..43facbe --- /dev/null +++ b/templates/sso/serviceaccount_created.html @@ -0,0 +1,29 @@ +{% extends "base.html" %} + +{% if error %} +{% block title %}Service Account Error{% endblock %} +{% else %} +{% block title %}Service Account{% endblock %} +{% endif %} + +{% block content %} +{% if error %} +
+Error: Your account has not been created. Either you already have a user on this service or a error has occured. If you think +this is incorrect please raise a bug on the tracker. +
+{% else %} +

Your account on {{ account.service }} has been created. Your login details are as follows:

+ + + + +
Username:{{ account.service_uid }}
Password:{{ account.password }}
+ +

Warning: You password is random, please either note it down or once logged into the service change it to something you +will remember. Service passwords are not stored in the Auth system.

+ +

Return to your profile page

+{% endif %} + +{% endblock %}