You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@steve.apache.org by hu...@apache.org on 2016/02/10 18:26:52 UTC

svn commit: r1729674 - in /steve/trunk/pysteve/www/wsgi: ./ rest_voter.py

Author: humbedooh
Date: Wed Feb 10 17:26:52 2016
New Revision: 1729674

URL: http://svn.apache.org/viewvc?rev=1729674&view=rev
Log:
first dirty stab at wsgi version.
It..works, and it around 3 times as fast, but needs lots of polishing.

Added:
    steve/trunk/pysteve/www/wsgi/
    steve/trunk/pysteve/www/wsgi/rest_voter.py

Added: steve/trunk/pysteve/www/wsgi/rest_voter.py
URL: http://svn.apache.org/viewvc/steve/trunk/pysteve/www/wsgi/rest_voter.py?rev=1729674&view=auto
==============================================================================
--- steve/trunk/pysteve/www/wsgi/rest_voter.py (added)
+++ steve/trunk/pysteve/www/wsgi/rest_voter.py Wed Feb 10 17:26:52 2016
@@ -0,0 +1,198 @@
+#!/usr/bin/env python
+#####
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#####
+import os, sys, json, re, time, base64, cgi, subprocess, hashlib, re
+from os import listdir
+version = 2
+if sys.hexversion < 0x03000000:
+    import ConfigParser as configparser
+else:
+    import configparser
+    version = 3
+    
+
+path = os.path.abspath(os.getcwd())
+
+sys.path.append(path)
+sys.path.append(os.path.basename(sys.argv[0]))
+sys.path.append(os.path.dirname(__file__))
+
+# Fetch config (hack, hack, hack)
+config = configparser.RawConfigParser()
+config.read('/var/www/steve/steve.cfg') #FIXME!
+
+
+# Some quick paths
+homedir = config.get("general", "homedir")
+
+
+from lib import response, voter, election
+
+
+def application (environ, start_response):
+    pathinfo = environ['PATH_INFO'] if 'PATH_INFO' in environ else None
+    whoami = environ['REMOTE_USER'] if 'REMOTE_USER' in environ else None
+    karma = 0
+    if whoami and config.has_option("karma", whoami):
+        karma = int(config.get("karma", whoami))
+    
+    form = cgi.FieldStorage(
+        fp=environ['wsgi.input'],
+        environ=environ,
+        keep_blank_values=True
+    )
+        
+    # Figure out what to do and where
+    if pathinfo:
+        l = pathinfo.split("/")
+        if l[0] == "":
+            l.pop(0)
+        action = l[0]
+        electionID = l[1] if len(l) > 1 else None
+        issueID = l[2]  if len(l) > 2 else None
+        voterID = form.getvalue('uid')
+        
+        if not voterID and karma < 3 and (action != "request" and action != "peek"):
+            return response.wsgirespond(start_response, 403, {'message': "Voter UID missing"})
+        elif electionID and re.search(r"([^A-Za-z0-9-.])", electionID):
+            return response.wsgirespond(start_response, 400, {'message': "Invalid election ID specified"})
+        elif issueID and re.search(r"([^A-Za-z0-9-.])", issueID):
+            return response.wsgirespond(start_response, 400, {'message': "Invalid issue ID specified"})
+        elif action == "view":
+            # View a list of issues for an election
+            if electionID and not issueID:
+                js = []
+                if election.exists(electionID):
+                    try:
+                        basedata = election.getBasedata(electionID)
+                        if not basedata:
+                            raise Exception("Could not load base data")
+                        if karma < 3 and not voter.get(electionID, basedata, voterID):
+                            raise Exception("Invalid voter ID presented")
+                        if 'closed' in basedata and basedata['closed'] == True:
+                            raise Exception("This election has closed")
+                        for issueID in election.listIssues(electionID):
+                            try:
+                                entry = election.getIssue(electionID, issueID)
+                                entry['hasVoted'] = voter.hasVoted(electionID, issueID, voterID)
+                                js.append(entry)
+                            except Exception as err:
+                                return response.wsgirespond(start_response, 500, {'message': 'Could not load issues: %s' % err})
+                    except Exception as err:
+                        return response.wsgirespond(start_response, 500, {'message': 'Could not load base data: %s' % err})
+                    if 'hash' in basedata:
+                        del basedata['hash']
+                    return response.wsgirespond(start_response, 200, {'base_data': basedata, 'issues': js, 'baseurl': config.get("general", "rooturl")})
+                else:
+                    return response.wsgirespond(start_response, 404, {'message': 'No such election'})
+                    
+            # View a speficic issue
+            elif electionID and issueID:
+                js = []
+                issuedata = election.getIssue(electionID, issueID)
+                if issuedata:
+                    try:
+                        basedata = election.getBasedata(electionID)
+                        if karma < 3 and not voter.get(electionID, basedata, voterID):
+                            raise Exception("Invalid voter ID presented")
+                        if 'closed' in basedata and basedata['closed'] == True:
+                            raise Exception("This election has closed")
+                        entry = election.getIssue(electionID, issueID)
+                        return response.wsgirespond(start_response, 200, {'issue': entry})
+                    except Exception as err:
+                        return response.wsgirespond(start_response, 500, {'message': "Could not load issue: %s" % err})
+                else:
+                    return response.wsgirespond(start_response, 404, {'message': 'No such issue'})
+            else:
+                return response.wsgirespond(start_response, 404, {'message': 'No election ID supplied'})
+                
+                
+                
+        elif action == "vote" and electionID and issueID and voterID:
+            try:
+                basedata = election.getBasedata(electionID)
+                issuedata = election.getIssue(electionID, issueID)
+                if basedata and issuedata:
+                    if 'closed' in basedata and basedata['closed'] == True:
+                            raise Exception("This election has closed")
+                    email = voter.get(electionID, basedata, voterID)
+                    if not email:
+                        return response.wsgirespond(start_response, 403, {'message': 'Could not save vote: Invalid voter ID presented'})
+                    else:
+                        vote = form.getvalue('vote')
+                        if not vote:
+                            return response.wsgirespond(start_response, 500, {'message': 'Please specify a vote'})
+                        else:
+                            invalid = election.invalidate(issuedata, vote)
+                            if invalid:
+                                return response.wsgirespond(start_response, 500, {'message': invalid})
+                            else:
+                                votehash = election.vote(electionID, issueID, voterID, vote)
+                                voteuid = hashlib.sha224(voterID).hexdigest()
+                                # Catch proxy-emails
+                                m = re.match(r"^(.+@.*?[a-zA-Z])-.+$", email)
+                                if m:
+                                    email = m.group(1)
+                                voter.email(email, "Vote registered: %s (%s)" % (issueID, issuedata['title']), "This is a receipt that your vote was registered for issue #%s:\n\nElection: %s (%s)\nIssue: %s (%s)\nVote cryptohash: %s\nVote UID: %s" % (issueID, basedata['title'], electionID, issuedata['title'], issueID, votehash, voteuid))
+                                return response.wsgirespond(start_response, 200, {'message': 'Vote saved!'})
+                else:
+                    return response.wsgirespond(start_response, 404, {'message': 'Could not save vote: No such election or issue'})
+                        
+            except Exception as err:
+                return response.wsgirespond(start_response, 500, {'message': 'Could not save vote: %s' % err})
+                
+                
+        elif action == "request" and election:
+            email = form.getvalue('email')
+            if not email or len(email) > 300 or not re.match(r"([^@]+@[^@]+)", email):
+                return response.wsgirespond(start_response, 400, {'message': 'Could not request voter ID: Invalid email address specified'})
+            else:
+                try:
+                    basedata = election.getBasedata(electionID)
+                    if basedata:
+                        if 'closed' in basedata and basedata['closed'] == True:
+                            raise Exception("This election has closed")
+                        if 'open' in basedata and basedata['open'] == "true":
+                            uid, xhash = voter.add(electionID, basedata, email)
+                            voter.email(email, "Your voter link for %s" % basedata['title'], "Your personal vote link is: %s/election.html?%s/%s\nDo not share this link with anyone." % (config.get("general", "rooturl"), electionID, uid))
+                            return response.wsgirespond(start_response, 200, {'message': "Voter ID sent via email"})
+                        else:
+                            return response.wsgirespond(start_response, 403, {'message': "Could not request voter ID: This eleciton is closed for the public"})
+                    else:
+                        return response.wsgirespond(start_response, 404, {'message': 'Could not request voter ID: No such election'})
+                            
+                except Exception as err:
+                    return response.wsgirespond(start_response, 500, {'message': 'Could not create voter ID: %s' % err})
+        elif action == "peek" and election:
+            try:
+                basedata = election.getBasedata(electionID, hideHash=True)
+                if basedata:
+                    if 'closed' in basedata and basedata['closed'] == True:
+                            raise Exception("This election has closed")
+                    if 'open' in basedata and basedata['open'] == "true":
+                        return response.wsgirespond(start_response, 200, { 'base_data': basedata } )
+                    else:
+                        return response.wsgirespond(start_response, 403, {'message': 'This election is not open to the public'})
+                else:
+                    return response.wsgirespond(start_response, 404, {'message': 'Could not request data: No such election'})
+                        
+            except Exception as err:
+                return response.wsgirespond(start_response, 500, {'message': 'Could not load election data: %s' % err})
+        else:
+            return response.wsgirespond(start_response, 400, {'message': 'Invalid action supplied'})
+    else:
+        return response.wsgirespond(start_response, 500, {'message': 'No path info supplied, aborting'})
\ No newline at end of file