| 1067 |
1067 |
issue = Issue.find(1)
|
| 1068 |
1068 |
assert_include attachment, issue.attachments
|
| 1069 |
1069 |
end
|
|
1070 |
|
|
1071 |
# ==========================================================================
|
|
1072 |
# API Authorization Tests for Private/Public Projects
|
|
1073 |
#
|
|
1074 |
# These tests verify that Redmine's authorization system correctly handles:
|
|
1075 |
# 1. Private projects - only members and admins can access
|
|
1076 |
# 2. Public projects - Non member/Anonymous roles control access
|
|
1077 |
#
|
|
1078 |
# Default permissions in a fresh Redmine installation:
|
|
1079 |
# Non member: :view_issues, :add_issues, :add_issue_notes (NO :edit_issues)
|
|
1080 |
# Anonymous: :view_issues only
|
|
1081 |
# ==========================================================================
|
|
1082 |
|
|
1083 |
# --- Private Project Tests ---
|
|
1084 |
# Private projects should deny access to non-members regardless of role permissions
|
|
1085 |
|
|
1086 |
test "POST /issues.json should not allow non-member to create issue on private project" do
|
|
1087 |
project = Project.find(2) # onlinestore - private project
|
|
1088 |
user = User.find(3) # dlopper - member of project 1, NOT project 2
|
|
1089 |
|
|
1090 |
assert_not project.is_public?
|
|
1091 |
assert_nil Member.find_by(project_id: project.id, user_id: user.id)
|
|
1092 |
|
|
1093 |
assert_no_difference('Issue.count') do
|
|
1094 |
post(
|
|
1095 |
'/issues.json',
|
|
1096 |
:params => {:issue => {:project_id => project.id, :tracker_id => 1, :subject => 'Unauthorized issue'}},
|
|
1097 |
:headers => {'X-Redmine-API-Key' => user.api_key})
|
|
1098 |
end
|
|
1099 |
|
|
1100 |
assert_includes [401, 403, 422], response.status
|
|
1101 |
end
|
|
1102 |
|
|
1103 |
test "PUT /issues/:id.json should not allow non-member to update issue on private project" do
|
|
1104 |
issue = Issue.find(4) # belongs to Project 2 (private)
|
|
1105 |
user = User.find(3) # dlopper - NOT a member of Project 2
|
|
1106 |
|
|
1107 |
assert_not issue.project.is_public?
|
|
1108 |
assert_nil Member.find_by(project_id: issue.project_id, user_id: user.id)
|
|
1109 |
|
|
1110 |
original_subject = issue.subject
|
|
1111 |
|
|
1112 |
put(
|
|
1113 |
"/issues/#{issue.id}.json",
|
|
1114 |
:params => {:issue => {:subject => 'Hacked subject'}},
|
|
1115 |
:headers => {'X-Redmine-API-Key' => user.api_key})
|
|
1116 |
|
|
1117 |
assert_includes [401, 403, 404], response.status
|
|
1118 |
|
|
1119 |
issue.reload
|
|
1120 |
assert_equal original_subject, issue.subject
|
|
1121 |
end
|
|
1122 |
|
|
1123 |
test "POST /issues.json should allow admin to create issue on private project even as non-member" do
|
|
1124 |
project = Project.find(2)
|
|
1125 |
user = User.find(1) # admin
|
|
1126 |
|
|
1127 |
assert user.admin?
|
|
1128 |
assert_not project.is_public?
|
|
1129 |
assert_nil Member.find_by(project_id: project.id, user_id: user.id)
|
|
1130 |
|
|
1131 |
assert_difference('Issue.count', 1) do
|
|
1132 |
post(
|
|
1133 |
'/issues.json',
|
|
1134 |
:params => {:issue => {:project_id => project.id, :tracker_id => 1, :subject => 'Admin created issue'}},
|
|
1135 |
:headers => credentials('admin'))
|
|
1136 |
end
|
|
1137 |
|
|
1138 |
assert_response :created
|
|
1139 |
end
|
|
1140 |
|
|
1141 |
test "PUT /issues/:id.json should allow admin to update issue on private project even as non-member" do
|
|
1142 |
issue = Issue.find(4)
|
|
1143 |
user = User.find(1) # admin
|
|
1144 |
|
|
1145 |
assert user.admin?
|
|
1146 |
assert_not issue.project.is_public?
|
|
1147 |
assert_nil Member.find_by(project_id: issue.project_id, user_id: user.id)
|
|
1148 |
|
|
1149 |
put(
|
|
1150 |
"/issues/#{issue.id}.json",
|
|
1151 |
:params => {:issue => {:subject => 'Admin updated subject'}},
|
|
1152 |
:headers => credentials('admin'))
|
|
1153 |
|
|
1154 |
assert_response :no_content
|
|
1155 |
|
|
1156 |
issue.reload
|
|
1157 |
assert_equal 'Admin updated subject', issue.subject
|
|
1158 |
end
|
|
1159 |
|
|
1160 |
# --- Public Project Tests ---
|
|
1161 |
# Public projects respect Non member/Anonymous role permissions
|
|
1162 |
|
|
1163 |
test "POST /issues.json should allow non-member to create issue on public project when Non member role has add_issues permission" do
|
|
1164 |
project = Project.find(1) # ecookbook - public project
|
|
1165 |
user = User.find(4) # rhill - NOT a member of any project
|
|
1166 |
|
|
1167 |
assert project.is_public?
|
|
1168 |
assert_nil Member.find_by(project_id: project.id, user_id: user.id)
|
|
1169 |
assert Role.non_member.has_permission?(:add_issues)
|
|
1170 |
|
|
1171 |
assert_difference('Issue.count', 1) do
|
|
1172 |
post(
|
|
1173 |
'/issues.json',
|
|
1174 |
:params => {:issue => {:project_id => project.id, :tracker_id => 1, :subject => 'Non-member created issue'}},
|
|
1175 |
:headers => {'X-Redmine-API-Key' => user.api_key})
|
|
1176 |
end
|
|
1177 |
|
|
1178 |
assert_response :created
|
|
1179 |
end
|
|
1180 |
|
|
1181 |
test "PUT /issues/:id.json should not allow non-member to update issue on public project when Non member role lacks edit_issues permission" do
|
|
1182 |
# This tests the DEFAULT Redmine behavior where Non member has :add_issues but NOT :edit_issues
|
|
1183 |
issue = Issue.find(1)
|
|
1184 |
user = User.find(4)
|
|
1185 |
|
|
1186 |
Role.non_member.remove_permission!(:edit_issues)
|
|
1187 |
Role.non_member.remove_permission!(:add_issue_notes)
|
|
1188 |
|
|
1189 |
assert issue.project.is_public?
|
|
1190 |
assert_nil Member.find_by(project_id: issue.project_id, user_id: user.id)
|
|
1191 |
assert_not Role.non_member.has_permission?(:edit_issues)
|
|
1192 |
|
|
1193 |
original_subject = issue.subject
|
|
1194 |
|
|
1195 |
put(
|
|
1196 |
"/issues/#{issue.id}.json",
|
|
1197 |
:params => {:issue => {:subject => 'Should fail'}},
|
|
1198 |
:headers => {'X-Redmine-API-Key' => user.api_key})
|
|
1199 |
|
|
1200 |
assert_includes [401, 403], response.status
|
|
1201 |
|
|
1202 |
issue.reload
|
|
1203 |
assert_equal original_subject, issue.subject
|
|
1204 |
ensure
|
|
1205 |
Role.non_member.add_permission!(:edit_issues)
|
|
1206 |
Role.non_member.add_permission!(:add_issue_notes)
|
|
1207 |
end
|
|
1208 |
|
|
1209 |
test "POST /issues.json should not allow anonymous to create issue on public project by default" do
|
|
1210 |
# Default Anonymous role lacks :add_issues permission
|
|
1211 |
project = Project.find(1)
|
|
1212 |
|
|
1213 |
assert project.is_public?
|
|
1214 |
assert_not Role.anonymous.has_permission?(:add_issues)
|
|
1215 |
|
|
1216 |
assert_no_difference('Issue.count') do
|
|
1217 |
post(
|
|
1218 |
'/issues.json',
|
|
1219 |
:params => {:issue => {:project_id => project.id, :tracker_id => 1, :subject => 'Should fail'}})
|
|
1220 |
end
|
|
1221 |
|
|
1222 |
assert_includes [401, 403, 422], response.status
|
|
1223 |
end
|
|
1224 |
|
|
1225 |
test "PUT /issues/:id.json should not allow anonymous to update issue on public project by default" do
|
|
1226 |
# Default Anonymous role lacks :edit_issues permission
|
|
1227 |
issue = Issue.find(1)
|
|
1228 |
|
|
1229 |
Role.anonymous.remove_permission!(:add_issue_notes)
|
|
1230 |
|
|
1231 |
assert issue.project.is_public?
|
|
1232 |
assert_not Role.anonymous.has_permission?(:edit_issues)
|
|
1233 |
|
|
1234 |
original_subject = issue.subject
|
|
1235 |
|
|
1236 |
put(
|
|
1237 |
"/issues/#{issue.id}.json",
|
|
1238 |
:params => {:issue => {:subject => 'Should fail'}})
|
|
1239 |
|
|
1240 |
assert_includes [401, 403], response.status
|
|
1241 |
|
|
1242 |
issue.reload
|
|
1243 |
assert_equal original_subject, issue.subject
|
|
1244 |
ensure
|
|
1245 |
Role.anonymous.add_permission!(:add_issue_notes)
|
|
1246 |
end
|
|
1247 |
|
|
1248 |
test "PUT /issues/:id.json should not modify attributes when user only has add_issue_notes permission" do
|
|
1249 |
# User can access update action (to add notes) but attribute changes should be ignored
|
|
1250 |
issue = Issue.find(1)
|
|
1251 |
user = User.find(4)
|
|
1252 |
|
|
1253 |
Role.non_member.remove_permission!(:edit_issues)
|
|
1254 |
|
|
1255 |
assert issue.project.is_public?
|
|
1256 |
assert_not Role.non_member.has_permission?(:edit_issues)
|
|
1257 |
assert Role.non_member.has_permission?(:add_issue_notes)
|
|
1258 |
|
|
1259 |
original_subject = issue.subject
|
|
1260 |
|
|
1261 |
put(
|
|
1262 |
"/issues/#{issue.id}.json",
|
|
1263 |
:params => {:issue => {:subject => 'Should be ignored', :notes => 'Adding a note'}},
|
|
1264 |
:headers => {'X-Redmine-API-Key' => user.api_key})
|
|
1265 |
|
|
1266 |
assert_response :no_content
|
|
1267 |
|
|
1268 |
issue.reload
|
|
1269 |
assert_equal original_subject, issue.subject
|
|
1270 |
ensure
|
|
1271 |
Role.non_member.add_permission!(:edit_issues)
|
|
1272 |
end
|
| 1070 |
1273 |
end
|