def test_registration(self): "Make sure that registration works" # Initialize urlName = "person_register" # Make sure the registration page appears properly self.assert_("Registration" in self.app.get(url(urlName))) # Register self.app.post(url(urlName), dict(username=username, password=password, nickname=nickname, email=email)) # Register with the same username but with different case self.app.post( url(urlName), dict(username=username.upper(), password=password, nickname=nickname + "x", email=email + "x") ) # Register with the same nickname but with different case self.app.post( url(urlName), dict(username=username + "x", password=password, nickname=nickname.upper(), email=email + "x") ) # Register with the same email but with different case self.app.post( url(urlName), dict(username=username + "x", password=password, nickname=nickname + "x", email=email.upper()) ) # Confirm registration self.app.get( url("person_confirm", ticket=Session.query(model.PersonCandidate.ticket).filter_by(email=email).first()[0]) ) # Make sure the person exists self.assertEqual(Session.query(model.Person).filter_by(email=email).count(), 1) # Make sure that conflicting registrations have been deleted self.assertEqual( Session.query(model.PersonCandidate).filter_by(password_hash=model.hashString(password)).count(), 0 )
def run(shapePath): 'Load regions from shapefile' # Parse shapePath shapeName = store.extractFileBaseName(shapePath).decode('utf-8') proj4, shapelyGeometries, fieldPacks, fieldDefinitions = geometry_store.load(shapePath) # Initialize srid = getSRID(proj4) featureCount = 0 # Make tags tagTexts = [ shapeName, ] tags = model.getTags('\n'.join(tagTexts), addMissing=True) # For each geometry, for shapelyGeometry, fieldPack in itertools.izip(shapelyGeometries, fieldPacks): # Gather properties featureProperties = {} for fieldValue, (fieldName, fieldType) in itertools.izip(fieldPack, fieldDefinitions): if fieldType == osgeo.ogr.OFTString and fieldValue: fieldValue = fieldValue.decode('latin-1') featureProperties[fieldName] = fieldValue # Make feature feature = model.Feature() feature.owner_id = personID feature.geometry = geoalchemy.WKBSpatialElement(buffer(shapelyGeometry.wkb), srid) feature.scope = model.scopePublic feature.properties = featureProperties feature.tags = tags Session.add(feature) # Increment featureCount += 1 # Commit Session.commit() # Return return '%s: %s' % (shapeName, featureCount)
def test_login(self): """ Make sure that logging in works Ensure that the login page shows Ensure that bad credentials result in an error message Ensure that good credentials result in a proper redirect """ # Initialize urlName = 'person_login' exampleURL = url('person_update') # Assert that the login page shows and stores url self.assert_('Login' in self.app.get(url(urlName, url=exampleURL))) # Add person Session.add( model.Person(username, model.hashString(password), nickname, email)) Session.commit() # Log in using bad credentials self.assertEqualJSON( self.app.post(url(urlName), dict(username=username, password=password + 'x')), 0) # Log in using good credentials self.assertEqualJSON( self.app.post(url(urlName), dict(username=username, password=password)), 1)
def test_logout(self): """ Make sure that logging out works If the person is logged in, make sure the person gets logged out and is redirected properly. If the person is already logged out, return the user to the page before the user tried to log out. """ # Initialize urlName = 'person_logout' exampleURL = url('person_index') # Add person Session.add( model.Person(username, model.hashString(password), nickname, email)) Session.commit() # Logging out should redirect back self.assert_(exampleURL in self.app.get(url(urlName, url=exampleURL))) # Log in self.assert_( 'Login' in self.app.get(url('person_login', url=exampleURL))) self.assertEqualJSON( self.app.post(url('person_login'), dict(username=username, password=password)), 1) # Logging out should redirect back self.assert_(exampleURL in self.app.get(url(urlName, url=exampleURL)))
def setUp(self): 'Prepare database' # Prepare people people = [] personPacks = [ ('test_person1', model.hashString('test_person1'), u'test_person1', '*****@*****.**'), ('test_person2', model.hashString('test_person2'), u'test_person2', '*****@*****.**'), ] for personPack in personPacks: person = Session.query(model.Person).filter_by(username=personPack[0]).first() if not person: person = model.Person(*personPack) Session.add(person) people.append(person) Session.commit() self.person1Key, self.person2Key = [x.key for x in people] # Prepare features features = [] featurePacks = [ (people[0].id, geoalchemy.WKTSpatialElement('LINESTRING(3 4,10 50,20 25)')), (people[1].id, geoalchemy.WKTSpatialElement('POLYGON((1 1,5 1,5 5,1 5,1 1),(2 2,2 3,3 3,3 2,2 2))')), ] for featurePack in featurePacks: feature = model.Feature() feature.owner_id = featurePack[0] feature.geometry = featurePack[1] Session.add(feature) features.append(feature) Session.commit() self.feature1ID, self.feature2ID = [x.id for x in features]
def test_index(self): "Assert that the index page shows how many accounts are on file" # Initialize urlName = "person_index" # Make sure that we begin with 0 people self.assert_("0 people" in self.app.get(url(urlName))) # Add person Session.add(model.Person(username, model.hashString(password), nickname, email)) Session.commit() # Make sure that we now have 1 person self.assert_("1 people" in self.app.get(url(urlName)))
def test_index(self): 'Assert that the index page shows how many accounts are on file' # Initialize urlName = 'person_index' # Make sure that we begin with 0 people self.assert_('0 people' in self.app.get(url(urlName))) # Add person Session.add( model.Person(username, model.hashString(password), nickname, email)) Session.commit() # Make sure that we now have 1 person self.assert_('1 people' in self.app.get(url(urlName)))
def run(shapePath): 'Load regions from shapefile' # Parse shapePath shapeName = store.extractFileBaseName(shapePath) countryAlpha3, administrativeLevel = re.match(r'(.*)_adm(\d+)', shapeName).groups() countryAlpha3 = countryAlpha3.upper() administrativeLevel = int(administrativeLevel) # Load try: countryName = countryPackByAlpha3[countryAlpha3][0].decode('utf-8') except KeyError: return '%s: Unable to match country code' % shapeName proj4, shapelyGeometries, fieldPacks, fieldDefinitions = geometry_store.load(shapePath) # Initialize srid = getSRID(proj4) featureCount = 0 # Make tags tagTexts = [ countryName + (u' Administrative Level %s' % administrativeLevel if administrativeLevel > 0 else ''), ] tags = model.getTags('\n'.join(tagTexts), addMissing=True) # For each geometry, for shapelyGeometry, fieldPack in itertools.izip(shapelyGeometries, fieldPacks): # Gather properties featureProperties = {} for fieldValue, (fieldName, fieldType) in itertools.izip(fieldPack, fieldDefinitions): if fieldType == osgeo.ogr.OFTString and fieldValue: fieldValue = fieldValue.decode('latin-1') featureProperties[fieldName] = fieldValue if administrativeLevel > 0: featureName = featureProperties['NAME_%s' % administrativeLevel] else: featureName = featureProperties['NAME_ENGLI'] featureProperties['Name'] = featureName # Make feature feature = model.Feature() feature.owner_id = personID feature.geometry = geoalchemy.WKBSpatialElement(buffer(shapelyGeometry.wkb), srid) feature.scope = model.scopePublic feature.properties = featureProperties feature.tags = tags Session.add(feature) # Increment featureCount += 1 # Commit Session.commit() # Return return '%s: %s' % (shapeName, featureCount)
def setUp(self): 'Clear tables' # Logout self.app.get(url('person_logout')) # Delete all people Session.rollback() Session.query(model.Person).delete() Session.query(model.PersonCandidate).delete() Session.commit()
def setUp(self): "Clear tables" # Logout self.app.get(url("person_logout")) # Delete all people Session.rollback() Session.query(model.Person).delete() Session.query(model.PersonCandidate).delete() Session.commit()
def confirm(self, ticket): 'Confirm changes' # Send feedback candidate = confirmPersonCandidate(ticket) # If the candidate exists, if candidate: # Set messageCode = 'updated' if candidate.person_id else 'created' # Delete expired or similar candidates Session.execute(model.person_candidates_table.delete().where((model.PersonCandidate.when_expired < datetime.datetime.utcnow()) | (model.PersonCandidate.username == candidate.username) | (model.PersonCandidate.nickname == candidate.nickname) | (model.PersonCandidate.email == candidate.email))) Session.commit() # If the candidate does not exist, else: # Set messageCode = 'expired' # Return return redirect(url('person_login', url='/', messageCode=messageCode))
def test_registration(self): 'Make sure that registration works' # Initialize urlName = 'person_register' # Make sure the registration page appears properly self.assert_('Registration' in self.app.get(url(urlName))) # Register self.app.post( url(urlName), dict(username=username, password=password, nickname=nickname, email=email)) # Register with the same username but with different case self.app.post( url(urlName), dict(username=username.upper(), password=password, nickname=nickname + 'x', email=email + 'x')) # Register with the same nickname but with different case self.app.post( url(urlName), dict(username=username + 'x', password=password, nickname=nickname.upper(), email=email + 'x')) # Register with the same email but with different case self.app.post( url(urlName), dict(username=username + 'x', password=password, nickname=nickname + 'x', email=email.upper())) # Confirm registration self.app.get( url('person_confirm', ticket=Session.query(model.PersonCandidate.ticket).filter_by( email=email).first()[0])) # Make sure the person exists self.assertEqual( Session.query(model.Person).filter_by(email=email).count(), 1) # Make sure that conflicting registrations have been deleted self.assertEqual( Session.query(model.PersonCandidate).filter_by( password_hash=model.hashString(password)).count(), 0)
def test_reset(self): """ Make sure that resetting the password works Trying to reset an email that does not exist should return an error Make sure that resetting the password does not immediately change the password Make sure that reset confirmation works """ # Initialize urlName = 'person_reset' # Reset an unfamiliar email self.assertEqualJSON(self.app.post(url(urlName), dict(email=email)), 0) # Add person Session.add( model.Person(username, model.hashString(password), nickname, email)) Session.commit() # Reset password self.assertEqualJSON(self.app.post(url(urlName), dict(email=email)), 1) # Make sure the candidate exists self.assertEqual( Session.query( model.PersonCandidate).filter_by(email=email).count(), 1) # Activate candidate self.app.get( url('person_confirm', ticket=Session.query(model.PersonCandidate.ticket).filter_by( email=email).first()[0])) # Make sure the password has changed self.assertEqual( Session.query(model.Person).filter_by( password_hash=model.hashString(password)).count(), 0)
def login_(self): 'Process login credentials' # Check username username = str(request.POST.get('username', '')) person = Session.query( model.Person).filter_by(username=username).first() # If the username does not exist, if not person: return dict(isOk=0) # Check password password_hash = model.hashString(str(request.POST.get('password', ''))) # If the password is incorrect, if password_hash != StringIO.StringIO(person.password_hash).read(): # Increase and return rejection_count without a requery rejection_count = person.rejection_count = person.rejection_count + 1 Session.commit() return dict(isOk=0, rejection_count=rejection_count) # If there have been too many rejections, if person.rejection_count >= parameter.REJECTION_LIMIT: # Expect recaptcha response recaptchaChallenge = request.POST.get('recaptcha_challenge_field', '') recaptchaResponse = request.POST.get('recaptcha_response_field', '') recaptchaPrivateKey = config.get('recaptcha.private', '') # Validate result = captcha.submit(recaptchaChallenge, recaptchaResponse, recaptchaPrivateKey, h.getRemoteIP()) # If the response is not valid, if not result.is_valid: return dict(isOk=0, rejection_count=person.rejection_count) # Get minutesOffset from UTC minutesOffset = h.getMinutesOffset() # Save session session['minutesOffset'] = minutesOffset session['personID'] = person.id session['nickname'] = person.nickname session['is_super'] = person.is_super session.save() # Save person person.minutes_offset = minutesOffset person.rejection_count = 0 Session.commit() # Return return dict(isOk=1)
def test_login(self): """ Make sure that logging in works Ensure that the login page shows Ensure that bad credentials result in an error message Ensure that good credentials result in a proper redirect """ # Initialize urlName = "person_login" exampleURL = url("person_update") # Assert that the login page shows and stores url self.assert_("Login" in self.app.get(url(urlName, url=exampleURL))) # Add person Session.add(model.Person(username, model.hashString(password), nickname, email)) Session.commit() # Log in using bad credentials self.assertEqualJSON(self.app.post(url(urlName), dict(username=username, password=password + "x")), 0) # Log in using good credentials self.assertEqualJSON(self.app.post(url(urlName), dict(username=username, password=password)), 1)
def _to_python(self, value, person): 'Check whether the value is unique' # If the person is new or the value changed, if not person or getattr(person, self.fieldName) != value: # Make sure the value is unique if Session.query(model.Person).filter(getattr(model.Person, self.fieldName)==value).first(): # Raise raise formencode.Invalid(self.errorMessage, value, person) # Return return value
def _to_python(self, value, person): 'Check whether the value is unique' # If the person is new or the value changed, if not person or getattr(person, self.fieldName) != value: # Make sure the value is unique if Session.query(model.Person).filter( getattr(model.Person, self.fieldName) == value).first(): # Raise raise formencode.Invalid(self.errorMessage, value, person) # Return return value
def test_logout(self): """ Make sure that logging out works If the person is logged in, make sure the person gets logged out and is redirected properly. If the person is already logged out, return the user to the page before the user tried to log out. """ # Initialize urlName = "person_logout" exampleURL = url("person_index") # Add person Session.add(model.Person(username, model.hashString(password), nickname, email)) Session.commit() # Logging out should redirect back self.assert_(exampleURL in self.app.get(url(urlName, url=exampleURL))) # Log in self.assert_("Login" in self.app.get(url("person_login", url=exampleURL))) self.assertEqualJSON(self.app.post(url("person_login"), dict(username=username, password=password)), 1) # Logging out should redirect back self.assert_(exampleURL in self.app.get(url(urlName, url=exampleURL)))
def login_(self): 'Process login credentials' # Check username username = str(request.POST.get('username', '')) person = Session.query(model.Person).filter_by(username=username).first() # If the username does not exist, if not person: return dict(isOk=0) # Check password password_hash = model.hashString(str(request.POST.get('password', ''))) # If the password is incorrect, if password_hash != StringIO.StringIO(person.password_hash).read(): # Increase and return rejection_count without a requery rejection_count = person.rejection_count = person.rejection_count + 1 Session.commit() return dict(isOk=0, rejection_count=rejection_count) # If there have been too many rejections, if person.rejection_count >= parameter.REJECTION_LIMIT: # Expect recaptcha response recaptchaChallenge = request.POST.get('recaptcha_challenge_field', '') recaptchaResponse = request.POST.get('recaptcha_response_field', '') recaptchaPrivateKey = config.get('recaptcha.private', '') # Validate result = captcha.submit(recaptchaChallenge, recaptchaResponse, recaptchaPrivateKey, h.getRemoteIP()) # If the response is not valid, if not result.is_valid: return dict(isOk=0, rejection_count=person.rejection_count) # Get minutesOffset from UTC minutesOffset = h.getMinutesOffset() # Save session session['minutesOffset'] = minutesOffset session['personID'] = person.id session['nickname'] = person.nickname session['is_super'] = person.is_super session.save() # Save person person.minutes_offset = minutesOffset person.rejection_count = 0 Session.commit() # Return return dict(isOk=1)
def reset(self): 'Reset password' # Get email email = request.POST.get('email') # Try to load the person person = Session.query(model.Person).filter(model.Person.email==email).first() # If the email is not in our database, if not person: return dict(isOk=0) # Reset account c.password = store.makeRandomAlphaNumericString(parameter.PASSWORD_LENGTH_AVERAGE) return changePerson(dict(username=person.username, password=c.password, nickname=person.nickname, email=person.email), 'reset', person)
def isRegistrationAction(message): 'Return True if the message is trying to register an SMS address' # Get messageFromWhom = message.fromWhom.lower() try: personID = int(message.subject) except ValueError: return False # If personID == 0, then the sender is trying to unregister his or her phone if personID == 0: Session.query(model.SMSAddress).filter_by(email=messageFromWhom).delete() return True # Load person = Session.query(model.Person).options(orm.eagerload(model.Person.sms_addresses)).get(personID) # If the person doesn't exist or we have recorded the address already, if not person or messageFromWhom in (x.email.lower() for x in person.sms_addresses): return False # Add Session.add(model.SMSAddress(messageFromWhom, personID)) # Return return True
def run(): 'Check and send text messages' # Initialize registrationActionCount = 0 getX = lambda x: configuration.get('app:main', x) if x in configuration.options('app:main') else '' # Connect try: imapStore = imap.Store(getX('sms.imap_server'), getX('sms.imap_username'), getX('sms.imap_password')) except imap.IMAPError: return 'Unable to connect to IMAP server' # For each message, for message in imapStore.read(includes=['inbox']): # If the message is trying to register an SMS address, if isRegistrationAction(message): registrationActionCount += 1 # Mark message for deletion message.markDeleted() # Finalize imapStore.expunge() Session.commit() return 'Registration actions: %s' % registrationActionCount
def update_(self): 'Update account' # Initialize personID = h.getPersonID() # If the user is trying to update SMS information, if 'smsAddressID' in request.POST: # Load action = request.POST.get('action') smsAddressID = request.POST['smsAddressID'] smsAddress = Session.query(model.SMSAddress).filter((model.SMSAddress.id==smsAddressID) & (model.SMSAddress.owner_id==personID)).first() if not smsAddress: return dict(isOk=0, message='Could not find smsAddressID=%s corresponding to personID=%s' % (smsAddressID, personID)) # If the user is trying to activate an SMS address, elif action == 'activate': smsAddress.is_active = True # If the user is trying to deactivate an SMS address, elif action == 'deactivate': smsAddress.is_active = False # If the user is trying to remove an SMS address, elif action == 'remove': Session.delete(smsAddress) # Otherwise, else: return dict(isOk=0, message='Command not recognized') # Commit and return Session.commit() return dict(isOk=1) # If the user is trying to update account information, else: # Send update confirmation email return changePerson(dict(request.POST), 'update', Session.query(model.Person).get(personID))
def confirmPersonCandidate(ticket): 'Move changes from the PersonCandidate table into the Person table' # Load candidate = Session.query(model.PersonCandidate).filter( model.PersonCandidate.ticket == ticket).filter( model.PersonCandidate.when_expired >= datetime.datetime.utcnow() ).first() # If the ticket exists, if candidate: # If the person exists, if candidate.person_id: # Update person = Session.query(model.Person).get(candidate.person_id) person.username = candidate.username person.password_hash = candidate.password_hash person.nickname = candidate.nickname person.email = candidate.email # Reset person.rejection_count = 0 # If the person does not exist, else: # Add person Session.add( model.Person(candidate.username, candidate.password_hash, candidate.nickname, candidate.email)) # Commit Session.commit() # Return return candidate
def update(self): 'Show account update page' # Render person = Session.query(model.Person).options(orm.eagerload(model.Person.sms_addresses)).get(h.getPersonID()) c.isNew = False c.smsAddresses = person.sms_addresses # Return return formencode.htmlfill.render(render('/people/change.mako'), { 'username': person.username, 'nickname': person.nickname, 'email': person.email, 'key': person.key, })
def confirm(self, ticket): 'Confirm changes' # Send feedback candidate = confirmPersonCandidate(ticket) # If the candidate exists, if candidate: # Set messageCode = 'updated' if candidate.person_id else 'created' # Delete expired or similar candidates Session.execute(model.person_candidates_table.delete().where( (model.PersonCandidate.when_expired < datetime.datetime.utcnow()) | (model.PersonCandidate.username == candidate.username) | (model.PersonCandidate.nickname == candidate.nickname) | (model.PersonCandidate.email == candidate.email))) Session.commit() # If the candidate does not exist, else: # Set messageCode = 'expired' # Return return redirect(url('person_login', url='/', messageCode=messageCode))
def isRegistrationAction(message): 'Return True if the message is trying to register an SMS address' # Get messageFromWhom = message.fromWhom.lower() try: personID = int(message.subject) except ValueError: return False # If personID == 0, then the sender is trying to unregister his or her phone if personID == 0: Session.query( model.SMSAddress).filter_by(email=messageFromWhom).delete() return True # Load person = Session.query(model.Person).options( orm.eagerload(model.Person.sms_addresses)).get(personID) # If the person doesn't exist or we have recorded the address already, if not person or messageFromWhom in (x.email.lower() for x in person.sms_addresses): return False # Add Session.add(model.SMSAddress(messageFromWhom, personID)) # Return return True
def run(): 'Check and send text messages' # Initialize registrationActionCount = 0 getX = lambda x: configuration.get( 'app:main', x) if x in configuration.options('app:main') else '' # Connect try: imapStore = imap.Store(getX('sms.imap_server'), getX('sms.imap_username'), getX('sms.imap_password')) except imap.IMAPError: return 'Unable to connect to IMAP server' # For each message, for message in imapStore.read(includes=['inbox']): # If the message is trying to register an SMS address, if isRegistrationAction(message): registrationActionCount += 1 # Mark message for deletion message.markDeleted() # Finalize imapStore.expunge() Session.commit() return 'Registration actions: %s' % registrationActionCount
def update(self): 'Show account update page' # Render person = Session.query(model.Person).options( orm.eagerload(model.Person.sms_addresses)).get(h.getPersonID()) c.isNew = False c.smsAddresses = person.sms_addresses # Return return formencode.htmlfill.render( render('/people/change.mako'), { 'username': person.username, 'nickname': person.nickname, 'email': person.email, 'key': person.key, })
def index(self, responseFormat='html'): 'Get tags with visible features' # Get responseFormat responseFormat = responseFormat.lower() if responseFormat not in ['json', 'html']: abort(400, 'Must specify a valid responseFormat: json, html') # Authenticate via personID or key personID = h.getPersonIDViaKey() # Get tags with visible features c.tags = Session.query(model.Tag).join(model.Tag.features).filter(model.getFeatureFilter(personID)).all() # If the user wants json, if responseFormat == 'json': return '\n'.join(sorted(x.text for x in c.tags)) # If the user wants html, elif responseFormat == 'html': return render('/tags/index.mako')
def getSRID(proj4): 'Convert proj4 to srid' # Simplify proj4Simplified = simplifyProj4(proj4) if not proj4Simplified: raise model.GeoRegistryError('Must specify valid proj4 spatial reference') # For each spatial reference, for proj4Standard, srid in Session.execute('SELECT proj4text, srid FROM spatial_ref_sys'): # Skip empty proj4s if not proj4Standard.strip(): continue # If we have a match, if simplifyProj4(proj4Standard) == proj4Simplified: return srid # If we have no matches, raise exception raise model.GeoRegistryError('Could not recognize proj4 spatial reference')
def index(self, responseFormat='html'): 'Get tags with visible features' # Get responseFormat responseFormat = responseFormat.lower() if responseFormat not in ['json', 'html']: abort(400, 'Must specify a valid responseFormat: json, html') # Authenticate via personID or key personID = h.getPersonIDViaKey() # Get tags with visible features c.tags = Session.query(model.Tag).join(model.Tag.features).filter( model.getFeatureFilter(personID)).all() # If the user wants json, if responseFormat == 'json': return '\n'.join(sorted(x.text for x in c.tags)) # If the user wants html, elif responseFormat == 'html': return render('/tags/index.mako')
def reset(self): 'Reset password' # Get email email = request.POST.get('email') # Try to load the person person = Session.query( model.Person).filter(model.Person.email == email).first() # If the email is not in our database, if not person: return dict(isOk=0) # Reset account c.password = store.makeRandomAlphaNumericString( parameter.PASSWORD_LENGTH_AVERAGE) return changePerson( dict(username=person.username, password=c.password, nickname=person.nickname, email=person.email), 'reset', person)
def test_update(self): 'Make sure we can update features properly' # Initialize urlName = 'feature_update' p = { 'key': self.person1Key, 'srid': 4326, 'featureCollection': geojson.dumps(geojson.FeatureCollection([ geojson.Feature(geometry=geojson.Point((0, 0)), properties={ 'Population': 100, }), ])), 'tags': 'tag1', 'public': 0, } # Test print 'Expect error if we try to login without authentication' self.app.post(url(urlName), status=401) self.app.post(url(urlName), adjust(p, key=''), status=401) print 'Expect error if we submit invalid srid' self.app.post(url(urlName), adjust(p, srid=''), status=400) self.app.post(url(urlName), adjust(p, srid='xxx'), status=400) self.app.post(url(urlName), adjust(p, srid='-1'), status=400) print 'Expect error if we submit invalid featureCollection' self.app.post(url(urlName), adjust(p, featureCollection=''), status=400) self.app.post(url(urlName), adjust(p, featureCollection=geojson.dumps(geojson.FeatureCollection([]))), status=400) print 'Expect error if we submit invalid tags' self.app.post(url(urlName), adjust(p, tags=''), status=400) self.app.post(url(urlName), adjust(p, tags='x' * (parameter.TAG_LENGTH_MAXIMUM + 1)), status=400) print 'Expect error if we submit invalid public' self.app.post(url(urlName), adjust(p, public='xxx'), status=400) print 'Expect error if we try to specify an invalid featureID' self.app.post(url(urlName), adjust(p, featureCollection=geojson.dumps(geojson.FeatureCollection([geojson.Feature(id='xxx', geometry=geojson.Point((0, 0)))]))), status=400) print 'Expect error if we try to update features that do not exist' self.app.post(url(urlName), adjust(p, featureCollection=geojson.dumps(geojson.FeatureCollection([geojson.Feature(id=0, geometry=geojson.Point((0, 0)))]))), status=400) print 'Expect error if we try to update features that we do not own' self.app.post(url(urlName), adjust(p, featureCollection=geojson.dumps(geojson.FeatureCollection([geojson.Feature(id=self.feature2ID, geometry=geojson.Point((0, 0)))]))), status=400) print 'Expect error if we submit invalid geometry' self.app.post(url(urlName), adjust(p, featureCollection=geojson.dumps(geojson.FeatureCollection([geojson.Feature(geometry=None)]))), status=400) print 'Check that an add request works properly' featureID = self.app.post(url(urlName), p).body.splitlines()[0] print 'Check that an edit request works properly' self.app.post(url(urlName), adjust(p, featureCollection=geojson.dumps(geojson.FeatureCollection([geojson.Feature(id=featureID, geometry=geojson.Point((0, 0)), properties={'Name': u'Montréal'})])))) self.assertEqual(Session.query(model.Feature).get(featureID).properties['Name'], u'Montréal')
def setUp(self): 'Prepare database' # Prepare people people = [] personPacks = [ ('test_person1', model.hashString('test_person1'), u'test_person1', '*****@*****.**'), ('test_person2', model.hashString('test_person2'), u'test_person2', '*****@*****.**'), ] for personPack in personPacks: person = Session.query( model.Person).filter_by(username=personPack[0]).first() if not person: person = model.Person(*personPack) Session.add(person) people.append(person) Session.commit() self.person1Key, self.person2Key = [x.key for x in people] # Prepare features features = [] featurePacks = [ (people[0].id, geoalchemy.WKTSpatialElement('LINESTRING(3 4,10 50,20 25)')), (people[1].id, geoalchemy.WKTSpatialElement( 'POLYGON((1 1,5 1,5 5,1 5,1 1),(2 2,2 3,3 3,3 2,2 2))')), ] for featurePack in featurePacks: feature = model.Feature() feature.owner_id = featurePack[0] feature.geometry = featurePack[1] Session.add(feature) features.append(feature) Session.commit() self.feature1ID, self.feature2ID = [x.id for x in features]
def test_delete(self): 'Make sure we can delete features properly' # Initialize urlName = 'feature_delete' p = { 'key': self.person1Key, 'featureIDs': str(self.feature1ID), } # Test print 'Expect error if we try to login without authentication' self.app.delete(url(urlName), status=401) self.app.delete(url(urlName, **adjust(p, key='')), status=401) print 'Expect error if we try to delete features that do not exist' self.app.delete(url(urlName, **adjust(p, featureIDs=str(0))), status=400) print 'Expect error if we try to delete features that we do not own' self.app.delete(url(urlName, **adjust(p, featureIDs=str(self.feature2ID))), status=400) print 'Check that a delete request works properly' self.app.delete(url(urlName, **p)) self.assertEqual(Session.query(model.Feature).get(self.feature1ID), None)
def test_delete(self): 'Make sure we can delete features properly' # Initialize urlName = 'feature_delete' p = { 'key': self.person1Key, 'featureIDs': str(self.feature1ID), } # Test print 'Expect error if we try to login without authentication' self.app.delete(url(urlName), status=401) self.app.delete(url(urlName, **adjust(p, key='')), status=401) print 'Expect error if we try to delete features that do not exist' self.app.delete(url(urlName, **adjust(p, featureIDs=str(0))), status=400) print 'Expect error if we try to delete features that we do not own' self.app.delete(url(urlName, **adjust(p, featureIDs=str(self.feature2ID))), status=400) print 'Check that a delete request works properly' self.app.delete(url(urlName, **p)) self.assertEqual( Session.query(model.Feature).get(self.feature1ID), None)
def test_reset(self): """ Make sure that resetting the password works Trying to reset an email that does not exist should return an error Make sure that resetting the password does not immediately change the password Make sure that reset confirmation works """ # Initialize urlName = "person_reset" # Reset an unfamiliar email self.assertEqualJSON(self.app.post(url(urlName), dict(email=email)), 0) # Add person Session.add(model.Person(username, model.hashString(password), nickname, email)) Session.commit() # Reset password self.assertEqualJSON(self.app.post(url(urlName), dict(email=email)), 1) # Make sure the candidate exists self.assertEqual(Session.query(model.PersonCandidate).filter_by(email=email).count(), 1) # Activate candidate self.app.get( url("person_confirm", ticket=Session.query(model.PersonCandidate.ticket).filter_by(email=email).first()[0]) ) # Make sure the password has changed self.assertEqual(Session.query(model.Person).filter_by(password_hash=model.hashString(password)).count(), 0)
def update_(self): 'Update account' # Initialize personID = h.getPersonID() # If the user is trying to update SMS information, if 'smsAddressID' in request.POST: # Load action = request.POST.get('action') smsAddressID = request.POST['smsAddressID'] smsAddress = Session.query(model.SMSAddress).filter( (model.SMSAddress.id == smsAddressID) & (model.SMSAddress.owner_id == personID)).first() if not smsAddress: return dict( isOk=0, message= 'Could not find smsAddressID=%s corresponding to personID=%s' % (smsAddressID, personID)) # If the user is trying to activate an SMS address, elif action == 'activate': smsAddress.is_active = True # If the user is trying to deactivate an SMS address, elif action == 'deactivate': smsAddress.is_active = False # If the user is trying to remove an SMS address, elif action == 'remove': Session.delete(smsAddress) # Otherwise, else: return dict(isOk=0, message='Command not recognized') # Commit and return Session.commit() return dict(isOk=1) # If the user is trying to update account information, else: # Send update confirmation email return changePerson(dict(request.POST), 'update', Session.query(model.Person).get(personID))
def confirmPersonCandidate(ticket): 'Move changes from the PersonCandidate table into the Person table' # Load candidate = Session.query(model.PersonCandidate).filter(model.PersonCandidate.ticket==ticket).filter(model.PersonCandidate.when_expired>=datetime.datetime.utcnow()).first() # If the ticket exists, if candidate: # If the person exists, if candidate.person_id: # Update person = Session.query(model.Person).get(candidate.person_id) person.username = candidate.username person.password_hash = candidate.password_hash person.nickname = candidate.nickname person.email = candidate.email # Reset person.rejection_count = 0 # If the person does not exist, else: # Add person Session.add(model.Person(candidate.username, candidate.password_hash, candidate.nickname, candidate.email)) # Commit Session.commit() # Return return candidate
personID = h.getPersonIDViaKey() # Load srid srid = request.params.get('srid', '') try: proj4 = model.validateSRID(srid) except model.GeoRegistryError, error: abort(400, str(error)) # Load tags try: tags = model.getTags(request.params.get('tags', '')) except model.GeoRegistryError, error: abort(400, str(error)) # Load query string queryStringHash = model.hashString(request.query_string) # Load cached map cachedMap = Session.query( model.Map).filter_by(query_hash=queryStringHash).first() # If we do not have a cached map or the cached map is not current, if not cachedMap or not cachedMap.when_updated or cachedMap.when_updated < max( x.when_updated for x in tags): # Load bboxFormat bboxFormat = request.params.get('bboxFormat', 'yxyx') if bboxFormat not in ['yxyx', 'xyxy']: abort(400, 'Must specify a valid bboxFormat: yxyx, xyxy') # Load bounding box bbox = request.params.get('bbox', '') # If a bounding box is specified, if bbox: # Expand try: terms = [float(x) for x in bbox.split(',')] if bboxFormat == 'yxyx':
def test_update(self): 'Make sure we can update features properly' # Initialize urlName = 'feature_update' p = { 'key': self.person1Key, 'srid': 4326, 'featureCollection': geojson.dumps( geojson.FeatureCollection([ geojson.Feature(geometry=geojson.Point((0, 0)), properties={ 'Population': 100, }), ])), 'tags': 'tag1', 'public': 0, } # Test print 'Expect error if we try to login without authentication' self.app.post(url(urlName), status=401) self.app.post(url(urlName), adjust(p, key=''), status=401) print 'Expect error if we submit invalid srid' self.app.post(url(urlName), adjust(p, srid=''), status=400) self.app.post(url(urlName), adjust(p, srid='xxx'), status=400) self.app.post(url(urlName), adjust(p, srid='-1'), status=400) print 'Expect error if we submit invalid featureCollection' self.app.post(url(urlName), adjust(p, featureCollection=''), status=400) self.app.post(url(urlName), adjust(p, featureCollection=geojson.dumps( geojson.FeatureCollection([]))), status=400) print 'Expect error if we submit invalid tags' self.app.post(url(urlName), adjust(p, tags=''), status=400) self.app.post(url(urlName), adjust(p, tags='x' * (parameter.TAG_LENGTH_MAXIMUM + 1)), status=400) print 'Expect error if we submit invalid public' self.app.post(url(urlName), adjust(p, public='xxx'), status=400) print 'Expect error if we try to specify an invalid featureID' self.app.post(url(urlName), adjust(p, featureCollection=geojson.dumps( geojson.FeatureCollection([ geojson.Feature(id='xxx', geometry=geojson.Point( (0, 0))) ]))), status=400) print 'Expect error if we try to update features that do not exist' self.app.post(url(urlName), adjust(p, featureCollection=geojson.dumps( geojson.FeatureCollection([ geojson.Feature(id=0, geometry=geojson.Point( (0, 0))) ]))), status=400) print 'Expect error if we try to update features that we do not own' self.app.post(url(urlName), adjust(p, featureCollection=geojson.dumps( geojson.FeatureCollection([ geojson.Feature(id=self.feature2ID, geometry=geojson.Point( (0, 0))) ]))), status=400) print 'Expect error if we submit invalid geometry' self.app.post(url(urlName), adjust(p, featureCollection=geojson.dumps( geojson.FeatureCollection( [geojson.Feature(geometry=None)]))), status=400) print 'Check that an add request works properly' featureID = self.app.post(url(urlName), p).body.splitlines()[0] print 'Check that an edit request works properly' self.app.post( url(urlName), adjust(p, featureCollection=geojson.dumps( geojson.FeatureCollection([ geojson.Feature(id=featureID, geometry=geojson.Point((0, 0)), properties={'Name': u'Montréal'}) ])))) self.assertEqual( Session.query(model.Feature).get(featureID).properties['Name'], u'Montréal')
def index(self): 'Show information about people registered in the database' c.people = Session.query(model.Person).all() return render('/people/index.mako')
def index(self): 'Show information about people registered in the database' c.people = Session.query(model.Person).all() return render('/people/index.mako')
def tearDown(self): Session.execute(model.feature_tags_table.delete()) Session.execute(model.features_table.delete()) Session.execute(model.tags_table.delete()) Session.commit()
def setUp(self): 'Prepare database' # Prepare people people = [] personPacks = [ ('test_person1', model.hashString('test_person1'), u'test_person1', '*****@*****.**'), ('test_person2', model.hashString('test_person2'), u'test_person2', '*****@*****.**'), ] for personPack in personPacks: person = Session.query(model.Person).filter_by(username=personPack[0]).first() if not person: person = model.Person(*personPack) Session.add(person) people.append(person) Session.commit() self.person1Key, self.person2Key = [x.key for x in people] # Prepare tags tags = [] self.tagTexts = [ u'tag with features that are public', u'tag with features that are private to person1', u'tag with features that are private to person2', ] for tagText in self.tagTexts: tag = Session.query(model.Tag).filter_by(text=tagText).first() if not tag: tag = model.Tag(tagText) Session.add(tag) tags.append(tag) Session.commit() tag1Public, tag1Private, tag2Private = tags # Prepare features features = [] featurePacks = [ (people[0].id, geoalchemy.WKTSpatialElement('MULTIPOINT (-90.2307590000000062 15.7834710000000005, 126.9779692000000040 37.5665350000000018, -0.1963060000000000 5.5557169999999996, -91.5219589999999954 14.8361560000000008)'), model.scopePublic, {'description': 'Santa Eulalia; Seoul; Accra; Xela'}), (people[0].id, geoalchemy.WKTSpatialElement('LINESTRING (-87.6297981999999962 41.8781135999999989, -84.3879823999999985 33.7489953999999983, -122.4194154999999995 37.7749294999999989)'), model.scopePrivate, {'description': 'Chicago; Atlanta; San Francisco'}), (people[1].id, geoalchemy.WKTSpatialElement('LINESTRING (-74.0059731 40.7143528, -90.5352778 14.6133333)'), model.scopePrivate, {'passenger': u'Hélène'}), ] for featurePack in featurePacks: feature = model.Feature() feature.owner_id, feature.geometry, feature.scope, feature.properties = featurePack Session.add(feature) features.append(feature) feature1Public, feature1Private, feature2Private = features feature1Public.tags = [tag1Public] feature1Private.tags = [tag1Private] feature2Private.tags = [tag2Private] Session.commit() self.feature1ID = feature1Public.id
def tearDown(self): Session.execute(model.feature_tags_table.delete()) Session.execute(model.features_table.delete()) Session.execute(model.tags_table.delete()) Session.commit()
def setUp(self): 'Prepare database' # Prepare people people = [] personPacks = [ ('test_person1', model.hashString('test_person1'), u'test_person1', '*****@*****.**'), ('test_person2', model.hashString('test_person2'), u'test_person2', '*****@*****.**'), ] for personPack in personPacks: person = Session.query( model.Person).filter_by(username=personPack[0]).first() if not person: person = model.Person(*personPack) Session.add(person) people.append(person) Session.commit() self.person1Key, self.person2Key = [x.key for x in people] # Prepare tags tags = [] self.tagTexts = [ u'tag with features that are public', u'tag with features that are private to person1', u'tag with features that are private to person2', ] for tagText in self.tagTexts: tag = Session.query(model.Tag).filter_by(text=tagText).first() if not tag: tag = model.Tag(tagText) Session.add(tag) tags.append(tag) Session.commit() tag1Public, tag1Private, tag2Private = tags # Prepare features features = [] featurePacks = [ (people[0].id, geoalchemy.WKTSpatialElement( 'MULTIPOINT (-90.2307590000000062 15.7834710000000005, 126.9779692000000040 37.5665350000000018, -0.1963060000000000 5.5557169999999996, -91.5219589999999954 14.8361560000000008)' ), model.scopePublic, { 'description': 'Santa Eulalia; Seoul; Accra; Xela' }), (people[0].id, geoalchemy.WKTSpatialElement( 'LINESTRING (-87.6297981999999962 41.8781135999999989, -84.3879823999999985 33.7489953999999983, -122.4194154999999995 37.7749294999999989)' ), model.scopePrivate, { 'description': 'Chicago; Atlanta; San Francisco' }), (people[1].id, geoalchemy.WKTSpatialElement( 'LINESTRING (-74.0059731 40.7143528, -90.5352778 14.6133333)' ), model.scopePrivate, { 'passenger': u'Hélène' }), ] for featurePack in featurePacks: feature = model.Feature() feature.owner_id, feature.geometry, feature.scope, feature.properties = featurePack Session.add(feature) features.append(feature) feature1Public, feature1Private, feature2Private = features feature1Public.tags = [tag1Public] feature1Private.tags = [tag1Private] feature2Private.tags = [tag2Private] Session.commit() self.feature1ID = feature1Public.id
except (KeyError, TypeError), error: abort(400, 'Could not parse geometry=%s' % featureGeometry) # If featureID is specified, load it if featureID is not None: try: featureID = int(featureID) except ValueError: abort( 400, 'Could not parse featureID=%s as an integer' % featureID) feature = featureByID[featureID] # If featureID is not specified, add it else: feature = model.Feature() feature.owner_id = personID Session.add(feature) # Set feature.properties = featureProperties feature.scope = model.scopePublic if public else model.scopePrivate feature.geometry = geoalchemy.WKTSpatialElement( featureGeometryWKT, srid) feature.tags = tags # Append features.append(feature) # Update timestamps for each tag for tag in tags: tag.updateTimestamp() # Commit Session.commit() # Return return '\n'.join(str(x.id) for x in features)
def setUp(self): 'Prepare database' # Prepare people people = [] personPacks = [ ('test_person1', model.hashString('test_person1'), u'test_person1', '*****@*****.**'), ('test_person2', model.hashString('test_person2'), u'test_person2', '*****@*****.**'), ] for personPack in personPacks: person = Session.query(model.Person).filter_by(username=personPack[0]).first() if not person: person = model.Person(*personPack) Session.add(person) people.append(person) Session.commit() self.person1Key, self.person2Key = [x.key for x in people] # Prepare tags tags = [] self.tagTexts = [ u'tag with features that are public', u'tag with features that are private to person1', u'tag with features that are private to person2', ] for tagText in self.tagTexts: tag = Session.query(model.Tag).filter_by(text=tagText).first() if not tag: tag = model.Tag(tagText) Session.add(tag) tags.append(tag) Session.commit() tag1Public, tag1Private, tag2Private = tags # Prepare features features = [] featurePacks = [ (people[0].id, geoalchemy.WKTSpatialElement('POINT(6 10)'), model.scopePublic), (people[0].id, geoalchemy.WKTSpatialElement('LINESTRING(3 4,10 50,20 25)'), model.scopePrivate), (people[1].id, geoalchemy.WKTSpatialElement('POLYGON((1 1,5 1,5 5,1 5,1 1),(2 2,2 3,3 3,3 2,2 2))'), model.scopePrivate), ] for featurePack in featurePacks: feature = model.Feature() feature.owner_id, feature.geometry, feature.scope = featurePack Session.add(feature) features.append(feature) feature1Public, feature1Private, feature2Private = features feature1Public.tags = [tag1Public] feature1Private.tags = [tag1Private] feature2Private.tags = [tag2Private] Session.commit()
def getCacheTimestamps(): return [ x[0] for x in Session.query(model.Map.when_updated).order_by( model.Map.when_updated) ]
return changePerson(dict(username=person.username, password=c.password, nickname=person.nickname, email=person.email), 'reset', person) # Helpers def changePerson(valueByName, action, person=None): 'Validate values and send confirmation email if values are okay' # Validate form try: form = PersonForm().to_python(valueByName, person) except formencode.Invalid, error: return dict(isOk=0, errorByID=error.unpack_errors()) # Prepare candidate candidate = model.PersonCandidate(form['username'], model.hashString(form['password']), form['nickname'], form['email']) candidate.person_id = person.id if person else None candidate.ticket = store.makeRandomUniqueTicket(parameter.TICKET_LENGTH, Session.query(model.PersonCandidate)) candidate.when_expired = datetime.datetime.utcnow() + datetime.timedelta(days=parameter.TICKET_LIFESPAN_IN_DAYS) Session.add(candidate) Session.commit() # Send confirmation toByValue = dict(nickname=form['nickname'], email=form['email']) subject = '[%s] Confirm %s' % (parameter.SITE_NAME, action) c.candidate = candidate c.username = form['username'] c.action = action body = render('/people/confirm.mako') try: 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) except smtp.SMTPError: return dict(isOk=0, errorByID={'status': 'Unable to send confirmation; please try again later.'}) # Return
for proj4Standard, srid in Session.execute('SELECT proj4text, srid FROM spatial_ref_sys'): # Skip empty proj4s if not proj4Standard.strip(): continue # If we have a match, if simplifyProj4(proj4Standard) == proj4Simplified: return srid # If we have no matches, raise exception raise model.GeoRegistryError('Could not recognize proj4 spatial reference') # If we are running standalone, if __name__ == '__main__': # Parse optionParser = script_process.buildOptionParser() options, arguments = optionParser.parse_args() # Load countryPackByAlpha3 countryPackByAlpha3 = {} countryPath = store.expandBasePath('utilities/countries.csv') for countryName, countryAlpha2, countryAlpha3 in csv.reader(open(countryPath, 'rt')): countryPackByAlpha3[countryAlpha3.upper()] = countryName, countryAlpha2.upper() # Initialize script_process.initialize(options) person = Session.query(model.Person).filter_by(username='******').first() personID = person.id folderPath = arguments[0] if arguments else '' # For each filePath, for filePath in sorted(glob.glob(os.path.join(folderPath, '*.shp'))): # Run print run(filePath)
personID = h.getPersonIDViaKey() # Load srid srid = request.params.get('srid', '') try: proj4 = model.validateSRID(srid) except model.GeoRegistryError, error: abort(400, str(error)) # Load tags try: tags = model.getTags(request.params.get('tags', '')) except model.GeoRegistryError, error: abort(400, str(error)) # Load query string queryStringHash = model.hashString(request.query_string) # Load cached map cachedMap = Session.query(model.Map).filter_by(query_hash=queryStringHash).first() # If we do not have a cached map or the cached map is not current, if not cachedMap or not cachedMap.when_updated or cachedMap.when_updated < max(x.when_updated for x in tags): # Load bboxFormat bboxFormat = request.params.get('bboxFormat', 'yxyx') if bboxFormat not in ['yxyx', 'xyxy']: abort(400, 'Must specify a valid bboxFormat: yxyx, xyxy') # Load bounding box bbox = request.params.get('bbox', '') # If a bounding box is specified, if bbox: # Expand try: terms = [float(x) for x in bbox.split(',')] if bboxFormat == 'yxyx': minY, minX, maxY, maxX = terms
def getCacheTimestamps(): return [x[0] for x in Session.query(model.Map.when_updated).order_by(model.Map.when_updated)]
def changePerson(valueByName, action, person=None): 'Validate values and send confirmation email if values are okay' # Validate form try: form = PersonForm().to_python(valueByName, person) except formencode.Invalid, error: return dict(isOk=0, errorByID=error.unpack_errors()) # Prepare candidate candidate = model.PersonCandidate(form['username'], model.hashString(form['password']), form['nickname'], form['email']) candidate.person_id = person.id if person else None candidate.ticket = store.makeRandomUniqueTicket( parameter.TICKET_LENGTH, Session.query(model.PersonCandidate)) candidate.when_expired = datetime.datetime.utcnow() + datetime.timedelta( days=parameter.TICKET_LIFESPAN_IN_DAYS) Session.add(candidate) Session.commit() # Send confirmation toByValue = dict(nickname=form['nickname'], email=form['email']) subject = '[%s] Confirm %s' % (parameter.SITE_NAME, action) c.candidate = candidate c.username = form['username'] c.action = action body = render('/people/confirm.mako') try: smtp.sendMessage( dict(email=config['error_email_from'], smtp=config['smtp_server'],