ip_blocks_spec.rb 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. # frozen_string_literal: true
  2. require 'rails_helper'
  3. RSpec.describe 'IP Blocks' do
  4. let(:role) { UserRole.find_by(name: 'Admin') }
  5. let(:user) { Fabricate(:user, role: role) }
  6. let(:token) { Fabricate(:accessible_access_token, resource_owner_id: user.id, scopes: scopes) }
  7. let(:scopes) { 'admin:read:ip_blocks admin:write:ip_blocks' }
  8. let(:headers) { { 'Authorization' => "Bearer #{token.token}" } }
  9. describe 'GET /api/v1/admin/ip_blocks' do
  10. subject do
  11. get '/api/v1/admin/ip_blocks', headers: headers, params: params
  12. end
  13. let(:params) { {} }
  14. it_behaves_like 'forbidden for wrong scope', 'admin:write:ip_blocks'
  15. it_behaves_like 'forbidden for wrong role', ''
  16. it_behaves_like 'forbidden for wrong role', 'Moderator'
  17. it 'returns http success' do
  18. subject
  19. expect(response).to have_http_status(200)
  20. end
  21. context 'when there is no ip block' do
  22. it 'returns an empty body' do
  23. subject
  24. expect(body_as_json).to be_empty
  25. end
  26. end
  27. context 'when there are ip blocks' do
  28. let!(:ip_blocks) do
  29. [
  30. IpBlock.create(ip: '192.0.2.0/24', severity: :no_access),
  31. IpBlock.create(ip: '172.16.0.1', severity: :sign_up_requires_approval, comment: 'Spam'),
  32. IpBlock.create(ip: '2001:0db8::/32', severity: :sign_up_block, expires_in: 10.days),
  33. ]
  34. end
  35. let(:expected_response) do
  36. ip_blocks.map do |ip_block|
  37. {
  38. id: ip_block.id.to_s,
  39. ip: ip_block.ip,
  40. severity: ip_block.severity.to_s,
  41. comment: ip_block.comment,
  42. created_at: ip_block.created_at.strftime('%Y-%m-%dT%H:%M:%S.%LZ'),
  43. expires_at: ip_block.expires_at&.strftime('%Y-%m-%dT%H:%M:%S.%LZ'),
  44. }
  45. end
  46. end
  47. it 'returns the correct blocked ips' do
  48. subject
  49. expect(body_as_json).to match_array(expected_response)
  50. end
  51. context 'with limit param' do
  52. let(:params) { { limit: 2 } }
  53. it 'returns only the requested number of ip blocks' do
  54. subject
  55. expect(body_as_json.size).to eq(params[:limit])
  56. end
  57. end
  58. end
  59. end
  60. describe 'GET /api/v1/admin/ip_blocks/:id' do
  61. subject do
  62. get "/api/v1/admin/ip_blocks/#{ip_block.id}", headers: headers
  63. end
  64. let!(:ip_block) { IpBlock.create(ip: '192.0.2.0/24', severity: :no_access) }
  65. it_behaves_like 'forbidden for wrong scope', 'admin:write:ip_blocks'
  66. it_behaves_like 'forbidden for wrong role', ''
  67. it_behaves_like 'forbidden for wrong role', 'Moderator'
  68. it 'returns the correct ip block', :aggregate_failures do
  69. subject
  70. expect(response).to have_http_status(200)
  71. json = body_as_json
  72. expect(json[:ip]).to eq("#{ip_block.ip}/#{ip_block.ip.prefix}")
  73. expect(json[:severity]).to eq(ip_block.severity.to_s)
  74. end
  75. context 'when ip block does not exist' do
  76. it 'returns http not found' do
  77. get '/api/v1/admin/ip_blocks/-1', headers: headers
  78. expect(response).to have_http_status(404)
  79. end
  80. end
  81. end
  82. describe 'POST /api/v1/admin/ip_blocks' do
  83. subject do
  84. post '/api/v1/admin/ip_blocks', headers: headers, params: params
  85. end
  86. let(:params) { { ip: '151.0.32.55', severity: 'no_access', comment: 'Spam' } }
  87. it_behaves_like 'forbidden for wrong scope', 'admin:read:ip_blocks'
  88. it_behaves_like 'forbidden for wrong role', ''
  89. it_behaves_like 'forbidden for wrong role', 'Moderator'
  90. it 'returns the correct ip block', :aggregate_failures do
  91. subject
  92. expect(response).to have_http_status(200)
  93. json = body_as_json
  94. expect(json[:ip]).to eq("#{params[:ip]}/32")
  95. expect(json[:severity]).to eq(params[:severity])
  96. expect(json[:comment]).to eq(params[:comment])
  97. end
  98. context 'when the required ip param is not provided' do
  99. let(:params) { { ip: '', severity: 'no_access' } }
  100. it 'returns http unprocessable entity' do
  101. subject
  102. expect(response).to have_http_status(422)
  103. end
  104. end
  105. context 'when the required severity param is not provided' do
  106. let(:params) { { ip: '173.65.23.1', severity: '' } }
  107. it 'returns http unprocessable entity' do
  108. subject
  109. expect(response).to have_http_status(422)
  110. end
  111. end
  112. context 'when the given ip address is already blocked' do
  113. before do
  114. IpBlock.create(params)
  115. end
  116. it 'returns http unprocessable entity' do
  117. subject
  118. expect(response).to have_http_status(422)
  119. end
  120. end
  121. context 'when the given ip address is invalid' do
  122. let(:params) { { ip: '520.13.54.120', severity: 'no_access' } }
  123. it 'returns http unprocessable entity' do
  124. subject
  125. expect(response).to have_http_status(422)
  126. end
  127. end
  128. end
  129. describe 'PUT /api/v1/admin/ip_blocks/:id' do
  130. subject do
  131. put "/api/v1/admin/ip_blocks/#{ip_block.id}", headers: headers, params: params
  132. end
  133. let!(:ip_block) { IpBlock.create(ip: '185.200.13.3', severity: 'no_access', comment: 'Spam', expires_in: 48.hours) }
  134. let(:params) { { severity: 'sign_up_requires_approval', comment: 'Decreasing severity' } }
  135. it 'returns the correct ip block', :aggregate_failures do
  136. expect { subject }
  137. .to change_severity_level
  138. .and change_comment_value
  139. expect(response).to have_http_status(200)
  140. expect(body_as_json).to match(hash_including({
  141. ip: "#{ip_block.ip}/#{ip_block.ip.prefix}",
  142. severity: 'sign_up_requires_approval',
  143. comment: 'Decreasing severity',
  144. }))
  145. end
  146. def change_severity_level
  147. change { ip_block.reload.severity }.from('no_access').to('sign_up_requires_approval')
  148. end
  149. def change_comment_value
  150. change { ip_block.reload.comment }.from('Spam').to('Decreasing severity')
  151. end
  152. context 'when ip block does not exist' do
  153. it 'returns http not found' do
  154. put '/api/v1/admin/ip_blocks/-1', headers: headers, params: params
  155. expect(response).to have_http_status(404)
  156. end
  157. end
  158. end
  159. describe 'DELETE /api/v1/admin/ip_blocks/:id' do
  160. subject do
  161. delete "/api/v1/admin/ip_blocks/#{ip_block.id}", headers: headers
  162. end
  163. let!(:ip_block) { IpBlock.create(ip: '185.200.13.3', severity: 'no_access') }
  164. it 'deletes the ip block', :aggregate_failures do
  165. subject
  166. expect(response).to have_http_status(200)
  167. expect(body_as_json).to be_empty
  168. expect(IpBlock.find_by(id: ip_block.id)).to be_nil
  169. end
  170. context 'when ip block does not exist' do
  171. it 'returns http not found' do
  172. delete '/api/v1/admin/ip_blocks/-1', headers: headers
  173. expect(response).to have_http_status(404)
  174. end
  175. end
  176. end
  177. end