blob: 41aa8d38a1c21439e0cc2029086fd831c97e01e5 [file] [log] [blame]
# coding: utf-8
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
import json
import datetime as dt
import bson
from mock import patch, MagicMock
from nose.tools import assert_equal, assert_in, assert_not_in
from ming.odm import ThreadLocalORMSession
from pylons import tmpl_context as c
from tg import config
from bson import ObjectId
from allura import model as M
from allura.tests import TestController
from allura.tests import decorators as td
from allura.lib import helpers as h
from allura.lib.decorators import task
from allura.lib.plugin import LocalAuthenticationProvider
class TestSiteAdmin(TestController):
def test_access(self):
r = self.app.get('/nf/admin/', extra_environ=dict(
username='test-user'), status=403)
r = self.app.get('/nf/admin/', extra_environ=dict(
username='*anonymous'), status=302)
r = r.follow()
assert 'Login' in r
def test_home(self):
r = self.app.get('/nf/admin/', extra_environ=dict(
username='root'))
assert 'Site Admin Home' in r
def test_stats(self):
r = self.app.get('/nf/admin/stats/', extra_environ=dict(
username='root'))
assert 'Forge Site Admin' in r.html.find(
'h2', {'class': 'dark title'}).contents[0]
stats_table = r.html.find('table')
cells = stats_table.findAll('td')
assert cells[0].contents[0] == 'Adobe', cells[0].contents[0]
def test_tickets_access(self):
self.app.get('/nf/admin/api_tickets', extra_environ=dict(
username='test-user'), status=403)
def test_new_projects_access(self):
self.app.get('/nf/admin/new_projects', extra_environ=dict(
username='test_user'), status=403)
r = self.app.get('/nf/admin/new_projects', extra_environ=dict(
username='*anonymous'), status=302).follow()
assert 'Login' in r
def test_new_projects(self):
r = self.app.get('/nf/admin/new_projects', extra_environ=dict(
username='root'))
headers = r.html.find('table').findAll('th')
assert headers[1].contents[0] == 'Created'
assert headers[2].contents[0] == 'Shortname'
assert headers[3].contents[0] == 'Name'
assert headers[4].contents[0] == 'Short description'
assert headers[5].contents[0] == 'Summary'
assert headers[6].contents[0] == 'Homepage'
assert headers[7].contents[0] == 'Admins'
def test_new_projects_deleted_projects(self):
'''Deleted projects should not be visible here'''
r = self.app.get('/nf/admin/new_projects', extra_environ=dict(
username='root'))
count = len(r.html.find('table').findAll('tr'))
p = M.Project.query.get(shortname='test')
p.deleted = True
ThreadLocalORMSession.flush_all()
r = self.app.get('/nf/admin/new_projects', extra_environ=dict(
username='root'))
assert_equal(len(r.html.find('table').findAll('tr')), count - 1)
def test_new_projects_daterange_filtering(self):
r = self.app.get('/nf/admin/new_projects', extra_environ=dict(
username='root'))
count = len(r.html.find('table').findAll('tr'))
assert_equal(count, 7)
filtr = r.forms[0]
filtr['start-dt'] = '2000/01/01 10:10:10'
filtr['end-dt'] = '2000/01/01 09:09:09'
r = filtr.submit()
count = len(r.html.find('table').findAll('tr'))
assert_equal(count, 1) # only row with headers - no results
def test_reclone_repo_access(self):
r = self.app.get('/nf/admin/reclone_repo', extra_environ=dict(
username='*anonymous'), status=302).follow()
assert 'Login' in r
def test_reclone_repo(self):
r = self.app.get('/nf/admin/reclone_repo')
assert 'Reclone repository' in r
def test_reclone_repo_default_value(self):
r = self.app.get('/nf/admin/reclone_repo')
assert 'value="p"' in r
def test_task_list(self):
r = self.app.get('/nf/admin/task_manager',
extra_environ=dict(username='*anonymous'), status=302)
import math
M.MonQTask.post(math.ceil, (12.5,))
r = self.app.get('/nf/admin/task_manager?page_num=1')
assert 'math.ceil' in r, r
def test_task_view(self):
import math
task = M.MonQTask.post(math.ceil, (12.5,))
url = '/nf/admin/task_manager/view/%s' % task._id
r = self.app.get(
url, extra_environ=dict(username='*anonymous'), status=302)
r = self.app.get(url)
assert 'math.ceil' in r, r
def test_task_new(self):
r = self.app.get('/nf/admin/task_manager/new')
assert 'New Task' in r, r
def test_task_create(self):
project = M.Project.query.get(shortname='test')
app = project.app_instance('admin')
user = M.User.by_username('root')
task_args = dict(
args=['foo'],
kwargs=dict(bar='baz'))
r = self.app.post('/nf/admin/task_manager/create', params=dict(
task='allura.tests.functional.test_site_admin.test_task',
task_args=json.dumps(task_args),
user='root',
path='/p/test/admin',
), status=302)
task = M.MonQTask.query.find({}).sort('_id', -1).next()
assert str(task._id) in r.location
assert task.context['project_id'] == project._id
assert task.context['app_config_id'] == app.config._id
assert task.context['user_id'] == user._id
assert task.args == task_args['args']
assert task.kwargs == task_args['kwargs']
def test_task_doc(self):
r = self.app.get('/nf/admin/task_manager/task_doc', params=dict(
task_name='allura.tests.functional.test_site_admin.test_task'))
assert json.loads(r.body)['doc'] == 'test_task doc string'
def test_site_notifications_access(self):
self.app.get('/nf/admin/site_notifications', extra_environ=dict(
username='test_user'), status=403)
r = self.app.get('/nf/admin/site_notifications', extra_environ=dict(
username='*anonymous'), status=302).follow()
assert 'Login' in r
def test_site_notifications(self):
M.notification.SiteNotification(active=True,
impressions=0,
content='test1',
user_role='test2',
page_regex='test3',
page_tool_type='test4')
ThreadLocalORMSession().flush_all()
assert M.notification.SiteNotification.query.find().count() == 1
r = self.app.get('/nf/admin/site_notifications/', extra_environ=dict(
username='root'))
table = r.html.find('table')
headers = table.findAll('th')
row = table.findAll('td')
assert headers[0].contents[0] == 'Active'
assert headers[1].contents[0] == 'Impressions'
assert headers[2].contents[0] == 'Content'
assert headers[3].contents[0] == 'User Role'
assert headers[4].contents[0] == 'Page Regex'
assert headers[5].contents[0] == 'Page Type'
assert row[0].contents[0].contents[0] == 'True'
assert row[1].contents[0].contents[0] == '0'
assert row[2].contents[0].contents[0] == 'test1'
assert row[3].contents[0].contents[0] == 'test2'
assert row[4].contents[0].contents[0] == 'test3'
assert row[5].contents[0].contents[0] == 'test4'
def test_site_notification_new_template(self):
r = self.app.get('/nf/admin/site_notifications/new')
assert r
assert 'New Site Notification' in r
assert 'Active' in r
assert 'Impressions' in r
assert 'Content' in r
assert 'User Role' in r
assert 'Page Regex' in r
assert 'Page Type' in r
def test_site_notification_create(self):
count = M.notification.SiteNotification.query.find().count()
active = 'True'
impressions = '7'
content = 'test1'
user_role = 'test2'
page_regex = 'test3'
page_tool_type = 'test4'
r = self.app.post('/nf/admin/site_notifications/create', params=dict(
active=active,
impressions=impressions,
content=content,
user_role=user_role,
page_regex=page_regex,
page_tool_type=page_tool_type))
note = M.notification.SiteNotification.query.find().sort('_id', -1).next()
assert '/nf/admin/site_notifications' in r.location
assert M.notification.SiteNotification.query.find().count() == count + 1
assert note.active == bool('True')
assert note.impressions == int(impressions)
assert note.content == content
assert note.user_role == user_role
assert note.page_regex == page_regex
assert note.page_tool_type == page_tool_type
def test_site_notification_edit_template(self):
note = M.notification.SiteNotification(active=True,
impressions=0,
content='test1',
user_role='test2',
page_regex='test3',
page_tool_type='test4')
ThreadLocalORMSession().flush_all()
r = self.app.get('/nf/admin/site_notifications/{}/edit'.format(note._id))
assert r
assert (u'selected', u'selected') in r.html.find('form').findAll('option')[1].attrs
assert r.form['impressions'].value == '0'
assert r.form['content'].value == 'test1'
assert r.form['user_role'].value == 'test2'
assert r.form['page_regex'].value == 'test3'
assert r.form['page_tool_type'].value == 'test4'
assert 'Edit Site Notification' in r
assert 'Active' in r
assert 'Impressions' in r
assert 'Content' in r
assert 'User Role' in r
assert 'Page Regex' in r
assert 'Page Type' in r
def test_site_notification_update(self):
active = 'True'
impressions = '7'
content = 'test1'
user_role = 'test2'
page_regex = 'test3'
page_tool_type = 'test4'
note = M.notification.SiteNotification(active=False,
impressions=0,
content='test')
ThreadLocalORMSession().flush_all()
count = M.notification.SiteNotification.query.find().count()
r = self.app.post('/nf/admin/site_notifications/{}/update'.format(note._id), params=dict(
active=active,
impressions=impressions,
content=content,
user_role=user_role,
page_regex=page_regex,
page_tool_type=page_tool_type))
ThreadLocalORMSession().flush_all()
note = M.notification.SiteNotification.query.find().sort('_id', -1).next()
assert '/nf/admin/site_notifications' in r.location
assert M.notification.SiteNotification.query.find().count() == count
assert note.active == bool('True')
assert note.impressions == int(impressions)
assert note.content == content
assert note.user_role == user_role
assert note.page_regex == page_regex
assert note.page_tool_type == page_tool_type
def test_site_notification_delete(self):
note = M.notification.SiteNotification(active=False,
impressions=0,
content='test')
ThreadLocalORMSession().flush_all()
count = M.notification.SiteNotification.query.find().count()
self.app.post('/nf/admin/site_notifications/{}/delete'.format(note._id))
assert M.notification.SiteNotification.query.find().count() == count -1
assert M.notification.SiteNotification.query.get(_id=bson.ObjectId(note._id)) is None
class TestProjectsSearch(TestController):
TEST_HIT = MagicMock(hits=1, docs=[{
'name_s': 'Test Project',
'is_nbhd_project_b': False,
'is_root_b': True,
'title': ['Project Test Project'],
'deleted_b': False,
'shortname_s': 'test',
'private_b': False,
'url_s': 'http://localhost:8080/p/test/',
'neighborhood_id_s': '53ccf6e6100d2b0741746c66',
'removal_changed_date_dt': '2014-07-21T11:18:00.087Z',
'registration_dt': '2014-07-21T11:18:00Z',
'type_s': 'Project',
'_version_': 1474236502200287232,
'neighborhood_name_s': 'Projects',
'id': 'allura/model/project/Project#53ccf6e8100d2b0741746e9f',
}])
def setUp(self):
super(TestProjectsSearch, self).setUp()
# Create project that matches TEST_HIT id
_id = ObjectId('53ccf6e8100d2b0741746e9f')
p = M.Project.query.get(_id=_id)
if not p:
M.Project(
_id=_id,
neighborhood_id=M.Neighborhood.query.get(url_prefix='/u/')._id,
shortname='test-project',
)
ThreadLocalORMSession().flush_all()
@patch('allura.controllers.site_admin.search')
def test_default_fields(self, search):
search.site_admin_search.return_value = self.TEST_HIT
r = self.app.get('/nf/admin/search_projects?q=fake&f=shortname')
options = [o['value'] for o in r.html.findAll('option')]
assert_equal(options, ['shortname', 'name', '__custom__'])
ths = [th.text for th in r.html.findAll('th')]
assert_equal(ths, ['Short name', 'Full name', 'Registered', 'Deleted?', 'Details'])
@patch('allura.controllers.site_admin.search')
def test_additional_fields(self, search):
search.site_admin_search.return_value = self.TEST_HIT
with h.push_config(config, **{'search.project.additional_search_fields': 'private, url',
'search.project.additional_display_fields': 'url'}):
r = self.app.get('/nf/admin/search_projects?q=fake&f=shortname')
options = [o['value'] for o in r.html.findAll('option')]
assert_equal(options, ['shortname', 'name', 'private', 'url', '__custom__'])
ths = [th.text for th in r.html.findAll('th')]
assert_equal(ths, ['Short name', 'Full name', 'Registered', 'Deleted?', 'url', 'Details'])
class TestUsersSearch(TestController):
TEST_HIT = MagicMock(hits=1, docs=[{
'_version_': 1478773871277506560,
'disabled_b': False,
'pending_b': False,
'display_name_t': 'Darth Vader',
'id': 'allura/model/auth/User#540efdf2100d2b1483155d39',
'last_access_login_date_dt': '2014-09-09T13:17:40.176Z',
'last_access_login_ip_s': '10.0.2.2',
'last_access_login_ua_t': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36',
'last_access_session_date_dt': '2014-09-09T13:17:40.33Z',
'last_access_session_ip_s': '10.0.2.2',
'last_access_session_ua_t': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36',
'last_password_updated_dt': '2014-09-09T13:17:38.857Z',
'localization_s': 'None/None',
'sex_s': 'Unknown',
'title': ['User darth'],
'type_s': 'User',
'url_s': '/u/darth/',
'user_registration_date_dt': '2014-09-09T13:17:38Z',
'username_s': 'darth'}])
def setUp(self):
super(TestUsersSearch, self).setUp()
# Create user that matches TEST_HIT id
_id = ObjectId('540efdf2100d2b1483155d39')
u = M.User.query.get(_id=_id)
if not u:
M.User(_id=_id, username='darth')
ThreadLocalORMSession().flush_all()
@patch('allura.controllers.site_admin.search')
def test_default_fields(self, search):
search.site_admin_search.return_value = self.TEST_HIT
r = self.app.get('/nf/admin/search_users?q=fake&f=username')
options = [o['value'] for o in r.html.findAll('option')]
assert_equal(options, ['username', 'display_name', '__custom__'])
ths = [th.text for th in r.html.findAll('th')]
assert_equal(ths, ['Username', 'Display name', 'Email', 'Registered',
'Status', 'Details'])
@patch('allura.controllers.site_admin.search')
def test_additional_fields(self, search):
search.site_admin_search.return_value = self.TEST_HIT
with h.push_config(config, **{'search.user.additional_search_fields': 'email_addresses, url',
'search.user.additional_display_fields': 'url'}):
r = self.app.get('/nf/admin/search_users?q=fake&f=username')
options = [o['value'] for o in r.html.findAll('option')]
assert_equal(options, ['username', 'display_name', 'email_addresses', 'url', '__custom__'])
ths = [th.text for th in r.html.findAll('th')]
assert_equal(ths, ['Username', 'Display name', 'Email', 'Registered',
'Status', 'url', 'Details'])
class TestUserDetails(TestController):
def test_404(self):
self.app.get('/nf/admin/user/does-not-exist/', status=404)
def test_general_info(self):
user = M.User.by_username('test-admin')
user.registration_date = lambda: dt.datetime(2014, 9, 1, 9, 9, 9)
user.last_access = {'login_date': dt.datetime(2014, 9, 2, 6, 6, 6),
'login_ua': 'browser of the future 1.0',
'login_ip': '8.8.8.8',
'session_date': dt.datetime(2014, 9, 12, 6, 6, 6),
'session_ua': 'browser of the future 1.1',
'session_ip': '7.7.7.7'}
r = self.app.get('/nf/admin/user/test-admin/')
# general info
assert_in('Username: test-admin', r)
assert_in('Full name: Test Admin', r)
assert_in('Registered: 2014-09-01 09:09:09', r)
# session info
assert_in('Date: 2014-09-02 06:06:06', r)
assert_in('IP: 8.8.8.8', r)
assert_in('UA: browser of the future 1.0', r)
assert_in('Date: 2014-09-12', r)
assert_in('IP: 7.7.7.7', r)
assert_in('UA: browser of the future 1.1', r)
# list of projects
projects = r.html.findAll('fieldset')[-1]
projects = [e.getText() for e in projects.findAll('li')]
assert_in('Test 2–Admin', projects)
assert_in('Test Project–Admin', projects)
assert_in('Adobe project 1–Admin', projects)
@patch('allura.model.auth.request')
@patch('allura.lib.helpers.request')
def test_audit_log(self, req1, req2):
req1.url = req2.url = 'http://host.domain/path/'
c.user = M.User.by_username('test-user-1')
h.auditlog_user('test activity user 1')
h.auditlog_user('test activity user 2', user=M.User.by_username('test-user-2'))
r = self.app.get('/nf/admin/user/test-admin')
assert_in('Add comment', r)
assert_not_in('test activity', r)
r = self.app.get('/nf/admin/user/test-user-1')
assert_in('test activity user 1', r)
assert_not_in('test activity user 2', r)
r = self.app.get('/nf/admin/user/test-user-2')
assert_not_in('test activity user 1', r)
assert_in('test activity user 2', r)
def test_add_audit_trail_entry_access(self):
self.app.get('/nf/admin/user/add_audit_log_entry', status=404) # GET is not allowed
r = self.app.post('/nf/admin/user/add_audit_log_entry',
extra_environ={'username': '*anonymous'},
status=302)
assert_equal(r.location, 'http://localhost/auth/')
def test_add_comment(self):
r = self.app.get('/nf/admin/user/test-user')
assert_not_in(u'Comment by test-admin: I was hêre!', r)
form = r.forms[4]
assert_equal(form['username'].value, 'test-user')
form['comment'] = u'I was hêre!'
r = form.submit()
assert_in(u'Comment added', self.webflash(r))
r = self.app.get('/nf/admin/user/test-user')
assert_in(u'Comment by test-admin: I was hêre!', r)
def test_disable_user(self):
# user was not pending
assert_equal(M.User.by_username('test-user-3').disabled, False)
assert_equal(M.User.by_username('test-user-3').pending, False)
r = self.app.get('/nf/admin/user/test-user-3')
form = r.forms[0]
assert_equal(form['username'].value, 'test-user-3')
assert_equal(form['status'].value, 'enable')
form['status'].value = 'disable'
with td.audits('Account disabled', user=True):
r = form.submit()
assert_equal(M.AuditLog.query.find().count(), 1)
assert_in(u'User disabled', self.webflash(r))
assert_equal(M.User.by_username('test-user-3').disabled, True)
assert_equal(M.User.by_username('test-user-3').pending, False)
# user was pending
user = M.User.by_username('test-user-3')
user.disabled = False
user.pending = True
ThreadLocalORMSession.flush_all()
assert_equal(M.User.by_username('test-user-3').disabled, False)
assert_equal(M.User.by_username('test-user-3').pending, True)
r = self.app.get('/nf/admin/user/test-user-3')
form = r.forms[0]
assert_equal(form['username'].value, 'test-user-3')
assert_equal(form['status'].value, 'pending')
form['status'].value = 'disable'
with td.audits('Account disabled', user=True):
r = form.submit()
assert_equal(M.AuditLog.query.find().count(), 1)
assert_in(u'User disabled', self.webflash(r))
assert_equal(M.User.by_username('test-user-3').disabled, True)
assert_equal(M.User.by_username('test-user-3').pending, True)
def test_enable_user(self):
# user was not pending
user = M.User.by_username('test-user-3')
user.disabled = True
ThreadLocalORMSession.flush_all()
assert_equal(M.User.by_username('test-user-3').disabled, True)
assert_equal(M.User.by_username('test-user-3').pending, False)
r = self.app.get('/nf/admin/user/test-user-3')
form = r.forms[0]
assert_equal(form['username'].value, 'test-user-3')
assert_equal(form['status'].value, 'disable')
form['status'].value = 'enable'
with td.audits('Account enabled', user=True):
r = form.submit()
assert_equal(M.AuditLog.query.find().count(), 1)
assert_in(u'User enabled', self.webflash(r))
assert_equal(M.User.by_username('test-user-3').disabled, False)
assert_equal(M.User.by_username('test-user-3').pending, False)
# user was pending
user = M.User.by_username('test-user-3')
user.disabled = False
user.pending = True
ThreadLocalORMSession.flush_all()
assert_equal(M.User.by_username('test-user-3').disabled, False)
assert_equal(M.User.by_username('test-user-3').pending, True)
r = self.app.get('/nf/admin/user/test-user-3')
form = r.forms[0]
assert_equal(form['username'].value, 'test-user-3')
assert_equal(form['status'].value, 'pending')
form['status'].value = 'enable'
with td.audits('Account enabled', user=True):
r = form.submit()
assert_equal(M.AuditLog.query.find().count(), 1)
assert_in(u'User enabled', self.webflash(r))
assert_equal(M.User.by_username('test-user-3').disabled, False)
assert_equal(M.User.by_username('test-user-3').pending, False)
# user was pending and disabled
user = M.User.by_username('test-user-3')
user.disabled = True
user.pending = True
ThreadLocalORMSession.flush_all()
assert_equal(M.User.by_username('test-user-3').disabled, True)
assert_equal(M.User.by_username('test-user-3').pending, True)
r = self.app.get('/nf/admin/user/test-user-3')
form = r.forms[0]
assert_equal(form['username'].value, 'test-user-3')
assert_equal(form['status'].value, 'disable')
form['status'].value = 'enable'
with td.audits('Account enabled', user=True):
r = form.submit()
assert_equal(M.AuditLog.query.find().count(), 1)
assert_in(u'User enabled', self.webflash(r))
assert_equal(M.User.by_username('test-user-3').disabled, False)
assert_equal(M.User.by_username('test-user-3').pending, False)
def test_set_pending(self):
# user was disabled
user = M.User.by_username('test-user-3')
user.disabled = True
ThreadLocalORMSession.flush_all()
assert_equal(M.User.by_username('test-user-3').disabled, True)
assert_equal(M.User.by_username('test-user-3').pending, False)
r = self.app.get('/nf/admin/user/test-user-3')
form = r.forms[0]
assert_equal(form['username'].value, 'test-user-3')
assert_equal(form['status'].value, 'disable')
form['status'].value = 'pending'
with td.audits('Account changed to pending', user=True):
r = form.submit()
assert_equal(M.AuditLog.query.find().count(), 1)
assert_in(u'Set user status to pending', self.webflash(r))
assert_equal(M.User.by_username('test-user-3').disabled, False)
assert_equal(M.User.by_username('test-user-3').pending, True)
# user was enabled
user = M.User.by_username('test-user-3')
user.pending = False
user.disabled = False
ThreadLocalORMSession.flush_all()
assert_equal(M.User.by_username('test-user-3').disabled, False)
assert_equal(M.User.by_username('test-user-3').pending, False)
r = self.app.get('/nf/admin/user/test-user-3')
form = r.forms[0]
assert_equal(form['username'].value, 'test-user-3')
assert_equal(form['status'].value, 'enable')
form['status'].value = 'pending'
with td.audits('Account changed to pending', user=True):
r = form.submit()
assert_equal(M.AuditLog.query.find().count(), 1)
assert_in(u'Set user status to pending', self.webflash(r))
assert_equal(M.User.by_username('test-user-3').disabled, False)
assert_equal(M.User.by_username('test-user-3').pending, True)
def test_emails(self):
# add test@example.com
with td.audits('New email address: test@example.com', user=True):
r = self.app.post('/nf/admin/user/update_emails', params={
'username': 'test-user',
'new_addr.addr': 'test@example.com',
'new_addr.claim': 'Claim Address',
'primary_addr': 'test@example.com'},
extra_environ=dict(username='test-admin'))
r = self.app.get('/nf/admin/user/test-user')
assert_in('test@example.com', r)
em = M.EmailAddress.get(email='test@example.com')
assert_equal(em.confirmed, True)
user = M.User.query.get(username='test-user')
assert_equal(user.get_pref('email_address'), 'test@example.com')
# add test2@example.com
with td.audits('New email address: test2@example.com', user=True):
r = self.app.post('/nf/admin/user/update_emails', params={
'username': 'test-user',
'new_addr.addr': 'test2@example.com',
'new_addr.claim': 'Claim Address',
'primary_addr': 'test@example.com'},
extra_environ=dict(username='test-admin'))
r = self.app.get('/nf/admin/user/test-user')
assert_in('test2@example.com', r)
em = M.EmailAddress.get(email='test2@example.com')
assert_equal(em.confirmed, True)
user = M.User.query.get(username='test-user')
assert_equal(user.get_pref('email_address'), 'test@example.com')
# change primary: test -> test2
with td.audits('Primary email changed: test@example.com => test2@example.com', user=True):
r = self.app.post('/nf/admin/user/update_emails', params={
'username': 'test-user',
'new_addr.addr': '',
'primary_addr': 'test2@example.com'},
extra_environ=dict(username='test-admin'))
r = self.app.get('/nf/admin/user/test-user')
user = M.User.query.get(username='test-user')
assert_equal(user.get_pref('email_address'), 'test2@example.com')
# remove test2@example.com
with td.audits('Email address deleted: test2@example.com', user=True):
r = self.app.post('/nf/admin/user/update_emails', params={
'username': 'test-user',
'addr-1.ord': '1',
'addr-2.ord': '2',
'addr-2.delete': 'on',
'new_addr.addr': '',
'primary_addr': 'test2@example.com'},
extra_environ=dict(username='test-admin'))
r = self.app.get('/nf/admin/user/test-user')
user = M.User.query.get(username='test-user')
# test@example.com set as primary since test2@example.com is deleted
assert_equal(user.get_pref('email_address'), 'test@example.com')
@patch.object(LocalAuthenticationProvider, 'set_password')
def test_set_random_password(self, set_password):
with td.audits('Set random password', user=True, actor='test-admin'):
r = self.app.post('/nf/admin/user/set_random_password', params={'username': 'test-user'})
assert_in('Password is set', self.webflash(r))
set_password.assert_called_once()
@patch('allura.tasks.mail_tasks.sendsimplemail')
@patch('allura.lib.helpers.gen_message_id')
def test_send_password_reset_link(self, gen_message_id, sendmail):
user = M.User.by_username('test-user')
user.set_pref('email_address', 'test-user@example.org')
M.EmailAddress(email='test-user@example.org', confirmed=True, claimed_by_user_id=user._id)
ThreadLocalORMSession.flush_all()
with td.audits('Password recovery link sent to: test-user@example.org', user=True):
r = self.app.post('/nf/admin/user/send_password_reset_link', params={'username': 'test-user'})
hash = user.get_tool_data('AuthPasswordReset', 'hash')
text = '''Your username is test-user
To reset your password on %s, please visit the following URL:
%s/auth/forgotten_password/%s''' % (config['site_name'], config['base_url'], hash)
sendmail.post.assert_called_once_with(
toaddr='test-user@example.org',
fromaddr=config['forgemail.return_path'],
reply_to=config['forgemail.return_path'],
subject='Allura Password recovery',
message_id=gen_message_id(),
text=text)
class TestDeleteProjects(TestController):
def confirm_form(self, r):
return self.find_form(r, lambda f: f.action == 'really_delete')
def delete_form(self, r):
return self.find_form(r, lambda f: f.action == 'confirm')
def test_projects_populated_from_get_params(self):
r = self.app.get('/nf/admin/delete_projects/')
assert_equal(self.delete_form(r)['projects'].value, u'')
link = '/nf/admin/delete_projects/?projects=/p/test/++++%23+comment%0A/adobe/adobe-1/%0A/p/test2/'
link += '&reason=The%0AReason&disable_users=True'
r = self.app.get(link)
form = self.delete_form(r)
assert_equal(form['projects'].value, u'/p/test/ # comment\n/adobe/adobe-1/\n/p/test2/')
assert_equal(form['reason'].value, u'The\nReason')
assert_equal(form['disable_users'].value, u'on')
def test_confirm_step_values(self):
r = self.app.get('/nf/admin/delete_projects/')
form = self.delete_form(r)
form['projects'] = 'p/test\ndne/dne'
form['reason'] = 'The Reason'
form['disable_users'] = True
r = form.submit()
confirm_form = self.confirm_form(r)
for f in ['reason', 'disable_users']:
assert_equal(confirm_form[f].value, form[f].value)
assert_equal(confirm_form['projects'].value, 'p/test # OK: /p/test/\ndne/dne # Neighborhood not found')
confirm_data = r.html.find('table').findAll('td')
assert_equal(len(confirm_data), 4) # 2 projects == 2 rows (2 columns each)
assert_equal(confirm_data[0].getText(), 'p/test')
assert_equal(confirm_data[1].find('a').get('href'), '/p/test/')
assert_equal(confirm_data[1].getText(), '/p/test/')
assert_equal(confirm_data[2].getText(), 'dne/dne')
assert_equal(confirm_data[3].getText(), 'Neighborhood not found')
def test_confirm_step_edit_link(self):
r = self.app.get('/nf/admin/delete_projects/')
form = self.delete_form(r)
form['projects'] = 'p/test\np/dne'
form['reason'] = 'The Reason\nMultiline'
form['disable_users'] = True
r = form.submit()
expected_href = './?projects=p/test++++%23+OK:+/p/test%0Ap/dne++++%23+Project not found'
expected_href += '&reason=The+Reason%0AMultiline&disable_users=True'
assert r.html.findAll('a', {'href': expected_href}) is not None
@patch('allura.controllers.site_admin.DeleteProjects', autospec=True)
def test_reason_passed_to_task(self, dp):
data = {'projects': 'p/test2', 'reason': 'Because "I can and want"'}
self.app.post('/nf/admin/delete_projects/really_delete', data)
dp.post.assert_called_once_with('-r \'Because "I can and want"\' p/test2')
@patch('allura.controllers.site_admin.DeleteProjects', autospec=True)
def test_multiline_reason_passed_to_task(self, dp):
data = {'projects': 'p/test2', 'reason': 'Because\nI want'}
self.app.post('/nf/admin/delete_projects/really_delete', data)
dp.post.assert_called_once_with('-r \'Because\nI want\' p/test2')
@patch('allura.controllers.site_admin.DeleteProjects', autospec=True)
def test_task_fires(self, dp):
data = {'projects': '/p/test\nhttp://localhost:8080/adobe/adobe-1\np/test2'}
self.app.post('/nf/admin/delete_projects/really_delete', data)
dp.post.assert_called_once_with('p/test adobe/adobe-1 p/test2')
@patch('allura.controllers.site_admin.DeleteProjects', autospec=True)
def test_comments_are_ignored(self, dp):
data = {'projects': '''/p/test # comment
/p/test2 # comment 2'''}
self.app.post('/nf/admin/delete_projects/really_delete', data)
dp.post.assert_called_once_with('p/test p/test2')
@patch('allura.controllers.site_admin.DeleteProjects', autospec=True)
def test_admins_and_devs_are_disabled(self, dp):
data = {'projects': '/p/test\np/test2', 'disable_users': True}
self.app.post('/nf/admin/delete_projects/really_delete', data)
dp.post.assert_called_once_with('--disable-users p/test p/test2')
@patch('allura.controllers.site_admin.DeleteProjects', autospec=True)
def test_subproject_delete(self, dp):
data = {'projects': '/p/test/sub1/something\np/test2'}
self.app.post('/nf/admin/delete_projects/really_delete', data)
dp.post.assert_called_once_with('p/test/sub1 p/test2')
@task
def test_task(*args, **kw):
"""test_task doc string"""
pass