Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Updated georegistry to latest pylons-authentication

  • Loading branch information...
commit aaa1415b57eaf03f9e8cc50f33153edfead975de 1 parent 3744aa8
authored November 16, 2010
6  .gitignore
... ...
@@ -1,4 +1,4 @@
1  
-.development.cfg
2  
-.production.cfg
3  
-*.pyc
4 1
 data
  2
+production.ini
  3
+*.pyc
  4
+*.swp
13  default.cfg
... ...
@@ -1,13 +0,0 @@
1  
-[mail support]
2  
-smtp = localhost
3  
-email = support@localhost
4  
-nickname = Support
5  
-
6  
-[recaptcha]
7  
-public =
8  
-private = 
9  
-
10  
-[database]
11  
-name =
12  
-username =
13  
-password =
16  development.ini
... ...
@@ -1,5 +1,16 @@
  1
+#
  2
+# georegistry - Pylons development environment configuration
  3
+#
  4
+# The %(here)s variable will be replaced with the parent directory of this file
  5
+#
1 6
 [DEFAULT]
2 7
 debug = true
  8
+email_to =
  9
+error_email_from = support@example.com
  10
+smtp_server = localhost
  11
+# smtp_username = 
  12
+# smtp_password = 
  13
+# smtp_use_tls = True
3 14
 
4 15
 [server:main]
5 16
 use = egg:Paste#http
@@ -13,8 +24,9 @@ static_files = true
13 24
 cache_dir = %(here)s/data
14 25
 beaker.session.key = georegistry
15 26
 beaker.session.secret = somesecret
16  
-sqlalchemy.url = postgresql://${username}:${password}@localhost/${name}
17  
-safe_path = %(here)s/.development.cfg
  27
+sqlalchemy.url = sqlite:///%(here)s/development.db
  28
+# recaptcha.public =
  29
+# recaptcha.private =
18 30
 
19 31
 [loggers]
20 32
 keys = root, routes, georegistry, sqlalchemy
40  ez_setup.py
@@ -17,6 +17,7 @@
17 17
 DEFAULT_VERSION = "0.6c9"
18 18
 DEFAULT_URL     = "http://pypi.python.org/packages/%s/s/setuptools/" % sys.version[:3]
19 19
 
  20
+
20 21
 md5_data = {
21 22
     'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca',
22 23
     'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb',
@@ -54,10 +55,12 @@
54 55
     'setuptools-0.6c9-py2.6.egg': 'ca37b1ff16fa2ede6e19383e7b59245a',
55 56
 }
56 57
 
  58
+
57 59
 import sys, os
58 60
 try: from hashlib import md5
59 61
 except ImportError: from md5 import md5
60 62
 
  63
+
61 64
 def _validate_md5(egg_name, data):
62 65
     if egg_name in md5_data:
63 66
         digest = md5(data).hexdigest()
@@ -69,6 +72,7 @@ def _validate_md5(egg_name, data):
69 72
             sys.exit(2)
70 73
     return data
71 74
 
  75
