# frozen_string_literal: true require 'rails_helper' RSpec.describe 'Clients', type: :request do let!(:admin_client) { create(:admin) } let!(:public_client) { create(:public) } let!(:read_client) { create(:read) } let!(:write_client) { create(:write) } let!(:clients) { create_list(:client, 20) } let(:random_client) { clients[Faker::Number.between(from: 0, to: clients.length - 1)] } let(:valid_client) do { name: 'clientA', description: 'Client across the river', permission: 'rw', public_ip: false } end let(:valid_client_update) do { name: 'clientA', permission: 'w', public_ip: true } end let(:random_client_update) do { name: random_client.name, description: 'updated description', public_ip: !random_client.public_ip # swap boolean } end let(:admin_perm_update) do { name: admin_client.name, public_ip: !admin_client.public_ip, # swap boolean permission: 'rw' } end let(:invalid_client_update) { { names: 'clientA' } } let(:non_existing_client) { 'DOES_NOT_EXIST_123546' } # admin describe 'POST /admin/client' do context 'when sending a valid update request' do before { post '/admin/client', params: valid_client, headers: api_key_header(admin_client) } it 'updates client from rw to w and returns 200' do api_key = json_response['api_key'] post '/admin/client', params: valid_client_update, headers: api_key_header(admin_client) expect(json_response).not_to be_empty expect(json_response['api_key'].length).to eq 82 expect(json_response['api_key'].length).not_to eq api_key expect(response).to have_http_status(200) api_key = json_response['api_key'] client_name = json_response['name'] # check if request was parsed properly get "/admin/clients/#{client_name}", headers: api_key_header(admin_client) expect(json_response).not_to be_empty expect(json_response['name']).to eq valid_client[:name] expect(json_response['description']).to eq valid_client[:description] expect(json_response['permission']).to eq valid_client_update[:permission] expect(json_response['public_ip']).to eq valid_client_update[:public_ip] expect(response).to have_http_status(200) # test the new api_key write put '/client', headers: api_key_header(nil, api_key) expect(json_response).not_to be_empty expect(response).to have_http_status(200) # test the new api_key read get "/clients/#{client_name}", headers: api_key_header(nil, api_key) expect(response.body).to be_empty expect(response).to have_http_status(403) end end context 'when sending a valid request' do before { post '/admin/client', params: valid_client, headers: api_key_header(admin_client) } it 'creates client that can read/write and returns 201' do expect(json_response).not_to be_empty expect(json_response['name']).to eq valid_client[:name] expect(json_response['api_key'].length).to eq 82 expect(response).to have_http_status(201) api_key = json_response['api_key'] # check if request was parsed properly get "/admin/clients/#{valid_client[:name]}", headers: api_key_header(admin_client) expect(json_response).not_to be_empty expect(json_response['name']).to eq valid_client[:name] expect(json_response['description']).to eq valid_client[:description] expect(json_response['permission']).to eq valid_client[:permission] expect(json_response['public_ip']).to eq valid_client[:public_ip] expect(response).to have_http_status(200) # test the new client write put '/client', headers: api_key_header(nil, api_key) expect(json_response).not_to be_empty expect(response).to have_http_status(200) ipv4 = json_response['ipv4'] # test the new client read get "/clients/#{valid_client[:name]}", headers: api_key_header(nil, api_key) expect(json_response).not_to be_empty expect(response).to have_http_status(200) expect(json_response['ipv4']).to eq ipv4 end end context 'when sending a valid request without api_key' do let!(:client_count) { Client.count } before { post '/admin/client', params: valid_client } it 'does not create client and returns status code 401' do expect(client_count).to eq Client.count expect(response.body).to be_empty expect(response).to have_http_status(401) end end context 'when sending a valid request with non admin api_key' do let!(:client_count) { Client.count } before { post '/admin/client', params: valid_client, headers: api_key_header(read_client) } it 'does not create client and returns status code 403' do expect(client_count).to eq Client.count expect(response.body).to be_empty expect(response).to have_http_status(403) end end context 'when sending an invalid request' do let!(:client_count) { Client.count } before { post '/admin/client', params: invalid_client_update, headers: api_key_header(admin_client) } it 'does not create client and returns status code 405' do expect(client_count).to eq Client.count expect(response.body).to be_empty expect(response).to have_http_status(405) end end context 'when sending a valid update request to remove last admin permission' do before { post '/admin/client', params: admin_perm_update, headers: api_key_header(admin_client) } it 'does not update admin and returns status code 406' do expect(admin_client.reload.perm_x).to eq true expect(response.body).to be_empty expect(response).to have_http_status(406) end end context 'when sending a valid update request to remove non last admin permission' do before do post '/admin/client', params: { name: 'admin2', permission: 'x' }, headers: api_key_header(admin_client) post '/admin/client', params: admin_perm_update, headers: api_key_header(admin_client) end it 'does update admin and returns status code 200' do expect(admin_client.reload.perm_x).to eq false expect(response.body).not_to be_empty expect(response).to have_http_status(200) end end context 'when sending a valid request to add another client above the MAX_CLIENTS limit' do before do clients_to_create = RynDNS::Application::MAX_CLIENTS - Client.count create_list(:client, clients_to_create) post '/admin/client', params: { name: 'extra_user' }, headers: api_key_header(admin_client) end it 'does not add another client and returns status code 429' do expect(Client.count).to eq RynDNS::Application::MAX_CLIENTS expect(response.body).to be_empty expect(response).to have_http_status(429) end end end describe 'PUT /admin/client' do context 'when sending a valid request' do before do put '/admin/client', params: random_client_update, headers: api_key_header(admin_client) random_client.reload end it 'updates client and returns 200' do expect(random_client.description).to eq random_client_update[:description] expect(random_client.public_ip).to eq random_client_update[:public_ip] expect(response.body).to be_empty expect(response).to have_http_status(200) end end context 'when sending a valid request without api_key' do before do put '/admin/client', params: random_client_update random_client.reload end it 'does not update client and returns 401' do expect(random_client.description).not_to eq random_client_update[:description] expect(random_client.public_ip).not_to eq random_client_update[:public_ip] expect(response.body).to be_empty expect(response).to have_http_status(401) end end context 'when sending a valid request with non admin api_key' do before do put '/admin/client', params: random_client_update, headers: api_key_header(write_client) random_client.reload end it 'does not update client and returns 403' do expect(random_client.description).not_to eq random_client_update[:description] expect(random_client.public_ip).not_to eq random_client_update[:public_ip] expect(response.body).to be_empty expect(response).to have_http_status(403) end end context 'when sending a valid request for non existing client' do before do random_client_update[:name] = non_existing_client put '/admin/client', params: random_client_update, headers: api_key_header(admin_client) random_client.reload end it 'does not update client and returns 404' do expect(random_client.description).not_to eq random_client_update[:description] expect(random_client.public_ip).not_to eq random_client_update[:public_ip] expect(response.body).to be_empty expect(response).to have_http_status(404) end end context 'when sending an invalid valid request' do before { put '/admin/client', params: invalid_client_update, headers: api_key_header(admin_client) } it 'returns 405' do expect(response.body).to be_empty expect(response).to have_http_status(405) end end context 'when sending a valid valid request to remove last admin permission' do before do put '/admin/client', params: admin_perm_update, headers: api_key_header(admin_client) admin_client.reload end it 'does not update admin and returns 406' do expect(admin_client.perm_x).to eq true expect(admin_client.public_ip).to_not eq admin_perm_update[:public_ip] expect(response.body).to be_empty expect(response).to have_http_status(406) end end context 'when sending a valid update request to remove non last admin permission' do before do put '/admin/client', params: { name: random_client.name, permission: 'x' }, headers: api_key_header(admin_client) put '/admin/client', params: admin_perm_update, headers: api_key_header(admin_client) end it 'does update admin and returns status code 200' do expect(admin_client.reload.perm_x).to eq false expect(response.body).to be_empty expect(response).to have_http_status(200) end end end describe 'GET /admin/clients' do context 'when requesting all clients' do before { get '/admin/clients', headers: api_key_header(admin_client) } it 'returns list of all clients and status code 200' do expect(list_equals_db?(json_response)).to eq true expect(response).to have_http_status(200) end end context 'when requesting all clients with no api_key' do before { get '/admin/clients' } it 'returns status code 401' do expect(response.body).to be_empty expect(response).to have_http_status(401) end end context 'when requesting all clients with write api_key' do before { get '/admin/clients', headers: api_key_header(write_client) } it 'returns status code 403' do expect(response.body).to be_empty expect(response).to have_http_status(403) end end context 'when requesting all clients with read api_key' do before { get '/admin/clients', headers: api_key_header(read_client) } it 'returns status code 403' do expect(response.body).to be_empty expect(response).to have_http_status(403) end end end describe 'GET /admin/clients/:name' do context 'when requesting random_client.name client with admin api_key' do before { get "/admin/clients/#{random_client.name}", headers: api_key_header(admin_client) } it 'returns info and status code 200' do expect(json_response['name']).to eq random_client.name expect(json_response['description']).to eq random_client.description expect(json_response['permission']).to eq parse_permission(random_client.perm_r, random_client.perm_w, random_client.perm_x) expect(json_response['public_ip']).to eq random_client.public_ip expect(json_response['ipv4']).to eq random_client.ipv4 expect(response).to have_http_status(200) end end context 'when requesting random client with no api_key' do before { get "/admin/clients/#{random_client.name}" } it 'returns status code 401' do expect(response.body).to be_empty expect(response).to have_http_status(401) end end context 'when requesting random client with write api_key' do before { get "/admin/clients/#{random_client.name}", headers: api_key_header(write_client) } it 'returns status code 403' do expect(response.body).to be_empty expect(response).to have_http_status(403) end end context 'when requesting random client with read api_key' do before { get "/admin/clients/#{random_client.name}", headers: api_key_header(read_client) } it 'returns status code 403' do expect(response.body).to be_empty expect(response).to have_http_status(403) end end context 'when requesting non existing client' do before { get "/admin/clients/#{non_existing_client}", headers: api_key_header(admin_client) } it 'returns status code 404' do expect(response.body).to be_empty expect(response).to have_http_status(404) end end end describe 'DELETE /admin/clients/:name' do context 'when sending a valid request' do let!(:client_count) { Client.count - 1 } before { delete "/admin/clients/#{random_client.name}", headers: api_key_header(admin_client) } it 'deletes client and returns 200' do expect(Client.find_by(name: random_client.name)).to eq nil expect(Client.count).to eq client_count expect(response.body).to be_empty expect(response).to have_http_status(200) end end context 'when sending a valid request without api_key' do let!(:client_count) { Client.count } before { delete "/admin/clients/#{random_client.name}" } it 'does not delete client and returns 401' do expect(Client.find_by(name: random_client.name)).to eq random_client expect(Client.count).to eq client_count expect(response.body).to be_empty expect(response).to have_http_status(401) end end context 'when sending a valid request with non admin api_key' do let!(:client_count) { Client.count } before { delete "/admin/clients/#{random_client.name}", headers: api_key_header(read_client) } it 'does not delete client and returns 403' do expect(Client.find_by(name: random_client.name)).to eq random_client expect(Client.count).to eq client_count expect(response.body).to be_empty expect(response).to have_http_status(403) end end context 'when sending a valid request for non existing client' do let!(:client_count) { Client.count } before { delete "/admin/clients/#{non_existing_client}", headers: api_key_header(admin_client) } it 'does not delete client and returns 404' do expect(Client.count).to eq client_count expect(response.body).to be_empty expect(response).to have_http_status(404) end end context 'when sending a valid valid request to delete last admin' do let!(:client_count) { Client.count } before { delete "/admin/clients/#{admin_client.name}", headers: api_key_header(admin_client) } it 'does not delete admin and returns 406' do expect(Client.find_by(name: admin_client.name)).to eq admin_client expect(Client.count).to eq client_count expect(response.body).to be_empty expect(response).to have_http_status(406) end end context 'when sending a valid update request to delete non last admin' do let!(:client_count) { Client.count - 1 } before do put '/admin/client', params: { name: random_client.name, permission: 'x' }, headers: api_key_header(admin_client) delete "/admin/clients/#{admin_client.name}", headers: api_key_header(admin_client) end it 'does delete admin and returns status code 200' do expect(Client.find_by(name: admin_client.name)).to eq nil expect(Client.count).to eq client_count expect(response.body).to be_empty expect(response).to have_http_status(200) end end end # client (write) describe 'PUT /client' do context 'when requesting with write api_key' do before { put '/client', headers: api_key_header(write_client) } it 'returns status code 200' do expect(json_response['name']).to eq write_client.name expect(json_response['ipv4']).to eq '127.0.0.1' expect(response).to have_http_status(200) end end context 'when requesting with write api_key and body' do before { put '/client', params: { ipv4: '99.55.66.2' }, headers: api_key_header(write_client) } it 'returns status code 200' do expect(json_response['name']).to eq write_client.name expect(json_response['ipv4']).to eq '99.55.66.2' expect(response).to have_http_status(200) end end context 'when requesting with no api_key' do before { put '/client' } it 'returns status code 401' do expect(response.body).to be_empty expect(response).to have_http_status(401) end end context 'when requesting with read api_key' do before { put '/client', headers: api_key_header(read_client) } it 'returns status code 403' do expect(response.body).to be_empty expect(response).to have_http_status(403) end end context 'when requesting with api_key of non existing client' do before do write_client.delete put '/client', headers: api_key_header(write_client) end it 'returns status code 403' do expect(response.body).to be_empty expect(response).to have_http_status(403) end end end describe 'DELETE /client' do context 'when requesting with write api_key' do before { delete '/client', headers: api_key_header(write_client) } it 'deletes ipv4 value and returns previous value with status code 200' do expect(json_response['name']).to eq write_client.name expect(json_response['ipv4']).to eq write_client.ipv4 expect(response).to have_http_status(200) # check if deletion was successful write_client.reload expect(write_client.ipv4).to eq '' end end context 'when requesting with no api_key' do before { delete '/client' } it 'returns status code 401' do expect(response.body).to be_empty expect(response).to have_http_status(401) end end context 'when requesting with read api_key' do before { delete '/client', headers: api_key_header(read_client) } it 'returns status code 403' do expect(response.body).to be_empty expect(response).to have_http_status(403) end end context 'when requesting with write api_key and invalid ip body' do before { put '/client', params: { ipv4: '5.9.256.66' }, headers: api_key_header(write_client) } it 'returns status code 406' do expect(response.body).to be_empty expect(response).to have_http_status(406) end end end # client (read) describe 'GET /clients/:name' do context 'when requesting write client with read api_key' do before { get "/clients/#{write_client.name}", headers: api_key_header(read_client) } it 'returns status code 200' do expect(json_response['name']).to eq write_client.name expect(json_response['ipv4']).to eq write_client.ipv4 expect(response).to have_http_status(200) end end context 'when requesting write client with no api_key' do before { get "/clients/#{write_client.name}" } it 'returns status code 401' do expect(response.body).to be_empty expect(response).to have_http_status(401) end end context 'request write client with write api_key' do before { get "/clients/#{write_client.name}", headers: api_key_header(write_client) } it 'returns status code 403' do expect(response.body).to be_empty expect(response).to have_http_status(403) end end context 'when requesting non existing client' do before { get "/clients/#{non_existing_client}", headers: api_key_header(read_client) } it 'returns status code 404' do expect(response.body).to be_empty expect(response).to have_http_status(404) end end end # public describe 'GET /public/:name' do context 'request public client' do before { get "/public/#{public_client.name}" } it 'returns status code 200' do expect(json_response['name']).to eq public_client.name expect(json_response['ipv4']).to eq public_client.ipv4 expect(response).to have_http_status(200) end end context 'request non existing client' do before { get "/public/#{non_existing_client}" } it 'returns status code 401' do expect(response.body).to be_empty expect(response).to have_http_status(401) end end context 'request non-public client' do before { get "/public/#{write_client.name}" } it 'returns status code 401' do expect(response.body).to be_empty expect(response).to have_http_status(401) end end end end