Mercurial > p > roundup > code
comparison test/test_cgi.py @ 5154:f608eeecf638
issue2550891: Allow subdir in template value. Anthony (antmail)
requested the ability to put templates into subdirectories. So
the issue class can accept @template=issues/item to get the
html/issues/issue.item.html template.
Inlcude a test case for missing and existing (tal) templates.
Also include a test that fails path traversal check.
Add mention of subdiectoy use to customizing.txt along with some
spelling fixes and ^M removal.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Fri, 22 Jul 2016 15:19:40 -0400 |
| parents | 92d33d3125a0 |
| children | 7fb697267fdb |
comparison
equal
deleted
inserted
replaced
| 5153:e9801faebbe4 | 5154:f608eeecf638 |
|---|---|
| 10 | 10 |
| 11 import unittest, os, shutil, errno, sys, difflib, cgi, re, StringIO | 11 import unittest, os, shutil, errno, sys, difflib, cgi, re, StringIO |
| 12 | 12 |
| 13 from roundup.cgi import client, actions, exceptions | 13 from roundup.cgi import client, actions, exceptions |
| 14 from roundup.cgi.exceptions import FormError | 14 from roundup.cgi.exceptions import FormError |
| 15 from roundup.cgi.templating import HTMLItem, HTMLRequest | 15 from roundup.cgi.templating import HTMLItem, HTMLRequest, NoTemplate |
| 16 from roundup.cgi.form_parser import FormParser | 16 from roundup.cgi.form_parser import FormParser |
| 17 from roundup import init, instance, password, hyperdb, date | 17 from roundup import init, instance, password, hyperdb, date |
| 18 | 18 |
| 19 from mocknull import MockNull | 19 from mocknull import MockNull |
| 20 | 20 |
| 1083 # used to be self.assertRaises(exceptions.Unauthorised, | 1083 # used to be self.assertRaises(exceptions.Unauthorised, |
| 1084 # but not acting like the column name is not found | 1084 # but not acting like the column name is not found |
| 1085 self.assertRaises(exceptions.SeriousError, | 1085 self.assertRaises(exceptions.SeriousError, |
| 1086 actions.ExportCSVAction(cl).handle) | 1086 actions.ExportCSVAction(cl).handle) |
| 1087 | 1087 |
| 1088 class TemplateTestCase(unittest.TestCase): | |
| 1089 ''' Test the template resolving code, i.e. what can be given to @template | |
| 1090 ''' | |
| 1091 def setUp(self): | |
| 1092 self.dirname = '_test_template' | |
| 1093 # set up and open a tracker | |
| 1094 self.instance = db_test_base.setupTracker(self.dirname) | |
| 1095 | |
| 1096 # open the database | |
| 1097 self.db = self.instance.open('admin') | |
| 1098 self.db.tx_Source = "web" | |
| 1099 self.db.user.create(username='Chef', address='chef@bork.bork.bork', | |
| 1100 realname='Bork, Chef', roles='User') | |
| 1101 self.db.user.create(username='mary', address='mary@test.test', | |
| 1102 roles='User', realname='Contrary, Mary') | |
| 1103 self.db.post_init() | |
| 1104 | |
| 1105 def tearDown(self): | |
| 1106 self.db.close() | |
| 1107 try: | |
| 1108 shutil.rmtree(self.dirname) | |
| 1109 except OSError, error: | |
| 1110 if error.errno not in (errno.ENOENT, errno.ESRCH): raise | |
| 1111 | |
| 1112 def testTemplateSubdirectory(self): | |
| 1113 # test for templates in subdirectories | |
| 1114 | |
| 1115 # make the directory | |
| 1116 subdir = self.dirname + "/html/subdir" | |
| 1117 os.mkdir(subdir) | |
| 1118 | |
| 1119 # get the client instance The form is needed to initialize, | |
| 1120 # but not used since I call selectTemplate directly. | |
| 1121 t = client.Client(self.instance, "user", | |
| 1122 {'PATH_INFO':'/user', 'REQUEST_METHOD':'POST'}, | |
| 1123 form=makeForm({"@template": "item"})) | |
| 1124 | |
| 1125 # create new file in subdir and a dummy file outside of | |
| 1126 # the tracker's html subdirectory | |
| 1127 shutil.copyfile(self.dirname + "/html/issue.item.html", | |
| 1128 subdir + "/issue.item.html") | |
| 1129 shutil.copyfile(self.dirname + "/html/user.item.html", | |
| 1130 self.dirname + "/user.item.html") | |
| 1131 | |
| 1132 # create link outside the html subdir. This should fail due to | |
| 1133 # path traversal check. | |
| 1134 os.symlink("../../user.item.html", subdir + "/user.item.html") | |
| 1135 # it will be removed and replaced by a later test | |
| 1136 | |
| 1137 # make sure a simple non-subdir template works. | |
| 1138 # user.item.html exists so this works. | |
| 1139 # note that the extension is not included just the basename | |
| 1140 self.assertEqual("user.item", t.selectTemplate("user", "item")) | |
| 1141 | |
| 1142 # there is no html/subdir/user.item.{,xml,html} so it will | |
| 1143 # raise NoTemplate. | |
| 1144 self.assertRaises(NoTemplate, | |
| 1145 t.selectTemplate, "user", "subdir/item") | |
| 1146 | |
| 1147 # there is an html/subdir/issue.item.html so this succeeeds | |
| 1148 r = t.selectTemplate("issue", "subdir/item") | |
| 1149 self.assertEqual("subdir/issue.item", r) | |
| 1150 | |
| 1151 # there is a self.directory + /html/subdir/user.item.html file, | |
| 1152 # but it is a link to self.dir /user.item.html which is outside | |
| 1153 # the html subdir so is rejected by the path traversal check. | |
| 1154 self.assertRaises(NoTemplate, | |
| 1155 t.selectTemplate, "user", "subdir/item") | |
| 1156 | |
| 1157 # clear out the link and create a new one to self.dirname + | |
| 1158 # html/user.item.html which is inside the html subdir | |
| 1159 # so the template check returns the symbolic link path. | |
| 1160 os.remove(subdir + "/user.item.html") | |
| 1161 os.symlink("../user.item.html", subdir + "/user.item.xml") | |
| 1162 | |
| 1163 # template check works | |
| 1164 r = t.selectTemplate("user", "subdir/item") | |
| 1165 self.assertEquals("subdir/user.item", r) | |
| 1166 | |
| 1088 # vim: set filetype=python sts=4 sw=4 et si : | 1167 # vim: set filetype=python sts=4 sw=4 et si : |
