From 3c0dca0fa30e52eec687f7eed45b6555338d0b10 Mon Sep 17 00:00:00 2001 From: Andrew Williams Date: Fri, 6 Aug 2010 13:46:07 +0100 Subject: [PATCH] API authentication (/api/login) now uses a seperate API password field. --- api/handlers.py | 2 +- sso/forms.py | 5 + ...__del_field_ssouser_xmpp__del_field_sso.py | 126 ++++++++++++++++++ sso/models.py | 9 +- sso/urls.py | 1 + sso/views.py | 16 ++- templates/apipassword.html | 17 +++ templates/sso/apipassword.html | 17 +++ 8 files changed, 183 insertions(+), 10 deletions(-) create mode 100644 sso/migrations/0002_auto__del_field_ssouser_website__del_field_ssouser_xmpp__del_field_sso.py create mode 100644 templates/apipassword.html create mode 100644 templates/sso/apipassword.html diff --git a/api/handlers.py b/api/handlers.py index 08d7abd..71eb04b 100755 --- a/api/handlers.py +++ b/api/handlers.py @@ -75,7 +75,7 @@ class LoginHandler(BaseHandler): 'email': u.email, 'groups': u.groups.all(), 'staff': u.is_staff, 'superuser': u.is_superuser } - if request.GET.get('pass', None) and request.GET['pass'] == u.password: + if request.GET.get('pass', None) and request.GET['pass'] == u.get_profile().api_service_password: return d return { 'auth': 'failed' } diff --git a/sso/forms.py b/sso/forms.py index 0a1d85e..b784b08 100644 --- a/sso/forms.py +++ b/sso/forms.py @@ -117,3 +117,8 @@ class UserLookupForm(forms.Form): raise forms.ValidationError("Account doesn't exist") return self.cleaned_data + +class APIPasswordForm(forms.Form): + + password = forms.CharField(widget=forms.PasswordInput, label="Password" ) + diff --git a/sso/migrations/0002_auto__del_field_ssouser_website__del_field_ssouser_xmpp__del_field_sso.py b/sso/migrations/0002_auto__del_field_ssouser_website__del_field_ssouser_xmpp__del_field_sso.py new file mode 100644 index 0000000..2663ed6 --- /dev/null +++ b/sso/migrations/0002_auto__del_field_ssouser_website__del_field_ssouser_xmpp__del_field_sso.py @@ -0,0 +1,126 @@ +# encoding: utf-8 +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + +class Migration(SchemaMigration): + + def forwards(self, orm): + + # Deleting field 'SSOUser.website' + db.delete_column('sso_ssouser', 'website') + + # Deleting field 'SSOUser.xmpp' + db.delete_column('sso_ssouser', 'xmpp') + + # Deleting field 'SSOUser.default_service_username' + db.delete_column('sso_ssouser', 'default_service_username') + + # Deleting field 'SSOUser.aim' + db.delete_column('sso_ssouser', 'aim') + + # Deleting field 'SSOUser.msn' + db.delete_column('sso_ssouser', 'msn') + + # Deleting field 'SSOUser.default_service_passwd' + db.delete_column('sso_ssouser', 'default_service_passwd') + + # Deleting field 'SSOUser.icq' + db.delete_column('sso_ssouser', 'icq') + + # Adding field 'SSOUser.api_service_password' + db.add_column('sso_ssouser', 'api_service_password', self.gf('django.db.models.fields.CharField')(default='', max_length=200, blank=True), keep_default=False) + + + def backwards(self, orm): + + # Adding field 'SSOUser.website' + db.add_column('sso_ssouser', 'website', self.gf('django.db.models.fields.CharField')(default='', max_length=200, blank=True), keep_default=False) + + # Adding field 'SSOUser.xmpp' + db.add_column('sso_ssouser', 'xmpp', self.gf('django.db.models.fields.CharField')(default='', max_length=200, blank=True), keep_default=False) + + # Adding field 'SSOUser.default_service_username' + db.add_column('sso_ssouser', 'default_service_username', self.gf('django.db.models.fields.CharField')(default='', max_length=200, blank=True), keep_default=False) + + # Adding field 'SSOUser.aim' + db.add_column('sso_ssouser', 'aim', self.gf('django.db.models.fields.CharField')(default='', max_length=64, blank=True), keep_default=False) + + # Adding field 'SSOUser.msn' + db.add_column('sso_ssouser', 'msn', self.gf('django.db.models.fields.CharField')(default='', max_length=200, blank=True), keep_default=False) + + # Adding field 'SSOUser.default_service_passwd' + db.add_column('sso_ssouser', 'default_service_passwd', self.gf('django.db.models.fields.CharField')(default='', max_length=200, blank=True), keep_default=False) + + # Adding field 'SSOUser.icq' + db.add_column('sso_ssouser', 'icq', self.gf('django.db.models.fields.CharField')(default='', max_length=15, blank=True), keep_default=False) + + # Deleting field 'SSOUser.api_service_password' + db.delete_column('sso_ssouser', 'api_service_password') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '80', 'unique': 'True'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False', 'blank': 'True'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'max_length': '30', 'unique': 'True'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'sso.service': { + 'Meta': {'object_name': 'Service'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'api': ('django.db.models.fields.CharField', [], {'max_length': '200'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '200'}), + 'settings_json': ('jsonfield.fields.JSONField', [], {'blank': 'True'}), + 'url': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}) + }, + 'sso.serviceaccount': { + 'Meta': {'object_name': 'ServiceAccount'}, + 'active': ('django.db.models.fields.BooleanField', [], {'default': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'service': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sso.Service']"}), + 'service_uid': ('django.db.models.fields.CharField', [], {'max_length': '200'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'sso.ssouser': { + 'Meta': {'object_name': 'SSOUser'}, + 'api_service_password': ('django.db.models.fields.CharField', [], {'max_length': '200', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'user': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'profile'", 'unique': 'True', 'to': "orm['auth.User']"}) + } + } + + complete_apps = ['sso'] diff --git a/sso/models.py b/sso/models.py index 1d1e619..b738ea9 100644 --- a/sso/models.py +++ b/sso/models.py @@ -32,14 +32,7 @@ class SSOUser(models.Model): user = models.ForeignKey(User, unique=True, related_name='profile') - default_service_passwd = models.CharField("Default Service Password", max_length=200, blank=True) - default_service_username = models.CharField("Default Service Username", max_length=200, blank=True) - - website = models.CharField("Website URL", max_length=200, blank=True) - aim = models.CharField("AIM", max_length=64, blank=True) - msn = models.CharField("MSN", max_length=200, blank=True) - icq = models.CharField("ICQ", max_length=15, blank=True) - xmpp = models.CharField("XMPP", max_length=200, blank=True) + api_service_password = models.CharField("API Services Password", max_length=200, blank=True) @property def _log(self): diff --git a/sso/urls.py b/sso/urls.py index b9f5a6e..0cfeed4 100644 --- a/sso/urls.py +++ b/sso/urls.py @@ -20,6 +20,7 @@ urlpatterns = patterns('', (r'^profile/log/eveapi/(?P\d+)/$', views.eveapi_log), (r'^profile/characters$', views.characters), (r'^profile/characters/(?P.*)/$', views.characters), + (r'^profile/apipassword/', views.set_apipassword), (r'^users/(?P.*)/$', views.user_view), (r'^users/$', views.user_lookup), ) diff --git a/sso/views.py b/sso/views.py index 871246b..1abeb33 100644 --- a/sso/views.py +++ b/sso/views.py @@ -15,7 +15,7 @@ from eve_api.models.api_player import EVEAccount, EVEPlayerCharacter from eve_proxy.models import ApiAccessLog from sso.models import ServiceAccount, Service, SSOUser, ExistingUser, ServiceError -from sso.forms import EveAPIForm, UserServiceAccountForm, ServiceAccountResetForm, RedditAccountForm, UserLookupForm +from sso.forms import EveAPIForm, UserServiceAccountForm, ServiceAccountResetForm, RedditAccountForm, UserLookupForm, APIPasswordForm from reddit.models import RedditAccount @@ -341,3 +341,17 @@ def user_lookup(request): return HttpResponseRedirect(reverse('sso.views.user_lookup')) return render_to_response('sso/lookup/userlookup.html', locals(), context_instance=RequestContext(request)) + + +@login_required +def set_apipasswd(request): + if request.method == 'POST': + form = APIPasswordForm(request.POST) + if form.is_valid(): + request.user.message_set.create(message="Your API Services password has been set.") + return HttpResponseRedirect(reverse('sso.views.profile')) # Redirect after POST + else: + form = APIPasswordForm(defaults) # An unbound form + + return render_to_response('sso/apipassword.html', locals(), context_instance=RequestContext(request)) + diff --git a/templates/apipassword.html b/templates/apipassword.html new file mode 100644 index 0000000..99005e2 --- /dev/null +++ b/templates/apipassword.html @@ -0,0 +1,17 @@ +{% extends "base.html" %} + +{% block title %}External Service Account Password Reset{% endblock %} + +{% block content %} + +

This service will reset your password for account {{ acc.service_uid }} on {{ acc.service }}. If you wish to continue please click the link +below.

+ +
+ +{{ form.as_table }} +
+ +
+ +{% endblock %} diff --git a/templates/sso/apipassword.html b/templates/sso/apipassword.html new file mode 100644 index 0000000..84377ec --- /dev/null +++ b/templates/sso/apipassword.html @@ -0,0 +1,17 @@ +{% extends "base.html" %} + +{% block title %}API Services Password Reset{% endblock %} + +{% block content %} + +

This service will reset your password for all API Services. If you wish to continue please click the link +below.

+ +
+ +{{ form.as_table }} +
+ +
+ +{% endblock %}