+
72 76
 def use_setuptools(
73 77
     version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
74 78
     download_delay=15
@@ -110,6 +114,7 @@ def do_download():
110 114
     except pkg_resources.DistributionNotFound:
111 115
         return do_download()
112 116
 
  117
+
113 118
 def download_setuptools(
114 119
     version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,
115 120
     delay = 15
@@ -158,40 +163,6 @@ def download_setuptools(
158 163
     return os.path.realpath(saveto)
159 164
 
160 165
 
161  
-
162  
-
163  
-
164  
-
165  
-
166  
-
167  
-
168  
-
169  
-
170  
-
171  
-
172  
-
173  
-
174  
-
175  
-
176  
-
177  
-
178  
-
179  
-
180  
-
181  
-
182  
-
183  
-
184  
-
185  
-
186  
-
187  
-
188  
-
189  
-
190  
-
191  
-
192  
-
193  
-
194  
-
195 166
 def main(argv, version=DEFAULT_VERSION):
196 167
     """Install or upgrade setuptools and EasyInstall"""
197 168
     try:
@@ -233,6 +204,7 @@ def main(argv, version=DEFAULT_VERSION):
233 204
             print "Setuptools version",version,"or greater has been installed."
234 205
             print '(Run "ez_setup.py -U setuptools" to reinstall or upgrade.)'
235 206
 
  207
+
236 208
 def update_md5(filenames):
237 209
     """Update our built-in md5 registry"""
238 210
 
47  georegistry/config/deployment.ini_tmpl
... ...
@@ -0,0 +1,47 @@
  1
+#
  2
+# georegistry - Pylons configuration
  3
+#
  4
+# The %(here)s variable will be replaced with the parent directory of this file
  5
+#
  6
+[DEFAULT]
  7
+debug = false
  8
+email_to =
  9
+error_email_from = support@example.com
  10
+smtp_server = localhost
  11
+# smtp_username = 
  12
+# smtp_password = 
  13
+# smtp_use_tls = True
  14
+
  15
+[server:main]
  16
+use = egg:Paste#http
  17
+host = 0.0.0.0
  18
+port = 5000
  19
+
  20
+[app:main]
  21
+use = egg:georegistry
  22
+full_stack = true
  23
+static_files = true
  24
+cache_dir = %(here)s/data
  25
+app_instance_uuid = ${app_instance_uuid}
  26
+beaker.session.key = georegistry
  27
+beaker.session.secret = ${app_instance_secret}
  28
+sqlalchemy.url = sqlite:///production.db
  29
+# recaptcha.public =
  30
+# recaptcha.private =
  31
+
  32
+[loggers]
  33
+keys = root
  34
+[handlers]
  35
+keys = console
  36
+[formatters]
  37
+keys = generic
  38
+[logger_root]
  39
+level = WARN
  40
+handlers = console
  41
+[handler_console]
  42
+class = StreamHandler
  43
+args = (sys.stderr,)
  44
+level = NOTSET
  45
+formatter = generic
  46
+[formatter_generic]
  47
+format = %(asctime)s %(levelname)-5.5s [%(name)s] [%(threadName)s] %(message)s
31  georegistry/config/environment.py
@@ -5,10 +5,9 @@
5 5
 from mako.lookup import TemplateLookup
6 6
 # Import system modules
7 7
 import os
8  
-import ConfigParser
9 8
 from sqlalchemy import engine_from_config
10 9
 # Import custom modules
11  
-from georegistry.lib import app_globals, helpers, store
  10
+from georegistry.lib import app_globals, helpers
12 11
 from georegistry.config.routing import make_map
13 12
 from georegistry.model import init_model
14 13
 
@@ -38,36 +37,8 @@ def load_environment(global_conf, app_conf):
38 37
         module_directory=os.path.join(app_conf['cache_dir'], 'templates'),
39 38
         input_encoding='utf-8', default_filters=['escape'],
40 39
         imports=['from webhelpers.html import escape'])
41  
-    # Load safe
42  
-    config['safe'] = loadSafe(config['safe_path'])
43  
-    config['sqlalchemy.url'] = patchSQLAlchemyURL(config['sqlalchemy.url'], config['safe'])
44 40
     # Setup the SQLAlchemy database engine
45 41
     engine = engine_from_config(config, 'sqlalchemy.')
46 42
     init_model(engine)
47 43
     # Return
48 44
     return config
49  
-    
50  
-
51  
-def loadSafe(safePath):
52  
-    'Load information that we do not want to include in the repository'
53  
-    # Validate
54  
-    if not os.path.exists(safePath):
55  
-        print 'Missing configuration: ' + safePath
56  
-        safePath = store.expandBasePath('default.cfg')
57  
-    # Initialize
58  
-    valueByName = {}
59  
-    # Load
60  
-    configuration = ConfigParser.ConfigParser() 
61  
-    configuration.read(safePath)
62  
-    for sectionName in configuration.sections(): 
63  
-        valueByName[sectionName] = dict(configuration.items(sectionName)) 
64  
-    # Return
65  
-    return valueByName
66  
-
67  
-
68  
-def patchSQLAlchemyURL(sqlalchemyURL, safe):
69  
-    'Apply sensitive credentials'
70  
-    # Define
71  
-    getDBParameter = lambda x: safe['database'][x]
72  
-    # Return
73  
-    return sqlalchemyURL.replace('${username}', getDBParameter('username')).replace('${password}', getDBParameter('password')).replace('${name}', getDBParameter('name'))
3  georegistry/config/routing.py
@@ -2,6 +2,7 @@
2 2
 # Import pylons modules
3 3
 from routes import Mapper
4 4
 
  5
+
5 6
 def make_map(config):
6 7
     'Create, configure and return the routes mapper'
7 8
     # Initialize map
@@ -31,5 +32,7 @@ def make_map(config):
31 32
     map.connect('region_index', '/regions.:(responseFormat)', controller='regions', action='index')
32 33
     map.connect('region_show', '/regions/:(countryCode).:(responseFormat)', controller='regions', action='show')
33 34
     map.connect('region_show_plain', '/regions/:(countryCode)', controller='regions', action='show')
  35
+    # Redirect index
  36
+    map.redirect('/', '/regions')
34 37
     # Return
35 38
     return map
50  georegistry/controllers/__init__.py
... ...
@@ -0,0 +1,50 @@
  1
+'General decorators'
  2
+# Import pylons modules
  3
+from pylons import request, url
  4
+from pylons.controllers.util import redirect
  5
+# Import system modules
  6
+from decorator import decorator
  7
+# Import custom modules
  8
+from georegistry.lib import helpers as h
  9
+
  10
+
  11
+# Authentication
  12
+
  13
+@decorator
  14
+def requireLogin(func, *args, **kwargs):
  15
+    'Redirect to login if the user is not logged in'
  16
+    # If the user is not logged in,
  17
+    if not h.isPerson():
  18
+        return redirect(url('person_login', targetURL=h.encodeURL(request.path)))
  19
+    # Execute
  20
+    return func(*args, **kwargs)
  21
+
  22
+@decorator
  23
+def requireLoginJSON(func, *args, **kwargs):
  24
+    'Give error message if the user is not logged in'
  25
+    # If the user is not logged in,
  26
+    if not h.isPerson():
  27
+        return dict(isOk=0, message='Login required')
  28
+    # Execute
  29
+    return func(*args, **kwargs)
  30
+
  31
+
  32
+# Authorization
  33
+
  34
+@decorator
  35
+def requireSuper(func, *args, **kwargs):
  36
+    'Redirect to homepage if the user is not a superuser'
  37
+    # If the user is not a superuser,
  38
+    if not h.isPersonSuper():
  39
+        return redirect(url('person_login', targetURL=h.encodeURL('/')))
  40
+    # Execute
  41
+    return func(*args, **kwargs)
  42
+
  43
+@decorator
  44
+def requireSuperJSON(func, *args, **kwargs):
  45
+    'Give error message if the user is not a superuser'
  46
+    # If the user is not a superuser,
  47
+    if not h.isPersonSuper():
  48
+        return dict(isOk=0, message='Access denied')
  49
+    # Execute
  50
+    return func(*args, **kwargs)
164  georegistry/controllers/people.py
@@ -7,12 +7,13 @@
7 7
 # Import system modules
8 8
 import recaptcha.client.captcha as captcha
9 9
 import cStringIO as StringIO
  10
+import sqlalchemy as sa
10 11
 import datetime
11 12
 # Import custom modules
12 13
 from georegistry import model
13 14
 from georegistry.model import Session
14 15
 from georegistry.config import parameter
15  
-from georegistry.lib import smtp, store, helpers as h
  16
+from georegistry.lib import helpers as h, store, smtp
16 17
 from georegistry.lib.base import BaseController, render
17 18
 
18 19
 
@@ -32,7 +33,7 @@ def register(self):
32 33
     @jsonify
33 34
     def register_(self):
34 35
         'Store proposed changes and send confirmation email'
35  
-        return changeAccount(dict(request.POST), 'registration', '/people/confirm.mako')
  36
+        return changePerson(dict(request.POST), 'registration', '/people/confirm.mako')
36 37
 
37 38
     def confirm(self, ticket):
38 39
         'Confirm changes'
@@ -76,13 +77,13 @@ def update_(self):
76 77
         # Prepare
77 78
         person = Session.query(model.Person).get(personID)
78 79
         # Return
79  
-        return changeAccount(dict(request.POST), 'update', '/people/confirm.mako', person)
  80
+        return changePerson(dict(request.POST), 'update', '/people/confirm.mako', person)
80 81
 
81 82
     def login(self, targetURL=h.encodeURL('/')):
82 83
         'Show login form'
83 84
         c.messageCode = request.GET.get('messageCode')
84 85
         c.targetURL = h.decodeURL(targetURL)
85  
-        c.publicKey = config['safe']['recaptcha']['public']
  86
+        c.recaptchaPublicKey = config.get('recaptcha.public', '')
86 87
         return render('/people/login.mako')
87 88
 
88 89
     @jsonify
@@ -107,9 +108,9 @@ def login_(self):
107 108
             # Expect recaptcha response
108 109
             recaptchaChallenge = request.POST.get('recaptcha_challenge_field', '')
109 110
             recaptchaResponse = request.POST.get('recaptcha_response_field', '')
110  
-            recaptchaKey = config['safe']['recaptcha']['private']
  111
+            recaptchaPrivateKey = config.get('recaptcha.private', '')
111 112
             # Validate
112  
-            result = captcha.submit(recaptchaChallenge, recaptchaResponse, recaptchaKey, h.getRemoteIP())
  113
+            result = captcha.submit(recaptchaChallenge, recaptchaResponse, recaptchaPrivateKey, h.getRemoteIP())
113 114
             # If the response is not valid,
114 115
             if not result.is_valid:
115 116
                 return dict(isOk=0, rejection_count=person.rejection_count)
@@ -119,6 +120,7 @@ def login_(self):
119 120
         session['minutesOffset'] = minutesOffset
120 121
         session['personID'] = person.id
121 122
         session['nickname'] = person.nickname
  123
+        session['is_super'] = person.is_super
122 124
         session.save()
123 125
         # Save person
124 126
         person.minutes_offset = minutesOffset
@@ -134,6 +136,7 @@ def logout(self, targetURL=h.encodeURL('/')):
134 136
             del session['minutesOffset']
135 137
             del session['personID']
136 138
             del session['nickname']
  139
+            del session['is_super']
137 140
             session.save()
138 141
         # Redirect
139 142
         return redirect(url(h.decodeURL(targetURL)))
@@ -150,13 +153,70 @@ def reset(self):
150 153
             return dict(isOk=0)
151 154
         # Reset account
152 155
         c.password = store.makeRandomAlphaNumericString(parameter.PASSWORD_LENGTH_AVERAGE)
153  
-        return changeAccount(dict(
154  
-            username=person.username,
155  
-            password=c.password,
156  
-            nickname=person.nickname,
157  
-            email=person.email,
158  
-            email_sms=person.email_sms,
159  
-        ), 'reset', '/people/confirm.mako', person)
  156
+        return changePerson(dict(username=person.username, password=c.password, nickname=person.nickname, email=person.email, email_sms=person.email_sms), 'reset', '/people/confirm.mako', person)
  157
+
  158
+
  159
+# Helpers
  160
+
  161
+def changePerson(valueByName, action, templatePath, person=None):
  162
+    'Validate values and send confirmation email if values are okay'
  163
+    # Validate form
  164
+    try:
  165
+        form = PersonForm().to_python(valueByName, person)
  166
+    except formencode.Invalid, error:
  167
+        return dict(isOk=0, errorByID=error.unpack_errors())
  168
+    # Prepare candidate
  169
+    candidate = model.PersonCandidate(form['username'], model.hashString(form['password']), form['nickname'], form['email'], form['email_sms'])
  170
+    candidate.person_id = person.id if person else None
  171
+    candidate.ticket = store.makeRandomUniqueTicket(parameter.TICKET_LENGTH, Session.query(model.PersonCandidate))
  172
+    candidate.when_expired = datetime.datetime.utcnow() + datetime.timedelta(days=parameter.TICKET_LIFESPAN_IN_DAYS)
  173
+    Session.add(candidate) 
  174
+    Session.commit()
  175
+    # Send confirmation
  176
+    toByValue = dict(nickname=form['nickname'], email=form['email'])
  177
+    subject = '[%s] Confirm %s' % (parameter.SITE_NAME, action)
  178
+    c.candidate = candidate
  179
+    c.username = form['username']
  180
+    c.action = action
  181
+    body = render(templatePath)
  182
+    try:
  183
+        smtp.sendMessage(dict(email=config['error_email_from'], smtp=config['smtp_server'], username=config.get('smtp_username', ''), password=config.get('smtp_password', ''), nickname=parameter.SITE_NAME + ' Support'), toByValue, subject, body)
  184
+    except smtp.SMTPError:
  185
+        return dict(isOk=0, errorByID={'status': 'Unable to send confirmation; please try again later.'})
  186
+    # Return
  187
+    return dict(isOk=1)
  188
+
  189
+def confirmPersonCandidate(ticket):
  190
+    'Move changes from the PersonCandidate table into the Person table'
  191
+    # Initialize
  192
+    matchedCandidateFilter = model.PersonCandidate.ticket==ticket
  193
+    expiredCandidateFilter = model.PersonCandidate.when_expired < datetime.datetime.utcnow()
  194
+    candidate = Session.query(model.PersonCandidate).filter(matchedCandidateFilter & sa.not_(expiredCandidateFilter)).first()
  195
+    # If the ticket exists,
  196
+    if candidate:
  197
+        # Prepare
  198
+        similarCandidateFilter = (model.PersonCandidate.username == candidate.username) | (model.PersonCandidate.nickname == candidate.nickname) | (model.PersonCandidate.email == candidate.email)
  199
+        # Delete expired or similar candidates
  200
+        Session.query(model.PersonCandidate).filter(expiredCandidateFilter | similarCandidateFilter).delete()
  201
+        # If the person exists,
  202
+        if candidate.person_id:
  203
+            # Update
  204
+            person = Session.query(model.Person).get(candidate.person_id)
  205
+            person.username = candidate.username
  206
+            person.password_hash = candidate.password_hash
  207
+            person.nickname = candidate.nickname
  208
+            person.email = candidate.email
  209
+            person.email_sms = candidate.email_sms
  210
+            # Reset
  211
+            person.rejection_count = 0
  212
+        # If the person does not exist,
  213
+        else:
  214
+            # Add person
  215
+            Session.add(model.Person(candidate.username, candidate.password_hash, candidate.nickname, candidate.email, candidate.email_sms))
  216
+        # Commit
  217
+        Session.commit()
  218
+    # Return
  219
+    return candidate
160 220
 
161 221
 
162 222
 # Validators
@@ -181,7 +241,6 @@ def _to_python(self, value, person):
181 241
         # Return
182 242
         return value
183 243
 
184  
-
185 244
 class SecurePassword(formencode.validators.FancyValidator):
186 245
     'Validator to prevent weak passwords'
187 246
 
@@ -191,9 +250,8 @@ def _to_python(self, value, person):
191 250
             raise formencode.Invalid('That password needs more variety', value, person)
192 251
         return value
193 252
 
194  
-
195 253
 class PersonForm(formencode.Schema):
196  
-    'Validate user credentials'
  254
+    'Validate person credentials'
197 255
 
198 256
     username = formencode.All(
199 257
         formencode.validators.String(
@@ -221,76 +279,4 @@ class PersonForm(formencode.Schema):
221 279
         formencode.validators.Email(not_empty=True),
222 280
         Unique('email', 'That email is reserved for another account'),
223 281
     )
224  
-    email_sms = formencode.All(
225  
-        formencode.validators.Email(),
226  
-        Unique('email_sms', 'That SMS address is reserved for another account'),
227  
-    )
228  
-
229  
-
230  
-# Helpers
231  
-
232  
-def changeAccount(valueByName, action, templatePath, person=None):
233  
-    'Validate values and send confirmation email if values are okay'
234  
-    try:
235  
-        # Validate form
236  
-        form = PersonForm().to_python(valueByName, person)
237  
-    except formencode.Invalid, error:
238  
-        return dict(isOk=0, errorByID=error.unpack_errors())
239  
-    else:
240  
-        # Purge expired candidates
241  
-        purgeExpiredPersonCandidates()
242  
-        # Prepare candidate
243  
-        candidate = model.PersonCandidate(form['username'], model.hashString(form['password']), form['nickname'], form['email'], form['email_sms'])
244  
-        candidate.person_id = person.id if person else None
245  
-        candidate.ticket = store.makeRandomUniqueTicket(parameter.TICKET_LENGTH, Session.query(model.PersonCandidate))
246  
-        candidate.when_expired = datetime.datetime.utcnow() + datetime.timedelta(days=parameter.TICKET_LIFESPAN_IN_DAYS)
247  
-        Session.add(candidate) 
248  
-        Session.commit()
249  
-        # Prepare recipient
250  
-        toByValue = dict(nickname=form['nickname'], email=form['email'])
251  
-        # Prepare subject
252  
-        subject = '[%s] Confirm %s' % (parameter.SITE_NAME, action)
253  
-        # Prepare body
254  
-        c.candidate = candidate
255  
-        c.username = form['username']
256  
-        c.action = action
257  
-        body = render(templatePath)
258  
-        # Send
259  
-        try:
260  
-            smtp.sendMessage(config['safe']['mail support'], toByValue, subject, body)
261  
-        except smtp.SMTPError:
262  
-            return dict(isOk=0, errorByID={'status': 'Unable to send confirmation; please try again later.'})
263  
-        # Return
264  
-        return dict(isOk=1)
265  
-
266  
-def purgeExpiredPersonCandidates():
267  
-    'Delete candidates that have expired'
268  
-    Session.execute(model.person_candidates_table.delete().where(model.PersonCandidate.when_expired<datetime.datetime.utcnow()))
269  
-
270  
-def confirmPersonCandidate(ticket):
271  
-    'Move changes from the PersonCandidate table into the Person table'
272  
-    # Query
273  
-    candidate = Session.query(model.PersonCandidate).filter(model.PersonCandidate.ticket==ticket).filter(model.PersonCandidate.when_expired>=datetime.datetime.utcnow()).first()
274  
-    # If the ticket exists,
275  
-    if candidate:
276  
-        # If the person exists,
277  
-        if candidate.person_id:
278  
-            # Update person
279  
-            person = Session.query(model.Person).get(candidate.person_id)
280  
-            person.username = candidate.username
281  
-            person.password_hash = candidate.password_hash
282  
-            person.nickname = candidate.nickname
283  
-            person.email = candidate.email
284  
-            person.email_sms = candidate.email_sms
285  
-            # Reset rejection_count
286  
-            person.rejection_count = 0
287  
-        # If the person does not exist,
288  
-        else:
289  
-            # Add person
290  
-            Session.add(model.Person(candidate.username, candidate.password_hash, candidate.nickname, candidate.email, candidate.email_sms))
291  
-        # Delete ticket
292  
-        Session.delete(candidate)
293  
-        # Commit
294  
-        Session.commit()
295  
-    # Return
296  
-    return candidate
  282
+    email_sms = formencode.validators.Email()
6  georegistry/lib/base.py
... ...
@@ -1,13 +1,11 @@
1  
-"""The base Controller API
2  
-
3  
-Provides the BaseController class for subclassing.
4  
-"""
  1
+'Base Controller API'
5 2
 # Import pylons modules
6 3
 from pylons.controllers import WSGIController
7 4
 from pylons.templating import render_mako as render
8 5
 # Import custom modules
9 6
 from georegistry.model.meta import Session
10 7
 
  8
+
11 9
 class BaseController(WSGIController):
12 10
 
13 11
     def __call__(self, environ, start_response):
3  georegistry/lib/helpers.py
@@ -19,6 +19,9 @@ def decodeURL(x):
19 19
 def isPerson():
20 20
     return 1 if 'personID' in session else 0
21 21
 
  22
+def isPersonSuper():
  23
+    return 1 if session.get('is_super', False) else 0
  24
+
22 25
 def getPersonID():
23 26
     return session.get('personID', 0)
24 27
 
11  georegistry/lib/store.py
@@ -2,8 +2,6 @@
2 2
 # Import system modules
3 3
 import os
4 4
 import random
5  
-import cPickle as pickle
6  
-import cStringIO as StringIO
7 5
 
8 6
 
9 7
 # File
@@ -85,12 +83,3 @@ def reduceSets(packs, itemName):
85 83
         return set()
86 84
     items = [x[itemName] for x in packs]
87 85
     return reduce(lambda x, y: x.union(y), items)
88  
-
89  
-
90  
-# Pickle
91  
-
92  
-def setPickle(x):
93  
-    return pickle.dumps(x, protocol=2)
94  
-
95  
-def getPickle(pickled_x):
96  
-    return pickle.load(StringIO.StringIO(pickled_x))
2  georegistry/model/__init__.py
@@ -33,7 +33,7 @@ def hashString(string):
33 33
     sa.Column('email_sms', sa.String(parameter.EMAIL_LENGTH_MAXIMUM)),
34 34
     sa.Column('minutes_offset', sa.Integer, default=0),
35 35
     sa.Column('rejection_count', sa.Integer, default=0),
36  
-    sa.Column('pickled', sa.LargeBinary),
  36
+    sa.Column('is_super', sa.Boolean, default=False),
37 37
 )
38 38
 person_candidates_table = sa.Table('person_candidates', Base.metadata,
39 39
     sa.Column('id', sa.Integer, primary_key=True),
2  georegistry/templates/base.mako
@@ -20,8 +20,8 @@ $(document).ready(function() {
20 20
         function () {this.className = this.className.replace('OFF', 'ON');}, 
21 21
         function () {this.className = this.className.replace('ON', 'OFF');}
22 22
     );
23  
-    function getID(obj) {return /\d+/.exec(obj.id)[0]}
24 23
     function getNumber(x) {return /\d+/.exec(x)[0]}
  24
+    function getID(obj) {return getNumber(obj.id)}
25 25
     ${self.js()}\
26 26
 });
27 27
 </script>
1  georegistry/templates/people/change.mako
@@ -71,7 +71,6 @@ $('#username').focus();
71 71
 ${'Register for an account' if c.isNew else 'Update your account'}
72 72
 </%def>
73 73
 
74  
-
75 74
 <table>
76 75
     <tr>
77 76
         <td class=label><label for=username>Username</label></td>
2  georegistry/templates/people/confirm.mako
@@ -8,4 +8,4 @@ Password: ${c.password}
8 8
 Please click on the link below to complete your ${c.action}.
9 9
 ${request.relative_url(h.url('person_confirm', ticket=c.candidate.ticket), to_application=True)}
10 10
 
11  
-This ticket expires on ${c.candidate.when_expired.strftime('%A, %B %d, %Y at %H:%M%p')}.
  11
+This ticket expires on ${c.candidate.when_expired.strftime('%A, %B %d, %Y at %I:%M%p')}.
2  georegistry/templates/people/login.mako
@@ -47,7 +47,7 @@ function ajax_login() {
47 47
             rejection_count = data.rejection_count ? data.rejection_count : rejection_count + 1;
48 48
             // If there have been too many rejections,
49 49
             if (rejection_count >= ${h.REJECTION_LIMIT}) {
50  
-                Recaptcha.create("${c.publicKey}", 'recaptcha', {
  50
+                Recaptcha.create("${c.recaptchaPublicKey}", 'recaptcha', {
51 51
                     theme: 'red',
52 52
                     callback: Recaptcha.focus_response_field
53 53
                 });
12  georegistry/websetup.py
@@ -3,9 +3,11 @@
3 3
 import pylons.test
4 4
 # Import system modules
5 5
 import logging; log = logging.getLogger(__name__)
  6
+import getpass
6 7
 # Import custom modules
7  
-from georegistry.config.environment import load_environment
  8
+from georegistry import model
8 9
 from georegistry.model.meta import Session, Base
  10
+from georegistry.config.environment import load_environment
9 11
 
10 12
 
11 13
 def setup_app(command, conf, vars):
@@ -15,3 +17,11 @@ def setup_app(command, conf, vars):
15 17
         load_environment(conf.global_conf, conf.local_conf)
16 18
     # Create the tables if they don't already exist
17 19
     Base.metadata.create_all(bind=Session.bind)
  20
+    # If users do not exist,
  21
+    if not Session.query(model.Person).all():
  22
+        print 'Please create an administrator account.'
  23
+        # Create admin
  24
+        person = model.Person(raw_input('Username (admin): ') or 'admin', model.hashString(getpass.getpass('Password (admin): ') or 'admin'), raw_input('Nickname (Administrator): ') or u'Administrator', raw_input('Email (support@invisibleroads.com): ') or 'support@invisibleroads.com', raw_input('SMS: '))
  25
+        person.is_super = True
  26
+        Session.add(person)
  27
+        Session.commit()
53  production.ini
... ...
@@ -1,53 +0,0 @@
1  
-[DEFAULT]
2  
-debug = false
3  
-email_to = 
4  
-error_email_from = 
5  
-smtp_server = 
6  
-smtp_username = 
7  
-smtp_password = 
8  
-smtp_use_tls = 
9  
-
10  
-[server:main]
11  
-use = egg:Paste#http
12  
-host = 127.0.0.1
13  
-port = 5000
14  
-
15  
-[app:main]
16  
-use = egg:georegistry
17  
-full_stack = true
18  
-static_files = true
19  
-cache_dir = %(here)s/data
20  
-beaker.session.key = georegistry
21  
-beaker.session.secret = somesecret
22  
-sqlalchemy.url = postgresql://${username}:${password}@localhost/${name}
23  
-safe_path = %(here)s/.production.cfg
24  
-
25  
-[loggers]
26  
-keys = root, routes, georegistry, sqlalchemy
27  
-[handlers]
28  
-keys = console
29  
-[formatters]
30  
-keys = generic
31  
-[logger_root]
32  
-level = WARN
33  
-handlers = console
34  
-[logger_routes]
35  
-level = WARN
36  
-handlers =
37  
-qualname = routes.middleware
38  
-[logger_georegistry]
39  
-level = WARN
40  
-handlers =
41  
-qualname = georegistry
42  
-[logger_sqlalchemy]
43  
-level = WARN
44  
-handlers =
45  
-qualname = sqlalchemy.engine
46  
-[handler_console]
47  
-class = StreamHandler
48  
-args = (sys.stderr,)
49  
-level = NOTSET
50  
-formatter = generic
51  
-[formatter_generic]
52  
-format = %(asctime)s,%(msecs)03d %(levelname)-5.5s [%(name)s] [%(threadName)s] %(message)s
53  
-datefmt = %H:%M:%S
4  setup.cfg
... ...
@@ -1,7 +1,3 @@
1  
-[egg_info]
2  
-tag_build = dev
3  
-tag_svn_revision = true
4  
-
5 1
 [easy_install]
6 2
 find_links = http://www.pylonshq.com/download/
7 3
 

0 notes on commit aaa1415

Please sign in to comment.
Something went wrong with that request. Please try again.