Project

General

Profile

Patch #43682 » api_authorization_tests.patch

陽一 宇田, 2026-01-17 16:07

View differences:

test/integration/api_test/issues_test.rb
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
    (1-1/1)