Commit a67b6dd3 by John Doe

added controller endpoints and services for adding and removing group members

parent ff791f4b
# frozen_string_literal: true
class UserGroupsController < ApplicationController
before_action :authenticate_user!
before_action :set_user_group, only: [:update, :destroy]
before_action :authentiate_group_admin, only: [:update, :destroy]
before_action :set_user_group,
only: [:update,
:remove_member,
:add_member,
:destroy]
before_action :authorize_group_admin,
only: [:update,
:remove_member,
:add_member,
:destroy]
# GET /user_groups.json
def index
@owned_groups = UserGroup.where(owner: current_user)
@member_groups = current_user.user_groups
my_groups = @member_groups+@owned_groups
my_groups = @member_groups + @owned_groups
@other_groups = UserGroup.where.not(id: my_groups.pluck(:id))
end
# POST /user_groups.json
def create
@user_group = UserGroup.new(user_group_params)
# TODO
end
# PATCH/PUT /user_groups/1/add_member.json
def add_member
@service = AddGroupMember.new
@service.run(@user_group, params[:user_id])
render :show, status: @service.success? ? :ok : :unprocessable_entity
end
if @user_group.save
render :show, status: :created, location: @user_group
else
render json: @user_group.errors, status: :unprocessable_entity
end
# PATCH/PUT /user_groups/1/remove_member.json
def remove_member
@service = RemoveGroupMember.new
@service.run(@user_group, params[:user_id])
render :show, status: @service.success? ? :ok : :unprocessable_entity
end
# PATCH/PUT /user_groups/1
# PATCH/PUT /user_groups/1.json
def update
if @user_group.update(user_group_params)
render :show, status: :ok, location: @user_group
else
render json: @user_group.errors, status: :unprocessable_entity
end
# TODO
end
# DELETE /user_groups/1
# DELETE /user_groups/1.json
def destroy
@user_group.destroy
# TODO
end
private
# Use callbacks to share common setup or constraints between actions.
def set_user_group
@user_group = UserGroup.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_group_params
params.permit(:name, :description)
end
def authorize_group_admin
head :unauthorized unless @user_group.owner==current_user
end
# Use callbacks to share common setup or constraints between actions.
def set_user_group
@user_group = UserGroup.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def user_group_params
params.permit(:name, :description)
end
def authorize_group_admin
head :unauthorized unless @user_group.owner == current_user
end
end
......@@ -12,10 +12,9 @@ class Nilm < ApplicationRecord
#---Validations-----
validates :name, presence: true
# def as_json(_options = {})
# nilm = super(except: [:created_at, :updated_at])
# nilm[:available] = db.available
# nilm[:db] = db.as_json()
# nilm
# end
def self.json_keys
[:id, :name, :description, :url]
end
end
......@@ -48,14 +48,14 @@ class User < ActiveRecord::Base
allowed_nilms = []
roles.each do |role|
#first get NILM's explicitly related to this user
user_nilms = self.nilms.where(permissions:{role: role})
user_nilms = self.nilms.where(permissions:{role: role}).includes(:db)
allowed_nilms+= user_nilms.pluck(:id)
#add NILM's related through a user_group
User.joins(:user_groups, :permissions, :nilms)
user_groups = self.user_groups
group_nilms = Nilm.joins(permissions: :user_group).where(permissions:{role: role}).
where(user_groups: {id: user_groups.pluck(:id)})
where(user_groups: {id: user_groups.pluck(:id)}).includes(:db)
if(not allowed_nilms.empty?)
group_nilms = group_nilms.where("nilms.id NOT IN (?)", allowed_nilms)
end
......
# frozen_string_literal: true
# Handles adding users to a group
class AddGroupMember
include ServiceStatus
attr_reader :user_group
def run(user_group, user_id)
# add user specified by [user_id] to the group
@user_group = user_group
user = User.find_by_id(user_id)
if user.nil?
add_error("invalid user_id")
return self
end
if( user==@user_group.owner ||
@user_group.users.include?(user))
add_error("user is already a member of this group")
return self
end
# ok, this user is new to the group, add them
@user_group.users << user
set_notice("added user to group")
self
end
end
# frozen_string_literal: true
# Handles removing users from a group
class RemoveGroupMember
include ServiceStatus
attr_reader :user_group
def run(user_group, user_id)
# remove user specified by [user_id] from the group
@user_group = user_group
user = User.find_by_id(user_id)
if user.nil?
add_error("invalid user_id")
return self
end
if( user==@user_group.owner )
add_error("cannot remove the group owner")
return self
end
if( not @user_group.users.include?(user))
add_error("user is not a member of this group")
return self
end
# ok, this user is a member of the group, remove them
@user_group.users.delete(user)
set_notice("removed user from group")
self
end
end
json.extract! nilm, :id, :name, :description, :url
json.extract! nilm, *Nilm.json_keys
json.db_id nilm.db.id
json.available nilm.db.available
json.admin do
json.array! @nilms[:admin], partial: 'nilms/nilm', as: :nilm
# frozen_string_literal: true
json.admin @nilms[:admin] do |nilm|
json.extract! nilm, *Nilm.json_keys
json.db_id nilm.db.id
json.available nilm.db.available
end
json.owner do
json.array! @nilms[:owner], partial: 'nilms/nilm', as: :nilm
json.owner @nilms[:owner] do |nilm|
json.extract! nilm, *Nilm.json_keys
json.db_id nilm.db.id
json.available nilm.db.available
end
json.viewer do
json.array! @nilms[:viewer], partial: 'nilms/nilm', as: :nilm
json.viewer @nilms[:viewer] do |nilm|
json.extract! nilm, *Nilm.json_keys
json.db_id nilm.db.id
json.available nilm.db.available
end
json.data do
json.extract! @user_group, *UserGroup.json_keys
if(@user_group.owner==current_user)
json.members @user_group.users do |user|
json.extract! user, *User.json_keys
end
end
end
json.partial! "helpers/messages", service: @service
......@@ -13,7 +13,7 @@ module ControlPanel
# -- all .rb files in that directory are automatically loaded.
config.api_only = true
# Add folders under the services and adapters directory
%w(nilm db db_folder db_stream permission).each do |service|
%w(nilm db db_folder db_stream permission user_group).each do |service|
config.autoload_paths << Rails.root.join("app/services/#{service}")
end
config.autoload_paths << Rails.root.join("app/adapters")
......
......@@ -7,6 +7,11 @@ Rails.application.routes.draw do
mount_devise_token_auth_for 'User', at: 'auth'
resources :users, only: [:index, :create, :destroy]
resources :user_groups, only: [:index, :create, :destroy]
resources :user_groups, only: [:index, :create, :destroy] do
member do
put 'add_member'
put 'remove_member'
end
end
resources :permissions, only: [:index, :create, :destroy]
end
......@@ -2,17 +2,27 @@
require 'rails_helper'
RSpec.describe UserGroupsController, type: :request do
let(:grp1) { create(:user_group, name: 'Group1') }
let(:grp2) { create(:user_group, name: 'Group2') }
let(:donnals) { create(:user_group, name: 'Donnals',
owner: john, members: [nicky])}
let(:john) { create(:user, first_name: 'Jonh') }
let(:nicky) { create(:user, first_name: 'Nicky')}
let(:steve) { create(:user, first_name: 'Steve')}
let(:owner) { create(:user) }
let(:member1) { create(:user) }
let(:member2) { create(:user) }
let(:other_user) { create(:user) }
let(:group) do
create(:user_group,
owner: owner,
members: [member1, member2])
end
describe 'GET index' do
let(:grp1) { create(:user_group, name: 'Group1') }
let(:grp2) { create(:user_group, name: 'Group2') }
let(:donnals) { create(:user_group, name: 'Donnals',
owner: john, members: [nicky])}
let(:john) { create(:confirmed_user, first_name: 'Jonh') }
let(:nicky) { create(:confirmed_user, first_name: 'Nicky')}
let(:steve) { create(:confirmed_user, first_name: 'Steve')}
before do
john.confirm
# force lazy evaluation of let to build groups
grp1; grp2; donnals;
end
......@@ -58,4 +68,89 @@ RSpec.describe UserGroupsController, type: :request do
end
end
end
describe 'PUT add_member' do
context 'with owner' do
it 'adds a member' do
@auth_headers = owner.create_new_auth_token
put "/user_groups/#{group.id}/add_member.json",
params: { user_id: other_user.id},
headers: @auth_headers
expect(response.status).to eq(200)
expect(group.reload.users.include?(other_user)).to be true
expect(response).to have_notice_message
#check to make sure JSON renders the members
body = JSON.parse(response.body)
expect(body['data']['members'].count).to eq group.users.count
end
it 'returns error on invalid request' do
@auth_headers = owner.create_new_auth_token
# member1 is already a member
put "/user_groups/#{group.id}/add_member.json",
params: { user_id: member1.id},
headers: @auth_headers
expect(response).to have_http_status(:unprocessable_entity)
expect(response).to have_error_message
end
end
context 'with anyone else' do
it 'returns unauthorized' do
@auth_headers = member1.create_new_auth_token
put "/user_groups/#{group.id}/add_member.json",
params: { user_id: other_user.id},
headers: @auth_headers
expect(response).to have_http_status(:unauthorized)
end
end
context 'without sign-in' do
it 'returns unauthorized' do
put "/user_groups/#{group.id}/add_member.json",
params: { user_id: other_user.id}
expect(response).to have_http_status(:unauthorized)
end
end
end
describe 'PUT remove_member' do
context 'with owner' do
it 'removes a member' do
@auth_headers = owner.create_new_auth_token
put "/user_groups/#{group.id}/remove_member.json",
params: { user_id: member1.id},
headers: @auth_headers
expect(response.status).to eq(200)
expect(group.reload.users.include?(member1)).to be false
expect(response).to have_notice_message
#check to make sure JSON renders the members
body = JSON.parse(response.body)
expect(body['data']['members'].count).to eq group.users.count
end
it 'returns error on invalid request' do
@auth_headers = owner.create_new_auth_token
# other_user is not a member
put "/user_groups/#{group.id}/remove_member.json",
params: { user_id: other_user.id},
headers: @auth_headers
expect(response).to have_http_status(:unprocessable_entity)
expect(response).to have_error_message
end
end
context 'with anyone else' do
it 'returns unauthorized' do
@auth_headers = member1.create_new_auth_token
put "/user_groups/#{group.id}/remove_member.json",
params: { user_id: member2.id},
headers: @auth_headers
expect(response).to have_http_status(:unauthorized)
end
end
context 'without sign-in' do
it 'returns unauthorized' do
put "/user_groups/#{group.id}/remove_member.json",
params: { user_id: other_user.id}
expect(response).to have_http_status(:unauthorized)
end
end
end
end
# frozen_string_literal: true
require 'rails_helper'
describe 'AddGroupMember service' do
let(:owner) { create(:user) }
let(:member1) { create(:user) }
let(:member2) { create(:user) }
let(:other_user) { create(:user) }
let(:group) do
create(:user_group,
owner: owner,
members: [member1, member2])
end
it 'adds specified user' do
service = AddGroupMember.new
service.run(group, other_user.id)
expect(service.success?).to be true
expect(group.users.count).to eq(3)
expect(group.users.include?(other_user)).to be(true)
end
it 'errors if user is the owner' do
service = AddGroupMember.new
service.run(group, owner.id)
expect(service.success?).to be false
expect(group.reload.owner).to eq owner
end
it 'errors if user is already a member' do
service = AddGroupMember.new
service.run(group, member1.id)
expect(service.success?).to be false
end
it 'errors if user_id is invalid' do
service = AddGroupMember.new
service.run(group, 99) # bad user id
expect(service.success?).to be false
end
end
# frozen_string_literal: true
require 'rails_helper'
describe 'RemoveGroupMember service' do
let(:owner) { create(:user) }
let(:member1) { create(:user) }
let(:member2) { create(:user) }
let(:other_user) { create(:user) }
let(:group) do
create(:user_group,
owner: owner,
members: [member1, member2])
end
it 'removes specified user' do
service = RemoveGroupMember.new
service.run(group, member1.id)
expect(service.success?).to be true
expect(group.users.count).to eq(1)
expect(group.users.include?(member1)).to be(false)
end
it 'errors if user is the owner' do
service = RemoveGroupMember.new
service.run(group, owner.id)
expect(service.success?).to be false
expect(group.reload.owner).to eq owner
end
it 'errors if user is not a member' do
service = RemoveGroupMember.new
service.run(group, other_user.id)
expect(service.success?).to be false
end
it 'errors if user_id is invalid' do
service = RemoveGroupMember.new
service.run(group, 99) # bad user id
expect(service.success?).to be false
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