]> git.openstreetmap.org Git - osqa.git/commitdiff
Add an OSM authentication provider
authorTom Hughes <tom@compton.nu>
Wed, 20 Aug 2014 12:55:40 +0000 (13:55 +0100)
committerTom Hughes <tom@compton.nu>
Tue, 12 May 2015 07:56:36 +0000 (08:56 +0100)
forum_modules/osmauth/__init__.py [new file with mode: 0644]
forum_modules/osmauth/authentication.py [new file with mode: 0644]
forum_modules/osmauth/forms.py [new file with mode: 0644]
forum_modules/osmauth/osm.py [new file with mode: 0644]
forum_modules/osmauth/templates/loginform.html [new file with mode: 0644]
forum_modules/osmauth/urls.py [new file with mode: 0644]

diff --git a/forum_modules/osmauth/__init__.py b/forum_modules/osmauth/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/forum_modules/osmauth/authentication.py b/forum_modules/osmauth/authentication.py
new file mode 100644 (file)
index 0000000..7c8e702
--- /dev/null
@@ -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 (file)
index 0000000..c59475e
--- /dev/null
@@ -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 (file)
index 0000000..94dcd13
--- /dev/null
@@ -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 (file)
index 0000000..5091dfa
--- /dev/null
@@ -0,0 +1,31 @@
+{% load i18n %}
+
+<fieldset id='openstreetmap_login_fs'>
+  <p><span class='big strong'>{% trans 'Enter your OpenStreetMap username and password' %}</span><br/><span class='grey'>({% trans 'or select your external provider below' %})</span></p>
+  <table>
+    <tr>
+        <td>
+             <label for="id_osm_username">{% trans 'Username' %}</label>
+        </td>
+        <td>
+             <input id="id_osm_username" type="text" class="required login" name="username" maxlength="255" />
+        </td>
+    </tr>
+    <tr>
+        <td>
+              <label for="id_osm_password">{% trans 'Password' %}</label>
+        </td>
+        <td>
+             <input id="id_osm_password" type="password" class="required login" name="password" maxlength="255" />
+        </td>
+    </tr>
+    <tr>
+        <td>
+            <input id="blogin" name="blogin" type="submit" value="{% trans 'Login' %}" />
+        </td>
+        <td>
+              <a href="https://www.openstreetmap.org/user/new">{% trans 'Create account' %}</a><span>&nbsp;|&nbsp;</span><a href="http://www.openstreetmap.org/user/forgot-password">{% trans 'Forgot your password?' %}</a>
+        </td>
+    </tr>
+  </table>
+</fieldset>
diff --git a/forum_modules/osmauth/urls.py b/forum_modules/osmauth/urls.py
new file mode 100644 (file)
index 0000000..62581f0
--- /dev/null
@@ -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'),
+)