From: Tom Hughes Date: Wed, 20 Aug 2014 12:55:40 +0000 (+0100) Subject: Add an OSM authentication provider X-Git-Tag: live~12 X-Git-Url: https://git.openstreetmap.org./osqa.git/commitdiff_plain/a7918118f11ba4e856d06307f20aba6057552e07?ds=sidebyside Add an OSM authentication provider --- diff --git a/forum_modules/osmauth/__init__.py b/forum_modules/osmauth/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/forum_modules/osmauth/authentication.py b/forum_modules/osmauth/authentication.py new file mode 100644 index 0000000..7c8e702 --- /dev/null +++ b/forum_modules/osmauth/authentication.py @@ -0,0 +1,21 @@ +from forum.authentication.base import AuthenticationConsumer, ConsumerTemplateContext, InvalidAuthentication +from forms import OpenStreetMapLoginForm + +class OpenStreetMapAuthConsumer(AuthenticationConsumer): + def process_authentication_request(self, request): + form_auth = OpenStreetMapLoginForm(request.POST) + + if form_auth.is_valid(): + request.session["auth_consumer_data"] = form_auth.get_user_data() + return form_auth.get_user() + else: + raise InvalidAuthentication(" ".join(form_auth.errors.values()[0])) + + def get_user_data(self, key): + return {} + +class OpenStreetMapAuthContext(ConsumerTemplateContext): + mode = 'TOP_STACK_ITEM' + weight = 0 + human_name = 'OpenStreetMap Login' + stack_item_template = 'modules/osmauth/loginform.html' diff --git a/forum_modules/osmauth/forms.py b/forum_modules/osmauth/forms.py new file mode 100644 index 0000000..c59475e --- /dev/null +++ b/forum_modules/osmauth/forms.py @@ -0,0 +1,72 @@ +from osm import OpenStreetMapAPI +from forum.forms import NextUrlField, UserNameField, SetPasswordForm +from django.utils.translation import ugettext as _ +from django import forms + +class OpenStreetMapLoginForm(forms.Form): + """ osm account signin form """ + next = NextUrlField() + username = UserNameField(required=False, skip_clean=True) + password = forms.CharField(max_length=128, + widget=forms.widgets.PasswordInput(attrs={'class':'required login'}), + required=False) + + def __init__(self, data=None, files=None, auto_id='id_%s', + prefix=None, initial=None): + super(OpenStreetMapLoginForm, self).__init__(data, files, auto_id, + prefix, initial) + self.user_details = None + + def _clean_nonempty_field(self, field): + value = None + if field in self.cleaned_data: + value = self.cleaned_data[field].strip() + if value == '': + value = None + self.cleaned_data[field] = value + return value + + def clean_username(self): + return self._clean_nonempty_field('username') + + def clean_password(self): + return self._clean_nonempty_field('password') + + def clean(self): + error_list = [] + username = self.cleaned_data['username'] + password = self.cleaned_data['password'] + + self.user_details = None + if username and password: + api = OpenStreetMapAPI(username, password) + + try: + self.user_details = api.user_details() + except: + del self.cleaned_data['username'] + del self.cleaned_data['password'] + error_list.insert(0, (_("Please enter valid username and password " + "(both are case-sensitive)."))) + error_list.insert(0, _('Login failed.')) + + elif password == None and username == None: + error_list.append(_('Please enter username and password')) + elif password == None: + error_list.append(_('Please enter your password')) + elif username == None: + error_list.append(_('Please enter user name')) + if len(error_list) > 0: + self._errors['__all__'] = forms.util.ErrorList(error_list) + + return self.cleaned_data + + def get_user(self): + """ get authenticated user """ + return "http://www.openstreetmap.org/user/%s" % self.user_details["id"] + + def get_user_data(self): + """ get user data for authenticated user """ + return { + "username": self.user_details["display_name"] + } diff --git a/forum_modules/osmauth/osm.py b/forum_modules/osmauth/osm.py new file mode 100644 index 0000000..94dcd13 --- /dev/null +++ b/forum_modules/osmauth/osm.py @@ -0,0 +1,19 @@ +from xml.etree.ElementTree import ElementTree +import urllib2 + +class OpenStreetMapAPI: + def __init__(self, username, password): + passman = urllib2.HTTPPasswordMgr() + passman.add_password("Web Password", "https://api.openstreetmap.org/api/0.6", username, password) + authhandler = urllib2.HTTPBasicAuthHandler(passman) + self.opener = urllib2.build_opener(authhandler) + + def user_details(self): + response = self.opener.open("https://api.openstreetmap.org/api/0.6/user/details") + tree = ElementTree() + root = tree.parse(response) + user = root.find("user") + return { + "id": user.attrib["id"], + "display_name": user.attrib["display_name"] + } diff --git a/forum_modules/osmauth/templates/loginform.html b/forum_modules/osmauth/templates/loginform.html new file mode 100644 index 0000000..5091dfa --- /dev/null +++ b/forum_modules/osmauth/templates/loginform.html @@ -0,0 +1,31 @@ +{% load i18n %} + +
+

{% trans 'Enter your OpenStreetMap username and password' %}
({% trans 'or select your external provider below' %})

+ + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + {% trans 'Create account' %} | {% trans 'Forgot your password?' %} +
+
diff --git a/forum_modules/osmauth/urls.py b/forum_modules/osmauth/urls.py new file mode 100644 index 0000000..62581f0 --- /dev/null +++ b/forum_modules/osmauth/urls.py @@ -0,0 +1,8 @@ +from django.conf.urls.defaults import * +from django.views.generic.simple import direct_to_template +from django.utils.translation import ugettext as _ +import views as app + +urlpatterns = patterns('', + url(r'^%s%s%s$' % (_('account/'), _('openstreetmap/'), _('register/')), app.register, name='auth_openstreetmap_register'), +)