Merge lp:~soren/surveilr/auth into lp:surveilr

Proposed by Soren Hansen
Status: Merged
Approved by: Soren Hansen
Approved revision: 21
Merged at revision: 21
Proposed branch: lp:~soren/surveilr/auth
Merge into: lp:surveilr
Diff against target: 643 lines (+387/-22)
15 files modified
surveilr/api/__init__.py (+19/-0)
surveilr/api/server/__init__.py (+21/-0)
surveilr/api/server/app.py (+42/-10)
surveilr/api/server/auth.py (+48/-0)
surveilr/api/server/factory.py (+29/-0)
surveilr/defaults.cfg (+12/-3)
surveilr/models.py (+6/-0)
surveilr/tests/api/server/__init__.py (+19/-0)
surveilr/tests/api/server/test_app.py (+30/-9)
surveilr/tests/api/server/test_auth.py (+82/-0)
surveilr/tests/api/server/test_factory.py (+43/-0)
surveilr/tests/test_utils.py (+6/-0)
surveilr/utils.py (+6/-0)
surveilr/who.ini (+23/-0)
tools/pip-requirements.txt (+1/-0)
To merge this branch: bzr merge lp:~soren/surveilr/auth
Reviewer Review Type Date Requested Status
Soren Hansen Pending
Review via email: mp+87544@code.launchpad.net

Commit message

Add authentication

Use repoze.who to provide a simple authentication system.

To post a comment you must log in.
lp:~soren/surveilr/auth updated
21. By Soren Hansen

Add authentication

