Commit 1d8ab2ba by source_reader

updated to new security framework

parent 7a9b3fa5
......@@ -2,7 +2,7 @@ source 'https://rubygems.org'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '5.2.2'
gem 'rails', '5.2.3'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
......
GEM
remote: https://rubygems.org/
specs:
actioncable (5.2.2)
actionpack (= 5.2.2)
actioncable (5.2.3)
actionpack (= 5.2.3)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailer (5.2.2)
actionpack (= 5.2.2)
actionview (= 5.2.2)
activejob (= 5.2.2)
actionmailer (5.2.3)
actionpack (= 5.2.3)
actionview (= 5.2.3)
activejob (= 5.2.3)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
actionpack (5.2.2)
actionview (= 5.2.2)
activesupport (= 5.2.2)
actionpack (5.2.3)
actionview (= 5.2.3)
activesupport (= 5.2.3)
rack (~> 2.0)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (5.2.2)
activesupport (= 5.2.2)
actionview (5.2.3)
activesupport (= 5.2.3)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
activejob (5.2.2)
activesupport (= 5.2.2)
activejob (5.2.3)
activesupport (= 5.2.3)
globalid (>= 0.3.6)
activemodel (5.2.2)
activesupport (= 5.2.2)
activerecord (5.2.2)
activemodel (= 5.2.2)
activesupport (= 5.2.2)
activemodel (5.2.3)
activesupport (= 5.2.3)
activerecord (5.2.3)
activemodel (= 5.2.3)
activesupport (= 5.2.3)
arel (>= 9.0)
activestorage (5.2.2)
actionpack (= 5.2.2)
activerecord (= 5.2.2)
activestorage (5.2.3)
actionpack (= 5.2.3)
activerecord (= 5.2.3)
marcel (~> 0.3.1)
activesupport (5.2.2)
activesupport (5.2.3)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
......@@ -81,7 +81,7 @@ GEM
regexp_parser (~> 1.2)
xpath (~> 3.2)
coderay (1.1.2)
concurrent-ruby (1.1.3)
concurrent-ruby (1.1.5)
crack (0.4.3)
safe_yaml (~> 1.0.0)
crass (1.0.4)
......@@ -123,7 +123,7 @@ GEM
rails (>= 4.2.0, < 6)
diff-lcs (1.3)
docile (1.3.1)
erubi (1.7.1)
erubi (1.8.0)
eventmachine (1.2.7)
eventmachine (1.2.7-x64-mingw32)
execjs (2.7.0)
......@@ -138,7 +138,7 @@ GEM
ffi (1.9.25-x64-mingw32)
formatador (0.2.5)
gherkin (5.1.0)
globalid (0.4.1)
globalid (0.4.2)
activesupport (>= 4.2.0)
guard (2.15.0)
formatador (>= 0.2.4)
......@@ -162,7 +162,7 @@ GEM
httparty (0.16.3)
mime-types (~> 3.0)
multi_xml (>= 0.5.2)
i18n (1.2.0)
i18n (1.6.0)
concurrent-ruby (~> 1.0)
jaro_winkler (1.5.1)
jbuilder (2.8.0)
......@@ -189,10 +189,10 @@ GEM
mime-types (3.2.2)
mime-types-data (~> 3.2015)
mime-types-data (3.2018.0812)
mimemagic (0.3.2)
mimemagic (0.3.3)
mini_magick (4.9.2)
mini_mime (1.0.1)
mini_portile2 (2.3.0)
mini_portile2 (2.4.0)
minitest (5.11.3)
msgpack (1.2.4)
msgpack (1.2.4-x64-mingw32)
......@@ -204,10 +204,10 @@ GEM
net-ssh (>= 2.6.5)
net-ssh (5.0.2)
nio4r (2.3.1)
nokogiri (1.8.5)
mini_portile2 (~> 2.3.0)
nokogiri (1.8.5-x64-mingw32)
mini_portile2 (~> 2.3.0)
nokogiri (1.10.3)
mini_portile2 (~> 2.4.0)
nokogiri (1.10.3-x64-mingw32)
mini_portile2 (~> 2.4.0)
notiffany (0.1.1)
nenv (~> 0.1)
shellany (~> 0.0)
......@@ -226,31 +226,31 @@ GEM
coderay (~> 1.1.0)
method_source (~> 0.9.0)
public_suffix (3.0.3)
rack (2.0.6)
rack (2.0.7)
rack-cors (1.0.2)
rack-test (1.1.0)
rack (>= 1.0, < 3)
rails (5.2.2)
actioncable (= 5.2.2)
actionmailer (= 5.2.2)
actionpack (= 5.2.2)
actionview (= 5.2.2)
activejob (= 5.2.2)
activemodel (= 5.2.2)
activerecord (= 5.2.2)
activestorage (= 5.2.2)
activesupport (= 5.2.2)
rails (5.2.3)
actioncable (= 5.2.3)
actionmailer (= 5.2.3)
actionpack (= 5.2.3)
actionview (= 5.2.3)
activejob (= 5.2.3)
activemodel (= 5.2.3)
activerecord (= 5.2.3)
activestorage (= 5.2.3)
activesupport (= 5.2.3)
bundler (>= 1.3.0)
railties (= 5.2.2)
railties (= 5.2.3)
sprockets-rails (>= 2.0.0)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.0.4)
loofah (~> 2.2, >= 2.2.2)
railties (5.2.2)
actionpack (= 5.2.2)
activesupport (= 5.2.2)
railties (5.2.3)
actionpack (= 5.2.3)
activesupport (= 5.2.3)
method_source
rake (>= 0.8.7)
thor (>= 0.19.0, < 2.0)
......@@ -400,7 +400,7 @@ DEPENDENCIES
omniauth
pg
rack-cors
rails (= 5.2.2)
rails (= 5.2.3)
rspec-json_expectations
rspec-rails (~> 3.1)
rubocop
......
module Joule
class Adapter
def initialize(url)
@backend = Backend.new(url)
def initialize(url, key)
@backend = Backend.new(url, key)
end
def refresh(nilm)
......
......@@ -9,8 +9,12 @@ module Joule
attr_reader :url
def initialize(url)
def initialize(url, key)
@url = url
self.class.default_options[:headers] = {'X-API-KEY': key}
self.class.default_options[:verify] = false
# TODO handle SSL configuration
end
def dbinfo
......
......@@ -4,31 +4,12 @@ class NodeAdapterFactory
open_timeout 5
read_timeout 5
def self.from_url(url)
begin
resp = get(url)
return nil unless resp.success?
info = resp.parsed_response
rescue
return nil
end
if info.include? 'NilmDB'
return Nilmdb::Adapter.new(url)
elsif info.include? 'Joule'
return Joule::Adapter.new(url)
else
return nil
end
end
def self.from_nilm(nilm)
if nilm.node_type=='nilmdb'
return Nilmdb::Adapter.new(nilm.url)
elsif nilm.node_type=='joule'
return Joule::Adapter.new(nilm.url)
else
# try to figure out what this nilm is
return self.from_url(nilm.url)
return Joule::Adapter.new(nilm.url, nilm.key)
end
return nil
end
end
\ No newline at end of file
......@@ -2,12 +2,11 @@
# controller for NILM objects
class NilmsController < ApplicationController
before_action :authenticate_user!
before_action :authenticate_user!, except: [:create]
before_action :set_nilm, only: [:update, :show, :refresh, :destroy]
before_action :authorize_viewer, only: [:show]
before_action :authorize_owner, only: [:update, :refresh]
before_action :authorize_admin, only: [:destroy]
before_action :create_adapter_from_url, only: [:create]
before_action :create_adapter_from_nilm, only: [:show]
# GET /nilms.json
......@@ -31,14 +30,21 @@ class NilmsController < ApplicationController
# POST /nilms.json
def create
@service = CreateNilm.new(@node_adapter)
@service.run(name: nilm_params[:name],
url: nilm_params[:url],
description: nilm_params[:description],
owner: current_user)
if User.count == 0
# If there are no users then create a user from the parameters
@service = AddNilmByUser.new
else
# Otherwise an auth_key is required to identify the user
@service = AddNilmByKey.new
end
@service.run(params, request.remote_ip)
if @service.success?
@nilm = @service.nilm
@role = 'owner'
render :show, status: @service.success? ? :ok : :unprocessable_entity
render plain: "ok"
else
render plain: @service.errors.join(", "), status: :unprocessable_entity
end
end
# PATCH/PUT /nilms/1
......@@ -98,15 +104,6 @@ class NilmsController < ApplicationController
head :unauthorized unless current_user.views_nilm?(@nilm)
end
def create_adapter_from_url
@node_adapter = NodeAdapterFactory.from_url(nilm_params[:url])
if @node_adapter.nil?
@service = StubService.new
@service.add_error("Cannot contact installation")
render 'helpers/empty_response', status: :unprocessable_entity
end
end
def create_adapter_from_nilm
@node_adapter = NodeAdapterFactory.from_nilm(@nilm)
if @node_adapter.nil?
......
......@@ -10,6 +10,19 @@ class UsersController < ApplicationController
# note: update is handled by devise
# POST /users/auth_token.json
def auth_token
# To receive an auth token a user must be a current admin or there
# are no NILM's associated with this node
nilms = current_user.retrieve_nilms_by_permission
head :unauthorized and return if (nilms[:admin].empty? and Nilm.count > 0)
auth_key = NilmAuthKey.find_by_user_id(current_user.id)
if auth_key.nil?
auth_key = NilmAuthKey.create(user: current_user)
end
render json: {key: auth_key.key}
end
# POST /users.json
def create
@service = StubService.new
......
# frozen_string_literal: true
# NILM object
class NilmAuthKey < ApplicationRecord
#---Associations-----
belongs_to :user
after_initialize do |auth_key|
auth_key.key ||= SecureRandom.hex(3).upcase
end
end
......@@ -11,6 +11,7 @@ class User < ActiveRecord::Base
has_many :memberships
has_many :user_groups, through: :memberships
has_many :data_views
has_one :nilm_auth_key
belongs_to :home_data_view, class_name: "DataView",
foreign_key: "home_data_view_id", dependent: :destroy
......
# frozen_string_literal: true
require 'uri'
require 'resolv'
class AddNilmByKey
include ServiceStatus
attr_reader :nilm
def run(request_params, remote_ip)
required_keys =
[:port, :scheme, :name, :api_key, :auth_key]
joule_params = request_params.permit(required_keys+[:name_is_host])
begin
required_keys.each{|key| joule_params.require(key)}
rescue ActionController::ParameterMissing => e
add_error(e.message)
return self
end
#1 Find the requestor
auth_key = NilmAuthKey.find_by_key(joule_params[:auth_key])
if auth_key.nil?
add_error("invalid authorization key")
return self
end
#2 Figure out the remote URL (resolve IP address to domain name for SSL)
if joule_params[:name_is_host].nil?
host = remote_ip
else
host = joule_params[:name]
end
url = URI("http://temp")
url.host = host
url.port = joule_params[:port]
url.scheme = joule_params[:scheme]
puts "using url #{url}"
#3 Create the Nilm
adapter = Joule::Adapter.new(url, joule_params[:api_key])
service = CreateNilm.new(adapter)
absorb_status(service.run(name: joule_params[:name], url:url,
key: joule_params[:api_key],
owner: auth_key.user))
auth_key.destroy if service.success?
@nilm = service.nilm
self
end
end
# frozen_string_literal: true
require 'uri'
require 'resolv'
class AddNilmByUser
include ServiceStatus
attr_reader :nilm
def run(request_params, remote_ip)
# Request Params is a hash with the following keys:
# User: [first_name, last_name, email, password]
# Nilm: [port, scheme, name, api_key]
#0 make sure parameters are present
required_keys =
[:port, :scheme, :name, :api_key] +
[:first_name, :last_name, :email, :password]
request_params = request_params.permit(required_keys+[:name_is_host])
begin
required_keys.each{|key| request_params.require(key)}
rescue ActionController::ParameterMissing => e
add_error(e.message)
return self
end
#1 Create a new user
owner = User.new(request_params.slice(:first_name, :last_name, :email, :password))
unless owner.save
add_errors(owner.errors.full_messages)
return self
end
#2 Figure out the remote URL (resolve IP address to domain name for SSL)
if request_params[:name_is_host].nil?
host = remote_ip
else
host = request_params[:name]
end
url = URI("http://temp")
url.host = host
url.port = request_params[:port]
url.scheme = request_params[:scheme]
#3 Create the Nilm
adapter = Joule::Adapter.new(url, request_params[:api_key])
service = CreateNilm.new(adapter)
absorb_status(service.run(name: request_params[:name], url:url,
key: request_params[:api_key],
owner: owner))
# remove the user if the NILM couldn't be created
owner.destroy if service.errors?
@nilm = service.nilm
self
end
end
......@@ -10,11 +10,12 @@ class CreateNilm
@node_adapter = node_adapter
end
def run(name:, url:, owner:, description:'')
def run(name:, url:, owner:, key:'', description:'')
# note: url should be NilmDB url
@nilm = Nilm.new(name: name,
description: description,
url: url,
key: key,
node_type: @node_adapter.node_type)
unless @nilm.valid?
add_errors(@nilm.errors.full_messages)
......
......@@ -32,7 +32,11 @@ Rails.application.routes.draw do
devise_for :users, path: "auth", only: [:invitations],
controllers: { invitations: 'invitations' }
resources :users, only: [:index, :create, :destroy]
resources :users, only: [:index, :create, :destroy] do
collection do
post 'auth_token'
end
end
resources :user_groups, only: [:index, :update, :create, :destroy] do
member do
put 'create_member'
......
class AddApiKeyToNilm < ActiveRecord::Migration[5.2]
def change
add_column :nilms, :key, :string
create_table "nilm_auth_keys", :force => true do |t|
t.integer "user_id"
t.string "key"
t.timestamps
end
end
end
......@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2018_08_18_012410) do
ActiveRecord::Schema.define(version: 2019_05_05_175223) do
create_table "data_views", force: :cascade do |t|
t.integer "user_id"
......@@ -166,6 +166,13 @@ ActiveRecord::Schema.define(version: 2018_08_18_012410) do
t.index ["user_id"], name: "index_memberships_on_user_id"
end
create_table "nilm_auth_keys", force: :cascade do |t|
t.integer "user_id"
t.string "key"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "nilms", force: :cascade do |t|
t.string "name"
t.string "description"
......@@ -173,6 +180,7 @@ ActiveRecord::Schema.define(version: 2018_08_18_012410) do
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "node_type"
t.string "key"
end
create_table "permissions", force: :cascade do |t|
......
......@@ -5,8 +5,9 @@ require 'rails_helper'
describe Joule::Backend do
# use the benchtop server joule API
let (:url) {'http://nuc:8088'}
let (:key) {'api_key'}
it 'retrieves database schema', :vcr do
backend = Joule::Backend.new(url)
backend = Joule::Backend.new(url, key)
schema = backend.db_schema
# make sure keys are symbolized
expect(schema).to include(:name, :id, :streams, :children)
......@@ -14,14 +15,14 @@ describe Joule::Backend do
expect(schema[:children][0]).to include(:name, :id, :streams, :children)
end
it 'retrieves module schema', :vcr do
backend = Joule::Backend.new(url)
backend = Joule::Backend.new(url, key)
backend.module_schemas.each do |m|
expect(m).to include(:name, :inputs, :outputs)
end
end
it 'loads raw data', :vcr do
backend = Joule::Backend.new(url)
backend = Joule::Backend.new(url, key)
resp = backend.load_data(6,
1531248642561047,
1531248642581047,
......@@ -33,7 +34,7 @@ describe Joule::Backend do
end
it 'loads decimated data', :vcr do
backend = Joule::Backend.new(url)
backend = Joule::Backend.new(url, key)
resp = backend.load_data(6,
1531248642561047,
1531330705273202,
......
......@@ -6,17 +6,7 @@ describe NodeAdapterFactory do
# use the NUC office server
let (:nilmdb_url) {'http://nuc/nilmdb'}
let (:joule_url) {'http://nuc:8088'}
it 'creates_adapter_from_url', :vcr do
adapter = NodeAdapterFactory.from_url(nilmdb_url)
expect(adapter.node_type).to eq('nilmdb')
adapter = NodeAdapterFactory.from_url(joule_url)
expect(adapter.node_type).to eq('joule')
end
it 'returns nil with invalid url', :vcr do
%w(http://www.google.com invalid_url).each do |url|
expect(NodeAdapterFactory.from_url(url)).to be_nil
end
end
it 'creates_adapter_from_nilm' do
nilm = create(:nilm, node_type: 'nilmdb')
adapter = NodeAdapterFactory.from_nilm(nilm)
......@@ -27,10 +17,4 @@ describe NodeAdapterFactory do
expect(adapter.node_type).to eq('joule')
end
it 'falls_back_to_url_when_node_type_is_invalid', :vcr do
nilm = create(:nilm, url: joule_url)
nilm.node_type='invalid'
adapter = NodeAdapterFactory.from_nilm(nilm)
expect(adapter.node_type).to eq('joule')
end
end
\ No newline at end of file
......@@ -167,49 +167,97 @@ RSpec.describe NilmsController, type: :request do
end
describe 'POST create' do
context 'with authenticated user' do
context 'for first user' do
it 'creates a NILM' do
result = StubService.new
result.add_error("cannot contact database")
@mock_adapter = instance_double(Nilmdb::Adapter,
node_type: 'nilmdb',
refresh: result)
allow(NodeAdapterFactory).to receive(:from_url).and_return(@mock_adapter)
@auth_headers = john.create_new_auth_token
user_params = {email: "bob@email.com", password: "password",
first_name: "Bob", last_name: "Test"}
nilm_params = {name: "Test Node", api_key: "api_key", port: 8088, scheme: "http"}
post "/nilms.json",
params: {name: 'new', url: 'http://sampleurl/nilmdb'},
headers: @auth_headers
params: user_params.merge(nilm_params)
expect(response).to have_http_status(:ok)
#should have a warning that NILM cannot see database
expect(response).to have_warning_message
# make sure the NILM was built
nilm = Nilm.find_by_name('new')
nilm = Nilm.find_by_name('Test Node')
expect(nilm).to_not be nil
expect(@mock_adapter).to have_received(:refresh)
# user should be an admin
expect(john.admins_nilm?(nilm)).to be true
owner = User.find_by_email("bob@email.com")
expect(owner.admins_nilm?(nilm)).to be true
end
it 'returns errors on invalid request' do
# name must be unique
create(:nilm, url: 'http://can/only/be/one')
@auth_headers = john.create_new_auth_token
# all user parameters must be present
user_params = {email: "bob@email.com", password: "password",
first_name: "Bob"}
nilm_params = {name: "Test Node", api_key: "api_key", port: 8088, scheme: "http"}
post "/nilms.json",
params: {name: 'CanOnlyBeOne', url: 'http://can/only/be/one'},
headers: @auth_headers
params: user_params.merge(nilm_params)
expect(response).to have_http_status(:unprocessable_entity)
expect(response).to have_error_message
# make sure the NILM was not built
expect(Nilm.where(url: 'http://can/only/be/one').count).to eq 1
expect(Nilm.count).to eq 0
expect(User.count).to eq 0
end
end
context 'without sign-in' do
it 'returns unauthorized' do
context 'for existing users' do
it 'creates a NILM' do
owner = create(:user)
NilmAuthKey.create(user: owner, key: "valid_key")
user_params = {auth_key: "valid_key"}
nilm_params = {name: "Test Node", api_key: "api_key", port: 8088, scheme: "http"}
post "/nilms.json",
params: {name: 'new', url: 'http://sampleurl/nilmdb'}
expect(response).to have_http_status(:unauthorized)
params: user_params.merge(nilm_params)
expect(response).to have_http_status(:ok)
#should have a warning that NILM cannot see database
expect(response).to have_warning_message
# make sure the NILM was built
nilm = Nilm.find_by_name('Test Node')
expect(nilm).to_not be nil
# user should be an admin
expect(owner.admins_nilm?(nilm)).to be true
# auth key should be destroyed
expect(NilmAuthKey.count).to eq 0
end
it 'requires auth key' do
create(:user)
user_params = {email: "bob@email.com", password: "password",
first_name: "Bob", last_name: "Test"}
nilm_params = {name: "Test Node", api_key: "api_key", port: 8088, scheme: "http"}
post "/nilms.json",
params: user_params.merge(nilm_params)
expect(response).to have_http_status(:unprocessable_entity)
expect(response).to have_error_message /auth_key/
# make sure the NILM was not built
expect(Nilm.count).to eq 0
expect(User.count).to eq 1
expect(User.find_by_email("bob@email.com")).to be nil
end
it 'requires valid auth key' do
create(:user)
user_params = {auth_key: "invalid"}
nilm_params = {name: "Test Node", api_key: "api_key", port: 8088, scheme: "http"}
post "/nilms.json",
params: user_params.merge(nilm_params)
expect(response).to have_http_status(:unprocessable_entity)
expect(response).to have_error_message /authorization/
# make sure the NILM was not built
expect(Nilm.count).to eq 0
expect(User.count).to eq 1
end
it 'returns error on invalid request' do
owner = create(:user)
NilmAuthKey.create(user: owner, key: "valid_key")
user_params = {auth_key: "valid_key"}
nilm_params = {name: "Missing port param", api_key: "api_key", scheme: "http"}
post "/nilms.json",
params: user_params.merge(nilm_params)
expect(response).to have_http_status(:unprocessable_entity)
expect(response).to have_error_message
# make sure the NILM was not built
expect(Nilm.count).to eq 0
# user still exists and has an auth key
expect(User.count).to eq 1
expect(NilmAuthKey.count).to eq 1
end
end
end
......
......@@ -27,4 +27,44 @@ RSpec.describe UsersController, type: :request do
end
end
end
describe 'POST auth_token' do
context 'with authenticated admin' do
it 'creates an auth_key if none exist' do
create(:nilm, admins: [john])
@auth_headers = john.create_new_auth_token
post "/users/auth_token.json", headers: @auth_headers
body = JSON.parse(response.body)
expect(body['key']).to eq(john.nilm_auth_key.key)
end
it 'returns existing auth key' do
create(:nilm, admins: [john])
auth_key = NilmAuthKey.create(user: john)
@auth_headers = john.create_new_auth_token
post "/users/auth_token.json", headers: @auth_headers
body = JSON.parse(response.body)
expect(body['key']).to eq(auth_key.key)
end
end
context 'with authenticated non-admin' do
it 'returns unauthorized if nilms exist' do
create(:nilm)
@auth_headers = john.create_new_auth_token
post "/users/auth_token.json", headers: @auth_headers
expect(response.status).to eq(401)
end
it 'returns auth key if no nilms exist' do
@auth_headers = john.create_new_auth_token
post "/users/auth_token.json", headers: @auth_headers
body = JSON.parse(response.body)
expect(body['key']).to eq(john.nilm_auth_key.key)
end
end
context 'without sign-in' do
it 'returns unauthorized' do
post "/users/auth_token.json"
expect(response.status).to eq(401)
end
end
end
end
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'AddNilmByKey' do
describe 'run' do
it 'creates nilm owned by the specified user' do
owner = create(:user)
key = NilmAuthKey.new(key: "random_key", user: owner)
key.save!
user_params = {auth_key: "random_key"}
nilm_params = {name: "Test Node", api_key: "api_key", port: 8088, scheme: "http"}
request_params = ActionController::Parameters.new(user_params.merge(nilm_params))
service = AddNilmByKey.new
service.run(request_params,"127.0.0.1")
expect(service.success?).to be true
# creates the nilm
nilm = service.nilm
expect(nilm.url).to eq "http://localhost:8088"
expect(nilm.name).to eq "Test Node"
expect(nilm.key).to eq "api_key"
# owner is an admin for the nilm
expect(owner.admins_nilm?(nilm)).to be true
# forwards warnings (can't contact made up installation)
expect(service.warnings?).to be true
# destroys the auth key
expect(NilmAuthKey.count).to eq 0
end
it 'requires valid auth key' do
service = AddNilmByKey.new
user_params = {auth_key: "invalid"}
nilm_params = {name: "Test Node", api_key: "api_key", port: 8088, scheme: "http"}
request_params = ActionController::Parameters.new(user_params.merge(nilm_params))
service.run(request_params,"127.0.0.1")
expect(service.success?).to be false
# forwards error messages
expect(service.errors[0]).to match("invalid authorization key")
# does not create the nilm
expect(Nilm.count).to eq 0
end
it 'forwards nilm errors' do
nilm = create(:nilm)
nilm.url = "http://localhost:8088"
nilm.save!
owner = create(:user)
key = NilmAuthKey.new(key: "random_key", user: owner)
key.save!
user_params = {auth_key: "random_key"}
nilm_params = {name: "Test Node", api_key: "api_key", port: 8088, scheme: "http"}
request_params = ActionController::Parameters.new(user_params.merge(nilm_params))
service = AddNilmByKey.new
service.run(request_params,"127.0.0.1")
# NILM already exists with the specified URL
expect(service.success?).to be false
# no new NILM created
expect(Nilm.count).to eq 1
# owner doesn't get permissions on the existing nilm
expect(owner.admins_nilm?(nilm)).to be false
# auth key is not deleted
expect(NilmAuthKey.count).to eq 1
end
end
end
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe 'AddNilmByUser' do
describe 'run' do
it 'creates a user and an associated nilm' do
service = AddNilmByUser.new
user_params = {email: "bob@email.com", password: "password",
first_name: "Bob", last_name: "Test"}
nilm_params = {name: "Test Node", api_key: "api_key", port: 8088, scheme: "http"}
request_params = ActionController::Parameters.new(user_params.merge(nilm_params))
service.run(request_params,"127.0.0.1")
expect(service.success?).to be true
# creates the nilm
nilm = service.nilm
expect(nilm.url).to eq "http://localhost:8088"
expect(nilm.name).to eq "Test Node"
expect(nilm.key).to eq "api_key"
# creates the user associated with the nilm
owner = User.find_by_email("bob@email.com")
expect(owner.admins_nilm?(nilm)).to be true
# forwards warnings (can't contact made up installation)
expect(service.warnings?).to be true
end
it 'requires all parameters' do
service = AddNilmByUser.new
user_params = {password: "missing_email",
first_name: "Bob", last_name: "Test"}
nilm_params = {name: "Test Node", api_key: "api_key", port: 8088, scheme: "http"}
request_params = ActionController::Parameters.new(user_params.merge(nilm_params))
service.run(request_params,"127.0.0.1")
expect(service.success?).to be false
u = User.new(user_params)
u.valid?
# forwards error messages
expect(service.errors[0]).to match /email/
# does not create the nilm
expect(Nilm.count).to eq 0
end
it 'requires valid user parameters' do
service = AddNilmByUser.new
user_params = {email: "bob@email.com", password: "short",
first_name: "Bob", last_name: "Test"}
nilm_params = {name: "Test Node", api_key: "api_key", port: 8088, scheme: "http"}
request_params = ActionController::Parameters.new(user_params.merge(nilm_params))
service.run(request_params,"127.0.0.1")
expect(service.success?).to be false
u = User.new(user_params)
u.valid?
# forwards error messages
expect(service.errors).to eq(u.errors.full_messages)
# does not create the nilm
expect(Nilm.count).to eq 0
end
it 'forwards nilm errors' do
nilm = create(:nilm)
nilm.url = "http://localhost:8088"
nilm.save!
service = AddNilmByUser.new
user_params = {email: "bob@email.com", password: "password",
first_name: "Bob", last_name: "Test"}
nilm_params = {name: "Test Node", api_key: "api_key", port: 8088, scheme: "http"}
request_params = ActionController::Parameters.new(user_params.merge(nilm_params))
service.run(request_params,"127.0.0.1")
# NILM already exists with the specified URL
expect(service.success?).to be false
# no new NILM created
expect(Nilm.count).to eq 1
# new user is not created
expect(User.find_by_email("bob@email.com")).to be nil
end
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment