[60ada4]: / Allura / allura / tests / test_security.py  Maximize  Restore  History

Download this file

202 lines (168 with data), 8.5 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
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
196
197
198
199
200
201
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
from tg import tmpl_context as c
import pytest
from ming.odm import ThreadLocalODMSession
from allura.tests import decorators as td
from allura.tests import TestController
from allura.lib.security import Credentials, all_allowed, has_access
from allura import model as M
from forgewiki import model as WM
from allura.lib.security import HIBPClientError, HIBPClient
from mock import Mock, patch
from requests.exceptions import Timeout
def _allow(obj, role, perm):
obj.acl.insert(0, M.ACE.allow(role._id, perm))
ThreadLocalODMSession.flush_all()
Credentials.get().clear()
def _deny(obj, role, perm):
obj.acl.insert(0, M.ACE.deny(role._id, perm))
ThreadLocalODMSession.flush_all()
Credentials.get().clear()
def _add_to_group(user, role):
M.ProjectRole.by_user(user, upsert=True).roles.append(role._id)
ThreadLocalODMSession.flush_all()
Credentials.get().clear()
@patch('allura.lib.security.requests.get', side_effect=Timeout())
def test_check_breached_password(r_get):
with pytest.raises(HIBPClientError):
HIBPClient.check_breached_password('qwerty')
class TestSecurity(TestController):
validate_skip = True
@td.with_wiki
def test_anon(self):
self.app.get('/security/*anonymous/forbidden', status=302)
self.app.get('/security/*anonymous/needs_auth', status=302)
self.app.get('/security/*anonymous/needs_project_access_fail',
status=302)
self.app.get(
'/security/*anonymous/needs_artifact_access_fail', status=302)
@td.with_wiki
def test_auth(self):
self.app.get('/security/test-admin/forbidden', status=403)
self.app.get('/security/test-admin/needs_auth', status=200)
self.app.get('/security/test-admin/needs_project_access_fail',
status=403)
self.app.get('/security/test-admin/needs_project_access_ok',
status=200)
# This should fail b/c test-user doesn't have the permission
self.app.get('/security/test-user/needs_artifact_access_fail',
extra_environ=dict(username='test-user'), status=403)
# This should succeed b/c users with the 'admin' permission on a
# project implicitly have all permissions to everything in the project
self.app.get(
'/security/test-admin/needs_artifact_access_fail', status=200)
self.app.get('/security/test-admin/needs_artifact_access_ok',
status=200)
@td.with_wiki
def test_all_allowed(self):
wiki = c.project.app_instance('wiki')
admin_role = M.ProjectRole.by_name('Admin')
dev_role = M.ProjectRole.by_name('Developer')
member_role = M.ProjectRole.by_name('Member')
auth_role = M.ProjectRole.by_name('*authenticated')
anon_role = M.ProjectRole.by_name('*anonymous')
test_user = M.User.by_username('test-user')
assert all_allowed(wiki, admin_role) == {
'configure', 'read', 'create', 'edit', 'unmoderated_post', 'post', 'moderate', 'admin', 'delete'}
assert all_allowed(wiki, dev_role) == {
'read', 'create', 'edit', 'unmoderated_post', 'post', 'moderate', 'delete'}
assert (all_allowed(wiki, member_role) ==
{'read', 'create', 'edit', 'unmoderated_post', 'post'})
assert (all_allowed(wiki, auth_role) ==
{'read', 'post', 'unmoderated_post'})
assert all_allowed(wiki, anon_role) == {'read'}
assert (all_allowed(wiki, test_user) ==
{'read', 'post', 'unmoderated_post'})
_add_to_group(test_user, member_role)
assert (all_allowed(wiki, test_user) ==
{'read', 'create', 'edit', 'unmoderated_post', 'post'})
_deny(wiki, auth_role, 'unmoderated_post')
assert (all_allowed(wiki, member_role) ==
{'read', 'create', 'edit', 'post'})
assert (all_allowed(wiki, test_user) ==
{'read', 'create', 'edit', 'post'})
@td.with_wiki
def test_deny_vs_allow(self):
'''
Test interaction of DENYs and ALLOWs in has_access.
'''
wiki = c.project.app_instance('wiki')
page = WM.Page.query.get(app_config_id=wiki.config._id)
anon_role = M.ProjectRole.by_name('*anonymous')
auth_role = M.ProjectRole.by_name('*authenticated')
test_user = M.User.by_username('test-user')
# confirm that *anon has expected access
assert has_access(page, 'read', anon_role)
assert has_access(page, 'post', anon_role)
assert has_access(page, 'unmoderated_post', anon_role)
assert all_allowed(page, anon_role) == {'read'}
# as well as an authenticated user
assert has_access(page, 'read', test_user)
assert has_access(page, 'post', test_user)
assert has_access(page, 'unmoderated_post', test_user)
assert (all_allowed(page, test_user) ==
{'read', 'post', 'unmoderated_post'})
_deny(page, auth_role, 'read')
# read granted to *anon should *not* bubble up past the *auth DENY
assert not has_access(page, 'read', test_user)
# but other perms should not be affected
assert has_access(page, 'post', test_user)
assert has_access(page, 'unmoderated_post', test_user)
# FIXME: all_allowed doesn't respect blocked user feature
#assert_equal(all_allowed(page, test_user), set(['post', 'unmoderated_post']))
assert has_access(wiki, 'read', test_user)
assert has_access(wiki, 'post', test_user)
assert has_access(wiki, 'unmoderated_post', test_user)
assert (all_allowed(wiki, test_user) ==
{'read', 'post', 'unmoderated_post'})
_deny(wiki, anon_role, 'read')
_allow(wiki, auth_role, 'read')
# there isn't a true heiarchy of roles, so any applicable DENY
# will block a user, even if there's an explicit ALLOW "higher up"
assert not has_access(wiki, 'read', test_user)
assert has_access(wiki, 'post', test_user)
assert has_access(wiki, 'unmoderated_post', test_user)
# FIXME: all_allowed doesn't respect blocked user feature
#assert_equal(all_allowed(wiki, test_user), set(['post', 'unmoderated_post']))
@td.with_wiki
def test_implicit_project(self):
'''
Test that relying on implicit project context does the Right Thing.
If you call has_access(artifact, perm), it should use the roles from
the project to which artifact belongs, even in c.project is something
else. If you really want to use the roles from an unrelated project,
you should have to be very explicit about it, not just set c.project.
'''
project1 = c.project
project2 = M.Project.query.get(shortname='test2')
wiki = project1.app_instance('wiki')
page = WM.Page.query.get(app_config_id=wiki.config._id)
test_user = M.User.by_username('test-user')
assert project1.shortname == 'test'
assert has_access(page, 'read', test_user)
c.project = project2
assert has_access(page, 'read', test_user)
@td.with_wiki
def test_deny_access_for_single_user(self):
wiki = c.project.app_instance('wiki')
user = M.User.by_username('test-user')
assert has_access(wiki, 'read', user)
wiki.acl.append(
M.ACE.deny(M.ProjectRole.by_user(user, upsert=True)._id, 'read', 'Spammer'))
Credentials.get().clear()
assert not has_access(wiki, 'read', user)