Use repoze.who to provide a simple authentication system.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'surveilr/api/__init__.py'
--- surveilr/api/__init__.py 2011-11-19 22:01:55 +0000
+++ surveilr/api/__init__.py 2012-01-04 23:13:32 +0000
@@ -0,0 +1,19 @@
1"""
2 Surveilr - Log aggregation, analysis and visualisation
3
4 Copyright (C) 2011 Linux2Go
5
6 This program is free software: you can redistribute it and/or
7 modify it under the terms of the GNU Affero General Public License
8 as published by the Free Software Foundation, either version 3 of
9 the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Affero General Public License for more details.
15
16 You should have received a copy of the GNU Affero General Public
17 License along with this program. If not, see
18 <http://www.gnu.org/licenses/>.
19"""
020
=== added directory 'surveilr/api/server'
=== added file 'surveilr/api/server/__init__.py'
--- surveilr/api/server/__init__.py 1970-01-01 00:00:00 +0000
+++ surveilr/api/server/__init__.py 2012-01-04 23:13:32 +0000
@@ -0,0 +1,21 @@
1"""
2 Surveilr - Log aggregation, analysis and visualisation
3
4 Copyright (C) 2011 Linux2Go
5
6 This program is free software: you can redistribute it and/or
7 modify it under the terms of the GNU Affero General Public License
8 as published by the Free Software Foundation, either version 3 of
9 the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Affero General Public License for more details.
15
16 You should have received a copy of the GNU Affero General Public
17 License along with this program. If not, see
18 <http://www.gnu.org/licenses/>.
19
20 Log collection server implementation
21"""
022
=== renamed file 'surveilr/api/server.py' => 'surveilr/api/server/app.py'
--- surveilr/api/server.py 2011-12-18 14:46:48 +0000
+++ surveilr/api/server/app.py 2012-01-04 23:13:32 +0000
@@ -18,11 +18,12 @@
18 License along with this program. If not, see18 License along with this program. If not, see
19 <http://www.gnu.org/licenses/>.19 <http://www.gnu.org/licenses/>.
2020
21 Log collection server implementation21 API server implementation
22"""22"""
2323
24import eventlet24import eventlet
25import eventlet.wsgi25import eventlet.wsgi
26import functools
26import json27import json
27import time28import time
2829
@@ -34,12 +35,29 @@
34from webob import Response35from webob import Response
35from webob.dec import wsgify36from webob.dec import wsgify
36from webob.exc import HTTPNotFound37from webob.exc import HTTPNotFound
38from webob.exc import HTTPForbidden
3739
38from surveilr import config40from surveilr import config
39from surveilr import messaging41from surveilr import messaging
40from surveilr import models42from surveilr import models
41from surveilr import utils43from surveilr import utils
4244
45def is_privileged(req):
46 if 'surveilr.user' in req.environ:
47 return req.environ['surveilr.user'].credentials['admin']
48 # This feels pretty scary
49 return True
50
51
52def privileged(f):
53 @functools.wraps(f)
54 def wrapped(self, req, *args):
55 if is_privileged(req):
56 return f(self, req, *args)
57 else:
58 return HTTPForbidden()
59 return wrapped
60
4361
44class NotificationController(object):62class NotificationController(object):
45 """Routes style controller for notifications"""63 """Routes style controller for notifications"""
@@ -58,15 +76,30 @@
58class UserController(object):76class UserController(object):
59 """Routes style controller for actions related to users"""77 """Routes style controller for actions related to users"""
6078
79 @privileged
61 def create(self, req):80 def create(self, req):
62 """Called for POST requests to /users81 """Called for POST requests to /users
6382
64 Creates the user, returns a JSON object with the ID assigned83 Creates the user, returns a JSON object with the ID assigned
65 to the user"""84 to the user"""
66 data = json.loads(req.body)85 data = json.loads(req.body)
67 user = models.User(**data)86
87 obj_data = {}
88
89 obj_data['credentials'] = {}
90
91 if 'admin' in data:
92 obj_data['credentials']['admin'] = data['admin']
93
94 for key in ['messaging_driver', 'messaging_address']:
95 if key in data:
96 obj_data[key] = data[key]
97
98 user = models.User(**obj_data)
68 user.save()99 user.save()
69 response = {'id': user.key}100 response = {'id': user.key,
101 'key': user.api_key,
102 'admin': user.credentials.get('admin', False)}
70 return Response(json.dumps(response))103 return Response(json.dumps(response))
71104
72 def show(self, req, id):105 def show(self, req, id):
@@ -77,7 +110,8 @@
77 user = models.User.get(id)110 user = models.User.get(id)
78 resp_dict = {'id': user.key,111 resp_dict = {'id': user.key,
79 'messaging_driver': user.messaging_driver,112 'messaging_driver': user.messaging_driver,
80 'messaging_address': user.messaging_address}113 'messaging_address': user.messaging_address,
114 'admin': user.credentials.get('admin', False)}
81 return Response(json.dumps(resp_dict))115 return Response(json.dumps(resp_dict))
82 except riakalchemy.NoSuchObjectError:116 except riakalchemy.NoSuchObjectError:
83 return HTTPNotFound()117 return HTTPNotFound()
@@ -183,7 +217,10 @@
183 path_prefix='/users/{user_id}')217 path_prefix='/users/{user_id}')
184218
185 def __init__(self, global_config):219 def __init__(self, global_config):
186 pass220 riak_host = config.get_str('riak', 'host')
221 riak_port = config.get_int('riak', 'port')
222
223 riakalchemy.connect(host=riak_host, port=riak_port)
187224
188 @wsgify225 @wsgify
189 def __call__(self, req):226 def __call__(self, req):
@@ -216,11 +253,6 @@
216253
217254
218def main():255def main():
219 riak_host = config.get_str('riak', 'host')
220 riak_port = config.get_int('riak', 'port')
221
222 riakalchemy.connect(host=riak_host, port=riak_port)
223
224 server_factory({}, '', 9877)(SurveilrApplication({}))256 server_factory({}, '', 9877)(SurveilrApplication({}))
225257
226258
227259
=== added file 'surveilr/api/server/auth.py'
--- surveilr/api/server/auth.py 1970-01-01 00:00:00 +0000
+++ surveilr/api/server/auth.py 2012-01-04 23:13:32 +0000
@@ -0,0 +1,48 @@
1"""
2 Surveilr - Log aggregation, analysis and visualisation
3
4 Copyright (C) 2011 Linux2Go
5
6 This program is free software: you can redistribute it and/or
7 modify it under the terms of the GNU Affero General Public License
8 as published by the Free Software Foundation, either version 3 of
9 the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Affero General Public License for more details.
15
16 You should have received a copy of the GNU Affero General Public
17 License along with this program. If not, see
18 <http://www.gnu.org/licenses/>.
19
20 API server auth implementation
21"""
22
23from surveilr import models
24
25from riakalchemy import NoSuchObjectError
26
27class AlwaysRequireAuth(object):
28 def __call__(self, environ, status, headers):
29 return 'repoze.who.identity' not in environ
30
31
32class SurveilrAuthPlugin(object):
33 def authenticate(self, environ, identity):
34 try:
35 login = identity['login']
36 password = identity['password']
37 except KeyError:
38 return None
39
40 try:
41 user = models.User.get(key=login)
42 except NoSuchObjectError:
43 return None
44
45 if user.api_key == password:
46 environ['surveilr.user'] = user
47 return login
48 return None
049
=== added file 'surveilr/api/server/factory.py'
--- surveilr/api/server/factory.py 1970-01-01 00:00:00 +0000
+++ surveilr/api/server/factory.py 2012-01-04 23:13:32 +0000
@@ -0,0 +1,29 @@
1"""
2 Surveilr - Log aggregation, analysis and visualisation
3
4 Copyright (C) 2011 Linux2Go
5
6 This program is free software: you can redistribute it and/or
7 modify it under the terms of the GNU Affero General Public License
8 as published by the Free Software Foundation, either version 3 of
9 the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Affero General Public License for more details.
15
16 You should have received a copy of the GNU Affero General Public
17 License along with this program. If not, see
18 <http://www.gnu.org/licenses/>.
19
20 API server factory
21"""
22import eventlet
23
24def server_factory(global_conf, host, port):
25 port = int(port)
26 def serve(application):
27 socket = eventlet.listen((host, port))
28 eventlet.wsgi.server(socket, application)
29 return serve
030
=== modified file 'surveilr/defaults.cfg'
--- surveilr/defaults.cfg 2011-12-20 10:59:35 +0000
+++ surveilr/defaults.cfg 2012-01-04 23:13:32 +0000
@@ -12,13 +12,22 @@
12port = 809812port = 8098
1313
14[server:main]14[server:main]
15paste.server_factory = surveilr.api.server:server_factory15paste.server_factory = surveilr.api.server.factory:server_factory
16host = 0.0.0.016host = 0.0.0.0
17port = 897717port = 8977
1818
19[composite:main]19[composite:main]
20use = egg:Paste#urlmap20use = egg:Paste#urlmap
21/surveilr = core21/surveilr = secured
22
23[pipeline:secured]
24pipeline = who core
2225
23[app:core]26[app:core]
24paste.app_factory = surveilr.api.server:SurveilrApplication27paste.app_factory = surveilr.api.server.app:SurveilrApplication
28
29[filter:who]
30use = egg:repoze.who#config
31config_file = %(here)s/who.ini
32log_file = stdout
33log_level = debug
2534
=== modified file 'surveilr/models.py'
--- surveilr/models.py 2011-12-09 16:17:30 +0000
+++ surveilr/models.py 2012-01-04 23:13:32 +0000
@@ -22,6 +22,7 @@
22from riakalchemy import RiakObject22from riakalchemy import RiakObject
23from riakalchemy.types import Integer, String, Dict, RelatedObjects23from riakalchemy.types import Integer, String, Dict, RelatedObjects
2424
25from surveilr import utils
2526
26class Service(RiakObject):27class Service(RiakObject):
27 """A service that is referenced by many LogEntry's28 """A service that is referenced by many LogEntry's
@@ -43,9 +44,14 @@
43 """A user of the service"""44 """A user of the service"""
44 bucket_name = 'users'45 bucket_name = 'users'
4546
47 api_key = String()
48 credentials = Dict()
46 messaging_driver = String()49 messaging_driver = String()
47 messaging_address = String()50 messaging_address = String()
4851
52 def pre_save(self):
53 if not hasattr(self, 'api_key'):
54 self.api_key = utils.generate_key()
4955
50class LogEntry(RiakObject):56class LogEntry(RiakObject):
51 """A log entry holding one or more metrics57 """A log entry holding one or more metrics
5258
=== added directory 'surveilr/tests/api/server'
=== added file 'surveilr/tests/api/server/__init__.py'
--- surveilr/tests/api/server/__init__.py 1970-01-01 00:00:00 +0000
+++ surveilr/tests/api/server/__init__.py 2012-01-04 23:13:32 +0000
@@ -0,0 +1,19 @@
1"""
2 Surveilr - Log aggregation, analysis and visualisation
3
4 Copyright (C) 2011 Linux2Go
5
6 This program is free software: you can redistribute it and/or
7 modify it under the terms of the GNU Affero General Public License
8 as published by the Free Software Foundation, either version 3 of
9 the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Affero General Public License for more details.
15
16 You should have received a copy of the GNU Affero General Public
17 License along with this program. If not, see
18 <http://www.gnu.org/licenses/>.
19"""
020
=== renamed file 'surveilr/tests/api/test_server.py' => 'surveilr/tests/api/server/test_app.py'
--- surveilr/tests/api/test_server.py 2011-12-20 10:59:35 +0000
+++ surveilr/tests/api/server/test_app.py 2012-01-04 23:13:32 +0000
@@ -27,8 +27,8 @@
27from surveilr import models27from surveilr import models
28from surveilr import tests28from surveilr import tests
29from surveilr import utils29from surveilr import utils
30from surveilr.api import server30from surveilr.api.server import app
31from surveilr.api.server import SurveilrApplication31from surveilr.api.server.app import SurveilrApplication
3232
3333
34class APIServerTests(tests.TestCase):34class APIServerTests(tests.TestCase):
@@ -36,12 +36,32 @@
36 super(APIServerTests, self).setUp()36 super(APIServerTests, self).setUp()
37 self.application = SurveilrApplication({})37 self.application = SurveilrApplication({})
3838
39 def test_create_user_denied(self):
40 """Creating a user is refused for non-privileged users"""
41 req = Request.blank('/users',
42 method='POST',
43 POST=json.dumps({'messaging_driver': 'fake',
44 'messaging_address': 'foo'}))
45 class FakeUser(object):
46 credentials = {'admin': False}
47
48 req.environ['surveilr.user'] = FakeUser()
49 resp = self.application(req)
50 self.assertEquals(resp.status_int, 403)
51
39 def test_create_retrieve_user(self):52 def test_create_retrieve_user(self):
40 """Create, retrieve, delete, attempt to retrieve again"""53 self._test_create_retrieve_user()
54
55 def test_create_retrieve_admin_user(self):
56 self._test_create_retrieve_user(admin=True)
57
58 def _test_create_retrieve_user(self, admin=False):
59 """Create, retrieve, delete, attempt to retrieve again (user)"""
41 req = Request.blank('/users',60 req = Request.blank('/users',
42 method='POST',61 method='POST',
43 POST=json.dumps({'messaging_driver': 'fake',62 POST=json.dumps({'messaging_driver': 'fake',
44 'messaging_address': 'foo'}))63 'messaging_address': 'foo',
64 'admin': True}))
45 resp = self.application(req)65 resp = self.application(req)
46 self.assertEquals(resp.status_int, 200)66 self.assertEquals(resp.status_int, 200)
4767
@@ -54,6 +74,7 @@
54 user = json.loads(resp.body)74 user = json.loads(resp.body)
55 self.assertEquals(user['messaging_driver'], 'fake')75 self.assertEquals(user['messaging_driver'], 'fake')
56 self.assertEquals(user['messaging_address'], 'foo')76 self.assertEquals(user['messaging_address'], 'foo')
77 self.assertEquals(user['admin'], True)
5778
58 req = Request.blank('/users/%s' % service_id, method='DELETE')79 req = Request.blank('/users/%s' % service_id, method='DELETE')
59 resp = self.application(req)80 resp = self.application(req)
@@ -81,7 +102,7 @@
81 self.assertEquals(resp.status_int, 200)102 self.assertEquals(resp.status_int, 200)
82103
83 def test_create_retrieve_service(self):104 def test_create_retrieve_service(self):
84 """Create, retrieve, delete, attempt to retrieve again"""105 """Create, retrieve, delete, attempt to retrieve again (service)"""
85 req = Request.blank('/services',106 req = Request.blank('/services',
86 method='POST',107 method='POST',
87 POST=json.dumps({'name': 'this_or_the_other'}))108 POST=json.dumps({'name': 'this_or_the_other'}))
@@ -149,7 +170,7 @@
149 'timestamp': 13217362355575,170 'timestamp': 13217362355575,
150 'metrics': {'duration': 85000,171 'metrics': {'duration': 85000,
151 'response_size': 12435}}))172 'response_size': 12435}}))
152 with mock.patch('surveilr.api.server.eventlet') as eventlet:173 with mock.patch('surveilr.api.server.app.eventlet') as eventlet:
153 resp = self.application(req)174 resp = self.application(req)
154175
155 self.assertEquals(eventlet.spawn_n.call_args[0][0],176 self.assertEquals(eventlet.spawn_n.call_args[0][0],
@@ -167,12 +188,12 @@
167 resp = self.application(req)188 resp = self.application(req)
168 self.assertEquals(resp.status_int, 404)189 self.assertEquals(resp.status_int, 404)
169190
170 @mock.patch('surveilr.api.server.eventlet', spec=['listen', 'wsgi'])191 @mock.patch('surveilr.api.server.app.eventlet', spec=['listen', 'wsgi'])
171 @mock.patch('surveilr.api.server.riakalchemy', spec=['connect'])192 @mock.patch('surveilr.api.server.app.riakalchemy', spec=['connect'])
172 def test_main(self, riakalchemy, eventlet):193 def test_main(self, riakalchemy, eventlet):
173 socket_sentinel = mock.sentinel.return_value194 socket_sentinel = mock.sentinel.return_value
174 eventlet.listen.return_value = socket_sentinel195 eventlet.listen.return_value = socket_sentinel
175 server.main()196 app.main()
176197
177 riakalchemy.connect.assert_called_with(host='127.0.0.1', port=8098)198 riakalchemy.connect.assert_called_with(host='127.0.0.1', port=8098)
178 eventlet.listen.assert_called_with(('', 9877))199 eventlet.listen.assert_called_with(('', 9877))
179200
=== added file 'surveilr/tests/api/server/test_auth.py'
--- surveilr/tests/api/server/test_auth.py 1970-01-01 00:00:00 +0000
+++ surveilr/tests/api/server/test_auth.py 2012-01-04 23:13:32 +0000
@@ -0,0 +1,82 @@
1"""
2 Surveilr - Log aggregation, analysis and visualisation
3
4 Copyright (C) 2011 Linux2Go
5
6 This program is free software: you can redistribute it and/or
7 modify it under the terms of the GNU Affero General Public License
8 as published by the Free Software Foundation, either version 3 of
9 the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Affero General Public License for more details.
15
16 You should have received a copy of the GNU Affero General Public
17 License along with this program. If not, see
18 <http://www.gnu.org/licenses/>.
19
20 Tests for API server auth
21"""
22
23from surveilr import models
24from surveilr import tests
25from surveilr.api.server import auth
26
27class TestAPIServerAuth(tests.TestCase):
28 def test_AlwaysRequireAuth_unauthenticated(self):
29 decider = auth.AlwaysRequireAuth()
30 self.assertEquals(decider({}, '200 OK', {}), True)
31
32 def test_AlwaysRequireAuth_already_authenticated(self):
33 decider = auth.AlwaysRequireAuth()
34 self.assertEquals(decider({'repoze.who.identity': 'someone'}, '200 OK', {}), False)
35
36class TestSurveilrAuthPlugin(tests.TestCase):
37 def test_authenticate_invcomplete_identity(self):
38 env = {}
39 identity = {'password': 'apikey'}
40
41 self.assertIsNone(auth.SurveilrAuthPlugin().authenticate(env,
42 identity))
43 self.assertEquals(env, {})
44
45
46 def test_authenticate_invalid_identity(self):
47 env = {}
48 identity = {'login': 'testuser',
49 'password': 'apikey'}
50
51 self.assertIsNone(auth.SurveilrAuthPlugin().authenticate(env,
52 identity))
53 self.assertEquals(env, {})
54
55
56 def test_authenticate_valid_credentials(self):
57 env = {}
58
59 user = models.User()
60 user.save()
61 identity = {'login': user.key,
62 'password': user.api_key}
63
64 self.assertEquals(auth.SurveilrAuthPlugin().authenticate(env,
65 identity),
66 user.key)
67 self.assertEquals(env['surveilr.user'].key, user.key)
68
69 def test_authenticate_wrong_key(self):
70 env = {}
71
72 user = models.User()
73 user.save()
74 self.addCleanup(user.delete)
75
76 identity = {'login': user.key,
77 'password': 'not the right key'}
78
79 self.assertIsNone(auth.SurveilrAuthPlugin().authenticate(env,
80 identity),
81 user.key)
82 self.assertEquals(env, {})
083
=== added file 'surveilr/tests/api/server/test_factory.py'
--- surveilr/tests/api/server/test_factory.py 1970-01-01 00:00:00 +0000
+++ surveilr/tests/api/server/test_factory.py 2012-01-04 23:13:32 +0000
@@ -0,0 +1,43 @@
1"""
2 Surveilr - Log aggregation, analysis and visualisation
3
4 Copyright (C) 2011 Linux2Go
5
6 This program is free software: you can redistribute it and/or
7 modify it under the terms of the GNU Affero General Public License
8 as published by the Free Software Foundation, either version 3 of
9 the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Affero General Public License for more details.
15
16 You should have received a copy of the GNU Affero General Public
17 License along with this program. If not, see
18 <http://www.gnu.org/licenses/>.
19
20 Tests for API server factory
21"""
22
23import mock
24
25from surveilr import tests
26from surveilr.api.server import factory
27
28class APIServerFactoryTests(tests.TestCase):
29 def test_server_factory_returns_callable(self):
30 self.assertTrue(callable(factory.server_factory({}, 'somehost', 1234)))
31
32 @mock.patch('surveilr.api.server.factory.eventlet')
33 def test_server_factory_returns_server(self, eventlet):
34 testhost = 'somehost'
35 testport = '1234'
36 serve = factory.server_factory({}, testhost, testport)
37 app = mock.sentinel.app
38
39 serve(app)
40
41 eventlet.listen.assert_called_with((testhost, int(testport)))
42 eventlet.wsgi.server.assert_called_with(eventlet.listen.return_value,
43 app)
044
=== modified file 'surveilr/tests/test_utils.py'
--- surveilr/tests/test_utils.py 2011-12-20 09:49:02 +0000
+++ surveilr/tests/test_utils.py 2012-01-04 23:13:32 +0000
@@ -23,6 +23,7 @@
23import json23import json
24import time24import time
25import mock25import mock
26import string
2627
27from surveilr import models28from surveilr import models
28from surveilr import tests29from surveilr import tests
@@ -94,3 +95,8 @@
94 self.assertEquals(utils.truncate(133, 20), 120)95 self.assertEquals(utils.truncate(133, 20), 120)
95 self.assertEquals(utils.truncate(133, 100), 100)96 self.assertEquals(utils.truncate(133, 100), 100)
96 self.assertEquals(utils.truncate(133, 200), 0)97 self.assertEquals(utils.truncate(133, 200), 0)
98
99 def test_generate_key(self):
100 key = utils.generate_key()
101 self.assertEquals(len(key), 32)
102 self.assertEquals(len(key.strip(string.letters + string.digits)), 0)
97103
=== modified file 'surveilr/utils.py'
--- surveilr/utils.py 2011-12-11 22:11:47 +0000
+++ surveilr/utils.py 2012-01-04 23:13:32 +0000
@@ -22,6 +22,8 @@
2222
23import httplib223import httplib2
24import json24import json
25import random
26import string
2527
2628
27def truncate(number, rounding_factor):29def truncate(number, rounding_factor):
@@ -39,6 +41,10 @@
39 return (int(number) / int(rounding_factor)) * int(rounding_factor)41 return (int(number) / int(rounding_factor)) * int(rounding_factor)
4042
4143
44def generate_key():
45 return ''.join([random.choice(string.letters + string.digits)
46 for x in range(32)])
47
42def enhance_data_point(data_point):48def enhance_data_point(data_point):
43 http = httplib2.Http(timeout=10)49 http = httplib2.Http(timeout=10)
4450
4551
=== added file 'surveilr/who.ini'
--- surveilr/who.ini 1970-01-01 00:00:00 +0000
+++ surveilr/who.ini 2012-01-04 23:13:32 +0000
@@ -0,0 +1,23 @@
1[plugin:basicauth]
2use = repoze.who.plugins.basicauth:make_plugin
3realm = 'Surveilr'
4
5[plugin:surveilrauth]
6use = surveilr.api.server.auth:SurveilrAuthPlugin
7
8[general]
9request_classifier = repoze.who.classifiers:default_request_classifier
10challenge_decider = surveilr.api.server.auth:AlwaysRequireAuth
11remote_user_key = REMOTE_USER
12
13[identifiers]
14plugins =
15 basicauth
16
17[authenticators]
18plugins =
19 surveilrauth
20
21[challengers]
22plugins =
23 basicauth
024
=== modified file 'tools/pip-requirements.txt'
--- tools/pip-requirements.txt 2011-12-20 10:59:35 +0000
+++ tools/pip-requirements.txt 2012-01-04 23:13:32 +0000
@@ -13,3 +13,4 @@
13paste13paste
14PasteScript14PasteScript
15-e hg+https://code.google.com/p/soren-bulksms/#egg=BulkSMS15-e hg+https://code.google.com/p/soren-bulksms/#egg=BulkSMS
16repoze.who

Subscribers

People subscribed via source and target branches

to all changes: