diff --git a/.gitignore b/.gitignore index 37292e7..fe6fe65 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,6 @@ # ignore IDE files .idea/* + +# ignore yard doc files +.yardoc/* \ No newline at end of file diff --git a/Gemfile b/Gemfile index 23909f1..7be2a89 100644 --- a/Gemfile +++ b/Gemfile @@ -92,8 +92,10 @@ gem 'caracal' gem 'caracal-rails' -# TODO where to put it? -gem "i18n-js", ">= 3.0.0.rc11" +# +# INTERNATIONALIZATION +# +gem "i18n-js", ">= 3.0.0.rc11" #damodar added TODO: explain # @@ -109,5 +111,9 @@ # gem 'swagger-docs' -# TODO where to put it? -gem "i18n-js", ">= 3.0.0.rc11" +# +# CODE DOCUMENTATION +# +gem 'yard' +gem 'redcarpet' + diff --git a/Rakefile b/Rakefile index 04c8372..6a2a218 100644 --- a/Rakefile +++ b/Rakefile @@ -6,6 +6,8 @@ DMPonline4::Application.load_tasks +# TODO: destroy rdoc rake task once finished with new documentation + RDoc::Task.new :rdoc do |rdoc| rdoc.main = "README.rdoc" @@ -14,4 +16,5 @@ rdoc.title = "DMPonline4 Documentation" rdoc.options << "--all" -end \ No newline at end of file +end + diff --git a/app/admin/org_token_permission.rb b/app/admin/org_token_permission.rb index 7ccebcb..e335d7f 100644 --- a/app/admin/org_token_permission.rb +++ b/app/admin/org_token_permission.rb @@ -1,7 +1,7 @@ ActiveAdmin.register OrgTokenPermission do permit_params :organisation_id, :token_permission_type_id - menu priority:25, label: proc{ I18n.t('admin.org_token_permission')}, parent: "Api" + menu priority: 40, label: proc{ I18n.t('admin.org_token_permission')}, parent: "Api" index do column I18n.t('admin.org') do |n| diff --git a/app/admin/organisation.rb b/app/admin/organisation.rb index 8b4afbc..2c88380 100644 --- a/app/admin/organisation.rb +++ b/app/admin/organisation.rb @@ -1,15 +1,15 @@ # [+Project:+] DMPonline -# [+Description:+] -# +# [+Description:+] +# # [+Created:+] 03/09/2014 -# [+Copyright:+] Digital Curation Centre +# [+Copyright:+] Digital Curation Centre ActiveAdmin.register Organisation do permit_params :abbreviation, :banner_file_id, :description, :domain, :logo_file_id, :name, :stylesheet_file_id, :target_url, :organisation_type_id, :wayfless_entity, :parent_id - + menu :priority => 14, :label => proc{I18n.t('admin.org')}, :parent => "Organisations management" - index do + index do column I18n.t('admin.org_title'), :sortable => :name do |ggn| link_to ggn.name, [:admin, ggn] end @@ -23,15 +23,16 @@ column I18n.t('admin.org_type'), :sortable => :organisation_type_id do |org_type| if !org_type.organisation_type_id.nil? then link_to org_type.organisation_type.name, [:admin, org_type] - end + end end - + actions end - - + + #show details of an organisation - show do + show do + resource.check_api_credentials attributes_table do row I18n.t('admin.org_title'), :sortable => :name do |gn| if !gn.name.nil? then @@ -45,12 +46,12 @@ '-' end end - row :sort_name + row :sort_name row I18n.t('admin.org_type'), :organisation_type_id do |org_type| if !org_type.organisation_type_id.nil? then link_to org_type.organisation_type.name, [:admin, org_type] - end - end + end + end row :description do |descr| if !descr.description.nil? then descr.description.html_safe @@ -65,18 +66,21 @@ row :logo_file_name row :domain row :wayfless_entity + row I18n.t('admin.token_permission_type') do + (organisation.token_permission_types.map{|tpt| link_to tpt.token_type, [:admin, tpt]}).join(', ').html_safe + end # row I18n.t('admin.org_parent'), :parent_id do |org_parent| # if !org_parent.parent_id.nil? then # parent_org = Organisation.find(org_parent.parent_id) # link_to parent_org.name, [:admin, parent_org] - # end + # end # end # row :stylesheet_file_id row :created_at row :updated_at end - end - + end + #templates sidebar sidebar I18n.t('admin.templates'), :only => :show, :if => proc { organisation.dmptemplates.count >= 1} do table_for organisation.dmptemplates.order("title asc") do |temp| @@ -87,7 +91,7 @@ end end - #form + #form form do |f| f.inputs "Details" do f.input :name @@ -100,18 +104,22 @@ f.input :logo_file_name f.input :domain f.input :wayfless_entity + f.input :token_permission_types, label: I18n.t('admin.token_permission_type'), + as: :select, multiple: true, include_blank: I18n.t('helpers.none'), + collection: TokenPermissionType.order(:token_type).map{|token| [token.token_type, token.id]}, + hint: I18n.t('admin.choose_api_permissions') # f.input :parent_id, :label => I18n.t('admin.org_parent'), :as => :select, :collection => Organisation.find(:all, :order => 'name ASC').map{|orgp|[orgp.name, orgp.id]} # f.input :stylesheet_file_id end - f.actions - end + f.actions + end controller do def permitted_params params.permit! end - end - - + end + + end diff --git a/app/admin/token_permission.rb b/app/admin/token_permission.rb deleted file mode 100644 index ed1bd19..0000000 --- a/app/admin/token_permission.rb +++ /dev/null @@ -1,31 +0,0 @@ -ActiveAdmin.register TokenPermission do - permit_params :api_token, :token_permission_type_id, :user_id - - #TODO: make migration to add user_id to the model so we can have the relationship... - - menu priority:25, label: proc{ I18n.t('admin.token_permission')}, parent: "Api" - - index do - column I18n.t('admin.user') do |n| - link_to n.user.email, [:admin,n] - end - column I18n.t('admin.token_permission') do |n| - link_to n.token_permission_type, [:admin, n] - end - actions - end - - show do - attributes_table do - row :user_id - row :token_permission_type_id - row :api_token - end - end - - controller do - def permitted_params - params.permit! - end - end -end diff --git a/app/admin/token_permission_type.rb b/app/admin/token_permission_type.rb index b3b9d2d..de4aa2d 100644 --- a/app/admin/token_permission_type.rb +++ b/app/admin/token_permission_type.rb @@ -1,10 +1,9 @@ ActiveAdmin.register TokenPermissionType do permit_params :token_type, :text_desription - menu priority: 20, label: proc{ I18n.t('admin.token_permission_type')}, parent: "Api" + menu priority: 40, label: proc{ I18n.t('admin.token_permission_type')}, parent: "Api" # TODO: Find better fix for the undefined method xxx_id_eq - remove_filter :token_permissions remove_filter :org_token_permissions index do diff --git a/app/admin/user.rb b/app/admin/user.rb index 859d8ca..67c5852 100644 --- a/app/admin/user.rb +++ b/app/admin/user.rb @@ -5,7 +5,7 @@ # [+Copyright:+] Digital Curation Centre ActiveAdmin.register User do - permit_params :password_confirmation, :encrypted_password, :remember_me, :id, :email, :firstname, :orcid_id, :shibboleth_id, :user_status_id, :surname, :user_type_id, :organisation_id, :skip_invitation, :other_organisation, :accept_terms, :role_ids, :api_token + permit_params :api_token, :password_confirmation, :encrypted_password, :remember_me, :id, :email, :firstname, :orcid_id, :shibboleth_id, :user_status_id, :surname, :user_type_id, :organisation_id, :skip_invitation, :other_organisation, :accept_terms, :role_ids menu :priority => 15, :label => proc{ I18n.t('admin.user')}, :parent => "User management" @@ -53,10 +53,10 @@ row :orcid_id row I18n.t('admin.org_title'), :organisation_id do |org_title| if !org_title.organisation_id.nil? then - link_to org_title.organisation.name, [:admin, org_title.organisation] - end + link_to org_title.organisation.name, [:admin, org_title.organisation] + end end - row :other_organisation + row :other_organisation # row I18n.t('admin.user_status'), :user_status_id do |us| # if !us.user_status.nil? then # link_to us.user_status.name, [:admin, us.user_status] @@ -87,7 +87,6 @@ f.input :surname f.input :email f.input :orcid_id - f.input :api_token # f.input :shibboleth_id f.input :organisation_id ,:label => I18n.t('admin.org_title'), :as => :select, @@ -104,6 +103,7 @@ :multiple => true, :include_blank => I18n.t('helpers.none'), :collection => Role.order('name').map{|ro| [ro.name, ro.id]} + f.input :api_token end diff --git a/app/controllers/api/v0/base_controller.rb b/app/controllers/api/v0/base_controller.rb index 5d80b5b..020b268 100644 --- a/app/controllers/api/v0/base_controller.rb +++ b/app/controllers/api/v0/base_controller.rb @@ -102,18 +102,22 @@ def authenticate_token authenticate_with_http_token do |token, options| - @token = token - logger.debug "whats the token? #{token}" - @user = User.find_by api_token: token - logger.debug "did we even find a guy? #{@user}" - !@user.nil? + # reject the empty string as it is our base empty token + if !token = "" + @token = token + @user = User.find_by(api_token: token) + # if no user found, return false, otherwise true + !@user.nil? + else + false + end end end def render_bad_credentials self.headers['WWW-Authenticate'] = "Token realm=\"\"" - render json: '"Bad credentials"', status: 401 + render json: I18n.t("api.bad_credentials"), status: 401 end def has_auth (auth_type) diff --git a/app/controllers/api/v0/guidance_groups_controller.rb b/app/controllers/api/v0/guidance_groups_controller.rb index 3eafd8a..f28b642 100644 --- a/app/controllers/api/v0/guidance_groups_controller.rb +++ b/app/controllers/api/v0/guidance_groups_controller.rb @@ -24,13 +24,13 @@ # check if the user has permission to use the guidances api if has_auth("guidance") # determine if they have authorization to view this guidance group - if GuidanceGroup.can_view(@user, params[:id]) + if GuidanceGroup.can_view?(@user, params[:id]) respond_with get_resource else - render json: '"You do not have authorization to view this"', status: 401 + render json: I18n.t("api.bad_resource"), status: 401 end else - render json: '"You do not have authorization to use this api endpoint"', status: 401 + render json: I18n.t("api.no_auth_for_endpoint"), status: 401 end end @@ -49,7 +49,7 @@ respond_with @all_viewable_groups else #render unauthorised - render json: '"You do not have authorization to use this api endpoint"', status: 401 + render json: I18n.t("api.no_auth_for_endpoint"), status: 401 end end diff --git a/app/controllers/api/v0/guidances_controller.rb b/app/controllers/api/v0/guidances_controller.rb index 0f1ff43..2803ea6 100644 --- a/app/controllers/api/v0/guidances_controller.rb +++ b/app/controllers/api/v0/guidances_controller.rb @@ -23,13 +23,13 @@ def show # ensure use has auth for guidances api if has_auth("guidance") - if Guidance.can_view(@user, params[:id]) + if Guidance.can_view?(@user, params[:id]) respond_with get_resource else - render json: '"you do not have authorisation to view this resource"', status: 401 + render json: I18n.t("api.bad_resource"), status: 401 end else - render json: '"You do not have authorisation to use this api endpoint"', status: 401 + render I18n.t("api.no_auth_for_endpoint"), status: 401 end end @@ -45,7 +45,7 @@ @all_viewable_guidances = Guidance.all_viewable(@user) respond_with @all_viewable_guidances else - render json '"You do not have authorisation to view this api endpoint"', status: 401 + render json I18n.t("api.no_auth_for_endpoint"), status: 401 end end diff --git a/app/controllers/api/v0/projects_controller.rb b/app/controllers/api/v0/projects_controller.rb index 35c990b..d9195e6 100644 --- a/app/controllers/api/v0/projects_controller.rb +++ b/app/controllers/api/v0/projects_controller.rb @@ -13,13 +13,16 @@ response :not_found end + ## + # Creates a new project based on the information passed in JSON to the API + def create # find the user's api_token permissions # then ensure that they have the permission associated with creating plans if has_auth "plans" #params[:organization_id] = Organisation.where(name: params[:template][:organization]) # find_by returns nil if none found, find_by! raises an ActiveRecord error - organization = Organisation.find_by name: params[:template][:organization] + organization = Organisation.find_by name: params[:template][:organisation] # if organization exists if !organization.nil? # if organization is funder @@ -34,15 +37,28 @@ dmptemplate = organization.templates.find_by title: params[:template][:name] # else error: organization has more than one template and template name unspecified else - render json: 'error:"Organization has more than one template and template name unspecified or invalid"', status: 400 and return + render json: I18n.t("api.org_multiple_templates"), status: 400 and return end # else error: organization specified is not a funder else - render json: 'error:"Organization specified is not a funder"', status: 400 and return + render json: I18n.t("api.org_not_funder"), status: 400 and return end # else error: organization does not exist else - render json: 'error:"Organization does not exist"', status: 400 and return + render json: I18n.t("api.org_dosent_exist"), status: 400 and return + end + + all_groups = [] + # Check to see if the user specified guidances + if !params[:guidance].nil? + # for each specified guidance, see if it exists + params[:guidance][:name].each do |guidance_name| + group = GuidanceGroup.find_by(name: guidance_name) + # if it exists, add it to the guidances for the new project + if !group.nil? + all_groups = all_groups + [group] + end + end end # cant invite a user without having a current user because of devise :ivitable @@ -63,6 +79,7 @@ @project.slug = params[:project][:title] @project.organisation = @user.organisations.first @project.assign_creator(user.id) + @project.guidance_groups = all_groups # if save successful, render success, otherwise show error if @project.save @@ -72,15 +89,15 @@ render json: get_resource.errors, status: :unprocessable_entity end else - render json: 'error:"You do not have authorisation to view this api endpoint"', status: 400 and return + render json: I18n.t("api.no_auth_for_endpoint"), status: 400 and return end end - private - def project_params - params.require(:template).permit(:organization, :name) - params.require(:project).permit(:title, :email) - end + # private + # def project_params + # params.require(:template).permit(:organisation, :name) + # params.require(:project).permit(:title, :email) + # end end end end diff --git a/app/controllers/organisation_users_controller.rb b/app/controllers/organisation_users_controller.rb index 2ff63c3..4693650 100644 --- a/app/controllers/organisation_users_controller.rb +++ b/app/controllers/organisation_users_controller.rb @@ -1,19 +1,25 @@ class OrganisationUsersController < ApplicationController - - def admin_index - if user_signed_in? && current_user.is_org_admin? then - - respond_to do |format| - format.html # index.html.erb - format.json { render json: @organisation_users } - end - else - render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) - end - end - - - - + def admin_index + if user_signed_in? && current_user.is_org_admin? then + # find excluded user_id's + excluded_ids = params[:user_ids] + excluded_ids.each do |user_id| + User.find(user_id).remove_token + end + # remove their api_tokens + # find included user id's + params[:user_ids].each do |user_id| + User.find(user_id).keep_or_generate_token + end + # keep_or_generate_token + respond_to do |format| + format.html # index.html.erb + format.json { render json: @organisation_users } + end + else + render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) + end + end + end \ No newline at end of file diff --git a/app/controllers/token_permission_types_controller.rb b/app/controllers/token_permission_types_controller.rb new file mode 100644 index 0000000..458ad69 --- /dev/null +++ b/app/controllers/token_permission_types_controller.rb @@ -0,0 +1,15 @@ +class TokenPermissionTypesController < ApplicationController + + + def index + if user_signed_in? && user.organisation.token_permission_types.count > 0 + @user = current_user + respond_to do |format| + format.html + end + else + render(file: File.join(Rails.root, 'public/403.html'),status: 403, layout: false) + end + end + +end \ No newline at end of file diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 3c8039f..8fad4df 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -57,9 +57,7 @@ end end end - - - + # DELETE /users/1 # DELETE /users/1.json @@ -72,4 +70,42 @@ format.json { head :no_content } end end + + def admin_index + if user_signed_in? && current_user.is_org_admin? then + respond_to do |format| + format.html # index.html.erb + format.json { render json: @organisation_users } + end + else + render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) + end + end + + def admin_api_update + if user_signed_in? && current_user.is_org_admin? then + #iterate through all org users + current_user.organisation.users.each do |user| + if !params[:user_ids].nil? + user_ids = params[:user_ids].map(&:to_i) + # if user_id in passed params + if user_ids.include? user.id + # run generate_or_keep + user.keep_or_generate_token! + # if not in passed params + else + # remove the token + user.remove_token! + end + else + # no users selected so remove all tokens + user.remove_token! + end + end + #redirect_to admin_index + else + render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false) + end + end + end diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index 4da5c9b..c413d99 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -16,4 +16,9 @@ @project = project mail(to: @user.email, subject: "DMP access removed") end + + def api_token_granted_notification(user) + @user = user + mail(to: @user.email, subject: I18n.t('helper.api_mail_subject') + end end \ No newline at end of file diff --git a/app/models/dmptemplate.rb b/app/models/dmptemplate.rb index 0e2aac4..15d1d16 100644 --- a/app/models/dmptemplate.rb +++ b/app/models/dmptemplate.rb @@ -1,108 +1,156 @@ class Dmptemplate < ActiveRecord::Base - - attr_accessible :organisation_id, :description, :published, :title, :user_id, :locale, :is_default, :guidance_group_ids, :as => [:default, :admin] - + + attr_accessible :organisation_id, :description, :published, :title, :user_id, :locale, :is_default, :guidance_group_ids, as: [:default, :admin] + #associations between tables has_many :phases - has_many :versions, :through => :phases - has_many :sections, :through => :versions - has_many :questions, :through => :sections + has_many :versions, through: :phases + has_many :sections, through: :versions + has_many :questions, through: :sections has_many :projects - + #has_many :guidances needs to be removed and checked - + belongs_to :organisation - + has_and_belongs_to_many :guidance_groups, join_table: "dmptemplates_guidance_groups" - + accepts_nested_attributes_for :guidance_groups accepts_nested_attributes_for :phases accepts_nested_attributes_for :organisation accepts_nested_attributes_for :projects - + has_settings :export, class_name: 'Settings::Dmptemplate' do |s| s.key :export, defaults: Settings::Dmptemplate::DEFAULT_SETTINGS end - + + ## + # Converts a DMPtemplate object into a string containing it's title + # + # @return [String] the title of the DMPtemplate def to_s "#{title}" end - + + ## + # takes a type or organisation and returns all published templates from + # organisations of that type + # + # @param ot [String] name of an organisation type e.g. founder + # @return [Array] list of published dmptemplates def self.templates_org_type(ot) - new_org_obejcts = OrganisationType.find_by_name(ot).organisations - + # DISCUSS - This function other than the check for the template being published + # is a superclass for the below funders_templates + new_org_obejcts = OrganisationType.find_by( name: ot ).organisations + org_templates = Array.new new_org_obejcts.each do |neworg| org_templates += neworg.dmptemplates.where("published = ?", true) end - - return org_templates - end - #returns all funders templates + return org_templates + end + + ## + # returns all templates from all organisations of the Organisation_Type funder + # + # @return [Array] all templates from funder organisations def self.funders_templates - new_org_obejcts = OrganisationType.find_by_name(I18n.t("helpers.org_type.funder")).organisations + new_org_obejcts = OrganisationType.find_by(name: I18n.t("helpers.org_type.funder")).organisations org_templates = Array.new - + new_org_obejcts.each do |neworg| org_templates += neworg.dmptemplates end - - return org_templates + + return org_templates end - - - #returns all institutional templates bellowing to the current user's org + + ## + # returns all institutional templates bellowing to the given organisation + # + # @param org_id [integer] the integer id for an organisation + # @return [Array] all templates from a user's organisation def self.own_institutional_templates(org_id) + # DISCUSS - Why is this done by scanning organisation_id's from the templates + # yet all other calls are done by finding an organisation, and using the + # has_many relationship to find the dmptemplates? + # - A possible answer is that there may be deleted organisations which we are + # serching for templates for. + # - A standardised behavior on querries, wether through active reccord or the + # where, should maybe be thought of/decided upon new_templates = self.where("organisation_id = ?", org_id) return new_templates end - - #returns an array with all funders and own institutional templates + + ## + # returns an array with all funders and of the given organisations's + # institutional templates + # + # @param org_id [integer] the integer id for an organisation + # @return [Array] all templates from the template's organisation + # or from a funder organisation def self.funders_and_own_templates(org_id) funders_templates = self.funders_templates - - #verify if org type is not a funder - current_org = Organisation.find(org_id) - if current_org.organisation_type.name != I18n.t("helpers.org_type.funder") then - own_institutional_templates = self.own_institutional_templates(org_id) - else - own_institutional_templates = [] - end - + # DISCUSS - Here we internationalise the word funder. There is code in the + # api that just uses the english word funder. Why are we internationalising + # the database querry, and do I need to change things like this elsewhere? + + #verify if org type is not a funder + current_org = Organisation.find(org_id) + if current_org.organisation_type.name != I18n.t("helpers.org_type.funder") then + own_institutional_templates = self.own_institutional_templates(org_id) + else + own_institutional_templates = [] + end + templates_list = Array.new templates_list += own_institutional_templates templates_list += funders_templates templates_list = templates_list.sort_by { |f| f['title'].downcase } - + return templates_list end - + + ## + # Returns the string name of the organisation type of the organisation who + # owns this dmptemplate + # + # @return [string] the string name of an organisation type def org_type org_type = organisation.organisation_type.name return org_type end - - #verify if a template has customisation by current user's org + + ## + # Verify if a template has customisation by given organisation + # + # @param org_id [integer] the integer id for an organisation + # @param temp [dmptemplate] a template object + # @return [Boolean] true if temp has customisation by the given organisation def has_customisations?(org_id, temp) + # EXPLAIN - I dont Understand the data model here. If the template isnt + # owned by the organisation, how can it make changes to a section? + # Why cant the owner make customisations? if temp.organisation_id != org_id then temp.phases.each do |phase| phase.versions.each do |version| version.sections.each do |section| - return true if section.organisation_id == org_id - - end + return true if section.organisation_id == org_id + end end - return false + return false end else - return false - end + return false + end end - - + + ## # verify if there are any publish version for the template + # + # @return [Boolean] true if there is a published version for the template def has_published_versions? phases.each do |phase| return true if !phase.latest_published_version.nil? diff --git a/app/models/guidance.rb b/app/models/guidance.rb index b1feb32..aa89dbb 100644 --- a/app/models/guidance.rb +++ b/app/models/guidance.rb @@ -8,27 +8,31 @@ class Guidance < ActiveRecord::Base - #associations between tables + #associations between tables attr_accessible :text, :question_id, :published, :as => [:default, :admin] - attr_accessible :guidance_group_ids, :as => [:default, :admin] - attr_accessible :theme_ids, :as => [:default, :admin] + attr_accessible :guidance_group_ids, :as => [:default, :admin] + attr_accessible :theme_ids, :as => [:default, :admin] - belongs_to :question + belongs_to :question - #belongs_to :dmptemplate - #belongs_to :theme + #belongs_to :dmptemplate + #belongs_to :theme - has_and_belongs_to_many :guidance_groups, join_table: "guidance_in_group" - has_and_belongs_to_many :themes, join_table: "themes_in_guidance" + has_and_belongs_to_many :guidance_groups, join_table: "guidance_in_group" + has_and_belongs_to_many :themes, join_table: "themes_in_guidance" - accepts_nested_attributes_for :themes - accepts_nested_attributes_for :guidance_groups + accepts_nested_attributes_for :themes + accepts_nested_attributes_for :guidance_groups - #verifies if one guidance belongs to a org + ## + # Determine if a guidance is in a group which belongs to a specified organisation + # + # @param org_id [Integer] the integer id for an organisation + # @return [Boolean] true if this guidance is in a group belonging to the specified organisation, false otherwise def in_group_belonging_to?(organisation_id) guidance_groups.each do |guidance_group| - if guidance_group.organisation_id == organisation_id then + if guidance_group.organisation_id == organisation_id return true end end @@ -36,33 +40,46 @@ end - #all guidance that belong to an organisation + ## + # returns all guidance that belongs to a specified organisation + # + # @param org_id [Integer] the integer id for an organisation + # @return [Array] list of guidance def self.by_organisation(org_id) - all_guidance = Guidance.all - org_guidance = Array.new - - all_guidance.each do |guidance| - if guidance.in_group_belonging_to?(org_id) then - org_guidance << guidance - end - end - + org_guidance = [] + Organisation.find_by(id: org_id).guidance_groups.each do |group| + org_guidance += group.guidances + end return org_guidance - end - + ## + # returns all templates belgonging to a specified guidance group + # + # @param guidance_group [Integer] the integer id for an guidance_group + # @return [Array] list of templates def get_guidance_group_templates? (guidance_group) + # DISCUSS - here we have yet another way of finding a specific or group of + # an object. Would it make sense to standardise the project by only using + # either finders or where, or alteast the same syntax within the where statement. + # Also why is this a ? method... it dosent return a boolean + # Additionally, shouldnt this be a function of guidance group, not guidance? + # and finally, it should be a self.method, as it dosent care about the guidance it's acting on templates = guidancegroups.where("guidance_group_id (?)", guidance_group.id).template return templates end - def self.can_view(user, id) - # we define guidances viewable to a user by those owned by a guidance group: - # owned by the DCC - # owned by a funder organisation - # owned by an organisation, of which the user is a member - + ## + # Returns whether or not a given user can view a given guidance + # we define guidances viewable to a user by those owned by a guidance group: + # owned by the DCC + # owned by a funder organisation + # owned by an organisation, of which the user is a member + # + # @param id [Integer] the integer id for a guidance + # @param user [User] a user object + # @return [Boolean] true if the specified user can view the specified guidance, false otherwise + def self.can_view?(user, id) guidance = Guidance.find_by(id: id) viewable = false @@ -70,7 +87,8 @@ guidance.guidance_groups.each do |guidance_group| # guidances are viewable if they are owned by any of the user's organisations - user.organisations do |organisation| + user.organisations.each do |organisation| + logger.debug "#{organisation.name}" if guidance_group.organisation.id == organisation.id viewable = true end @@ -90,30 +108,33 @@ return viewable end + ## + # Returns a list of all guidances which a specified user can view + # we define guidances viewable to a user by those owned by a guidance group: + # owned by the DCC + # owned by a funder organisation + # owned by an organisation, of which the user is a member + # + # @param user [User] a user object + # @return [Array] a list of all "viewable" guidances to a user def self.all_viewable(user) - # we define vuiable guidances as those owned by a guidance group: - # owned by the DCC - # owned by a funder organisation - # owned by an organisation, of which the user is a member - - # first find all groups owned by the DCC dcc_groups = (Organisation.find_by name: "Digital Curation Centre").guidance_groups # find all groups owned by a Funder organisation funder_groups = [] funders = OrganisationType.find_by( name: "Funder") funders.organisations.each do |funder| - funder_groups = funder_groups + funder.guidance_groups + funder_groups += funder.guidance_groups end # find all groups owned by any of the user's organisations organisation_groups = [] user.organisations.each do |organisation| - organisation_groups = organisation_groups + organisation.guidance_groups + organisation_groups += organisation.guidance_groups end # find all guidances belonging to any of the viewable groups all_viewable_guidances = [] all_viewable_groups = dcc_groups + funder_groups + organisation_groups all_viewable_groups.each do |group| - all_viewable_guidances = all_viewable_guidances + group.guidances + all_viewable_guidances += group.guidances end # pass the list of viewable guidances to the view return all_viewable_guidances diff --git a/app/models/guidance_group.rb b/app/models/guidance_group.rb index 21da8cc..d7606fd 100644 --- a/app/models/guidance_group.rb +++ b/app/models/guidance_group.rb @@ -13,10 +13,21 @@ attr_accessible :organisation_id, :name, :optional_subset, :published, :as => [:default, :admin] attr_accessible :dmptemplate_ids, :as => [:default, :admin] + ## + # Converts a guidance group to a string containing the display name + # + # @return [String] the name of the organisation, with or without the name of the guidance group def to_s "#{display_name}" end + ## + # Converts the current guidance group to a string containing the display name. + # If it's organisation has no other guidance groups, then the name is simply + # the name of the parent organisation, otherwise it returns the name of the + # organisation followed by the name of the guidance group. + # + # @return [String] the display name for the guidance group def display_name if organisation.guidance_groups.count > 1 return "#{organisation.name}: #{name}" @@ -25,6 +36,11 @@ end end + ## + # Returns the list of all guidance groups not coming from the given organisations + # + # @params excluded_orgs [Array] a list of organisations to exclude in the result + # @return [Array] a list of guidance groups def self.guidance_groups_excluding(excluded_orgs) excluded_org_ids = Array.new excluded_orgs.each do |org| @@ -34,16 +50,22 @@ return return_orgs end - def self.can_view(user, id) - # we define guidance groups viewable to a user by: - # those owned by the DCC - # those owned by a funder organisation - # those owned by an organisation, of which the user is a member - + ## + # Returns whether or not a given user can view a given guidance group + # we define guidances viewable to a user by those owned by: + # the DCC + # a funder organisation + # an organisation, of which the user is a member + # + # @param id [Integer] the integer id for a guidance group + # @param user [User] a user object + # @return [Boolean] true if the specified user can view the specified guidance group, false otherwise + def self.can_view?(user, id) guidance_group = GuidanceGroup.find_by(id: id) viewable = false + # groups are viewable if they are owned by any of the user's organisations - user.organisations do |organisation| + user.organisations.each do |organisation| if guidance_group.organisation.id == organisation.id viewable = true end @@ -62,12 +84,16 @@ return viewable end + ## + # Returns a list of all guidance groups which a specified user can view + # we define guidance groups viewable to a user by those owned by: + # the DCC + # a funder organisation + # an organisation, of which the user is a member + # + # @param user [User] a user object + # @return [Array] a list of all "viewable" guidance groups to a user def self.all_viewable(user) - # we define guidance groups viewable to a user by: - # those owned by the DCC - # those owned by a funder organisation - # those owned by an organisation, of which the user is a member - # first find all groups owned by the DCC dcc_groups = [] Organisation.where( name: "Digital Curation Centre").find_each do |dcc| diff --git a/app/models/organisation.rb b/app/models/organisation.rb index 0aa0c88..0828218 100644 --- a/app/models/organisation.rb +++ b/app/models/organisation.rb @@ -1,101 +1,148 @@ class Organisation < ActiveRecord::Base - #associations between tables - belongs_to :organisation_type - has_many :guidance_groups - has_many :dmptemplates - has_many :sections - has_many :users - has_many :option_warnings - has_many :suggested_answers - has_many :org_token_permissions + #associations between tables + belongs_to :organisation_type + has_many :guidance_groups + has_many :dmptemplates + has_many :sections + has_many :users, through: :user_org_roles + has_many :option_warnings + has_many :suggested_answers + has_and_belongs_to_many :token_permission_types, join_table: "org_token_permissions" has_many :user_org_roles belongs_to :parent, :class_name => 'Organisation' - has_many :children, :class_name => 'Organisation', :foreign_key => 'parent_id' + has_many :children, :class_name => 'Organisation', :foreign_key => 'parent_id' - accepts_nested_attributes_for :organisation_type - accepts_nested_attributes_for :dmptemplates + accepts_nested_attributes_for :organisation_type + accepts_nested_attributes_for :dmptemplates + accepts_nested_attributes_for :token_permission_types - attr_accessible :abbreviation, :banner_text, :description, :domain, :logo_file_name, :name, :stylesheet_file_id, :target_url, :organisation_type_id, :wayfless_entity, :parent_id, :sort_name + attr_accessible :abbreviation, :banner_text, :description, :domain, :logo_file_name, :name, :stylesheet_file_id, :target_url, :organisation_type_id, :wayfless_entity, :parent_id, :sort_name, :token_permission_type_ids + ## + # returns the name of the current organisation + # + # @return [String] the name of the organisation + def to_s + name + end - def to_s - name - end + ## + # returns the abbreviation for the organisation if it exists, name otherwise + # + # @return [String] abbreviation or name + def short_name + if abbreviation.nil? then + return name + else + return abbreviation + end + end - def short_name - if abbreviation.nil? then - return name - else - return abbreviation - end - end + ## + # returns all organisations who have parents of a given organisation type + # + # @params org_type [String] the name of an organisation type + # @return [Array] a list of organisations + def self.orgs_with_parent_of_type(org_type) + parents = OrganisationType.find_by(name: (org_type)).organisations + children = Array.new + parents.each do |parent| + children += parent.children + end + return children + end - #retrieves info off a child org - def self.orgs_with_parent_of_type(org_type) - parents = OrganisationType.find_by_name(org_type).organisations - children = Array.new - parents.each do |parent| - children += parent.children - end - return children - end + ## + # returns a list of all guidance groups belonging to other organisations + # + # @return [Array] + def self.other_organisations + #DISCUSS - What does this method do? + org_types = [I18n.t('helpers.org_type.organisation')] + organisations_list = [] + org_types.each do |ot| + new_org_obejct = OrganisationType.find_by(name: ot) + org_with_guidance = GuidanceGroup.joins(new_org_obejct.organisations) - def self.other_organisations - org_types = [I18n.t('helpers.org_type.organisation')] - organisations_list = [] - org_types.each do |ot| - new_org_obejct = OrganisationType.find_by_name(ot) + organisations_list = organisations_list + org_with_guidance + end + return organisations_list + end - org_with_guidance = GuidanceGroup.joins(new_org_obejct.organisations) + ## + # returns a list of all sections of a given version from this organisation and it's parents + # + # @params version_id [Integer] version number of the section + # @return [Array
] list of sections + def all_sections(version_id) + if parent.nil? + secs = sections.where("version_id = ?", version_id) + if secs.nil? then + secs = Array.new + end + return secs + else + return sections.where("version_id = ? ", version_id).all + parent.all_sections(version_id) + end + end - organisations_list = organisations_list + org_with_guidance - end - return organisations_list - end + ## + # returns the guidance groups of this organisation and all of it's children + # + # @return [Array] list of guidance groups + def all_guidance_groups + ggs = guidance_groups + children.each do |c| + ggs = ggs + c.all_guidance_groups + end + return ggs + end - def all_sections(version_id) - if parent.nil? - secs = sections.where("version_id = ?", version_id) - if secs.nil? then - secs = Array.new - end - return secs - else - return sections.where("version_id = ? ", version_id).all + parent.all_sections(version_id) - end - end + ## + # returns the highest parent organisation in the tree + # + # @return [organisation] the root organisation + def root + if parent.nil? + return self + else + return parent.root + end + end - def all_guidance_groups - ggs = guidance_groups - children.each do |c| - ggs = ggs + c.all_guidance_groups - end - return ggs - end + ## + # takes in the id of, and returns an OptionWarning + # + # @params option_id [number] the id of the desired warning + # @return [OptionWarning] the specified warning + def warning(option_id) + warning = option_warnings.find_by(option_id: option_id) + if warning.nil? && !parent.nil? then + return parent.warning(option_id) + else + return warning + end + end - def root - if parent.nil? - return self - else - return parent.root - end - end + ## + # returns all published templates belonging to the organisation + # + # @return [Array] published dmptemplates + def published_templates + return dmptemplates.where("published = ?", 1) + end - def warning(option_id) - warning = option_warnings.find_by_option_id(option_id) - if warning.nil? && !parent.nil? then - return parent.warning(option_id) - else - return warning - end - end - - def published_templates - return dmptemplates.where("published = ?", 1) - end + def check_api_credentials + if token_permission_types.count == 0 + users.each do |user| + user.api_token = "" + user.save! + end + end + end end diff --git a/app/models/token_permission.rb b/app/models/token_permission.rb deleted file mode 100644 index 53d8567..0000000 --- a/app/models/token_permission.rb +++ /dev/null @@ -1,10 +0,0 @@ -class TokenPermission < ActiveRecord::Base - attr_accessible :token_permission_type_id, :token_permission_type, :api_token, :user_id, :user, :as => [:default, :admin] - - #associations between tables - belongs_to :token_permission_type - belongs_to :user - - - -end diff --git a/app/models/token_permission_type.rb b/app/models/token_permission_type.rb index 2de7d56..8c02ecb 100644 --- a/app/models/token_permission_type.rb +++ b/app/models/token_permission_type.rb @@ -3,8 +3,7 @@ attr_accessible :token_type, :text_desription, :as => [:default, :admin] #associations between tables - has_many :token_permissions - has_many :org_token_permissions + has_and_belongs_to_many :org_token_permissions, join_table: "org_token_permissions" def to_s self.token_type diff --git a/app/models/user.rb b/app/models/user.rb index 5621a2c..96114b4 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -14,7 +14,6 @@ has_many :project_groups, :dependent => :destroy has_many :organisations , through: :user_org_roles has_many :user_role_types, through: :user_org_roles - has_many :token_permissions has_many :projects, through: :project_groups do @@ -41,7 +40,8 @@ accepts_nested_attributes_for :roles attr_accessible :role_ids - attr_accessible :password_confirmation, :encrypted_password, :remember_me, :id, :email, :firstname, :last_login,:login_count, :orcid_id, :password, :shibboleth_id, :user_status_id, :surname, :user_type_id, :organisation_id, :skip_invitation, :other_organisation, :accept_terms, :role_ids, :dmponline3, :api_token + attr_accessible :password_confirmation, :encrypted_password, :remember_me, :id, :email, :firstname, :last_login,:login_count, :orcid_id, :password, :shibboleth_id, :user_status_id, :surname, :user_type_id, :organisation_id, :skip_invitation, :other_organisation, :accept_terms, :role_ids, :dmponline3 + attr_accessible :api_token # FIXME: The duplication in the block is to set defaults. It might be better if # they could be set in Settings::PlanList itself, if possible. @@ -59,22 +59,33 @@ end def organisation_id=(new_organisation_id) - if !self.user_org_roles.pluck(:organisation_id).include?(new_organisation_id.to_i) then - if self.user_org_roles.count != 1 then - new_user_org_role = UserOrgRole.new - new_user_org_role.organisation_id = new_organisation_id - new_user_org_role.user_role_type = UserRoleType.find_by_name("user"); - self.user_org_roles << new_user_org_role - else - user_org_role = self.user_org_roles.first - user_org_role.organisation_id = new_organisation_id - user_org_role.save - org_admin_role = roles.find_by_name("org_admin") - unless org_admin_role.nil? then - roles.delete(org_admin_role) - end - end - end + # if the user is not part of the new organisation + if !self.user_org_roles.pluck(:organisation_id).include?(new_organisation_id.to_i) then + # if the user has more than one role + if self.user_org_roles.count != 1 then + new_user_org_role = UserOrgRole.new + new_user_org_role.organisation_id = new_organisation_id + new_user_org_role.user_role_type = UserRoleType.find_by_name("user"); + self.user_org_roles << new_user_org_role + # + # if the user has roles other than one(0/2/3?) + else + # set role to first role + user_org_role = self.user_org_roles.first + # change org_id to new org_id + user_org_role.organisation_id = new_organisation_id + # save modified role + user_org_role.save + # if user has an "org_admin" role + org_admin_role = roles.find_by_name("org_admin") + unless org_admin_role.nil? then + # delete it + roles.delete(org_admin_role) + end + end + end + # rip api_token from user + self.api_token = "" end def organisation_id @@ -120,5 +131,23 @@ return org_type end + def remove_token! + unless api_token.empty? + self.api_token = "" + self.save! + end + end + + def keep_or_generate_token! + if api_token.empty? + self.api_token = loop do + random_token = SecureRandom.urlsafe_base64(nil, false) + break random_token unless User.exists?(api_token: random_token) + end + self.save! + # send an email to the user to notify them of their new api token + UserMailer.api_token_granted_notification(self) + end + end end diff --git a/app/views/api/v0/guidance_groups/index.json.jbuilder b/app/views/api/v0/guidance_groups/index.json.jbuilder index 2271872..3f5aa68 100644 --- a/app/views/api/v0/guidance_groups/index.json.jbuilder +++ b/app/views/api/v0/guidance_groups/index.json.jbuilder @@ -14,6 +14,10 @@ json.templates @templates do |template| json.title template.title end + json.guidances guidance_group.guidances do |guidance| + json.text guidance.text + json.id guidance.id + end json.optional guidance_group.optional_subset json.updated guidance_group.updated_at end diff --git a/app/views/api/v0/guidance_groups/show.json.jbuilder b/app/views/api/v0/guidance_groups/show.json.jbuilder index e776269..bcffb41 100644 --- a/app/views/api/v0/guidance_groups/show.json.jbuilder +++ b/app/views/api/v0/guidance_groups/show.json.jbuilder @@ -14,6 +14,10 @@ json.templates @templates do |template| json.title template.title end + json.guidances @guidance_group.guidances do |guidance| + json.text guidance.text + json.id guidance.id + end json.optional @guidance_group.optional_subset json.updated @guidance_group.updated_at -end \ No newline at end of file +end diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb index fb692c8..7dc9e68 100644 --- a/app/views/devise/registrations/edit.html.erb +++ b/app/views/devise/registrations/edit.html.erb @@ -58,6 +58,16 @@ :autocomplete => "off" , :class => "text_field has-tooltip", "data-toggle" => "tooltip", "data-html" => "true", "title" => t("helpers.orcid_html") %> + <% unless @user.api_token.nil? %> + + <%= t("helpers.api_token") %> + <%= @user.api_token %> + + + <%= t("helpers.api_info") %> + <%= link_to( t("helpers.api_use"), controller: "token_permission_types", action: "index")%> + + <% end %>

diff --git a/app/views/layouts/_dmponline_navigation.html.erb b/app/views/layouts/_dmponline_navigation.html.erb index 3e87b87..5334682 100644 --- a/app/views/layouts/_dmponline_navigation.html.erb +++ b/app/views/layouts/_dmponline_navigation.html.erb @@ -28,12 +28,12 @@ <% end %> <%= link_to t("org_admin.org_details_label"), admin_show_organisation_path(current_user.organisation_id)%> - <% if current_path == "/org/admin/users" then %> + <% if current_path == "/org/admin/users/admin_index" || current_path == "/org/admin/users/admin_api_update" then %>

  • <% else %>
  • <% end %> - <%= link_to t("org_admin.user_list_label"), "/org/admin/users", :class => "main_nav_last_li"%> + <%= link_to t("org_admin.user_list_label"), "/org/admin/users/admin_index", :class => "main_nav_last_li"%>
  • <% else %> <% if user_signed_in? %> diff --git a/app/views/organisation_users/admin_index.html.erb b/app/views/organisation_users/admin_index.html.erb index f6184c1..1418cf9 100644 --- a/app/views/organisation_users/admin_index.html.erb +++ b/app/views/organisation_users/admin_index.html.erb @@ -1,46 +1,64 @@ <%= stylesheet_link_tag "admin" %>

    - <%= t('org_admin.users_list') %> + <%= t('org_admin.users_list') %>

    <%= raw t('org_admin.user_text_html')%> <% @user_roles = current_user.organisation.user_org_roles %> -<% @user_roles = @user_roles.uniq_by {|u| u.user_id } %> - - - - - - - - - - - - <% @user_roles.each do |user_id| %> - <% if !user_id.user.nil? then%> - - - - - - - <%end%> - <% end %> - -
    <%= t('org_admin.user_full_name') %><%= t('org_admin.user_name') %><%= t('org_admin.last_logged_in') %><%= t('org_admin.how_many_plans') %>
    - <% if !user_id.user.name.nil? then%> - <%= user_id.user.name %> - <%end%> - - <%= user_id.user.email %> - - <% if !user_id.user.last_sign_in_at.nil? then%> - <%= l user_id.user.last_sign_in_at.to_date, :formats => :short %> - <%end%> - - <% if !user_id.user.project_groups.nil? then%> - <%= user_id.user.project_groups.count %> - <%end%> -
    +<% @user_roles = @user_roles.uniq_by {|u| u.user_id } %> + + + + + + + + <% if current_user.organisation.token_permission_types.count > 0 %> + + <% end %> + + + <% form_tag admin_index_organisation_users_path, method: :put do %> + + <% @user_roles.each do |user_id| %> + <% if !user_id.user.nil? then%> + + + + + + <% if current_user.organisation.token_permission_types.count > 0 %> + + <% end %> + + <% end %> + <% end %> + + <%= submit_tag "Update API Privleges" %> + <% end %> +
    <%= t('org_admin.user_full_name') %><%= t('org_admin.user_name') %><%= t('org_admin.last_logged_in') %><%= t('org_admin.how_many_plans') %><%= t('org_admin.api_privleges') %>
    + <% if !user_id.user.name.nil? then%> + <%= user_id.user.name %> + <% end %> + + <%= user_id.user.email %> + + <% if !user_id.user.last_sign_in_at.nil? then%> + <%= l user_id.user.last_sign_in_at.to_date, :formats => :short %> + <% end %> + + <% if !user_id.user.project_groups.nil? then%> + <%= user_id.user.project_groups.count %> + <% end %> + + <%= check_box_tag "user_ids[]", user_id %> + +
    \ No newline at end of file diff --git a/app/views/token_permission_types/index.html.erb b/app/views/token_permission_types/index.html.erb new file mode 100644 index 0000000..7832b4e --- /dev/null +++ b/app/views/token_permission_types/index.html.erb @@ -0,0 +1,14 @@ + +<% @user.organisation.token_permission_types.each do |token_type|%> +

    + <%= token_type.token_type %> +

    +
    + +
    + + <%= token_type.text_desription %> + +
    + +<% end %> \ No newline at end of file diff --git a/app/views/user_mailer/api_token_granted_notification.html.erb b/app/views/user_mailer/api_token_granted_notification.html.erb new file mode 100644 index 0000000..817a6ff --- /dev/null +++ b/app/views/user_mailer/api_token_granted_notification.html.erb @@ -0,0 +1,6 @@ +

    <% t('custom_devise.hello') %><%= @user.name %>

    + + +

    +<% t('helpers.api_granted') %>"<%= link_to t('helpers.api_view_token'), controller: "users", action: "edit") %>". +

    diff --git a/app/views/users/admin_index.html.erb b/app/views/users/admin_index.html.erb new file mode 100644 index 0000000..33a717e --- /dev/null +++ b/app/views/users/admin_index.html.erb @@ -0,0 +1,57 @@ +<%= stylesheet_link_tag "admin" %> + +

    + <%= t('org_admin.users_list') %> +

    + +<%= raw t('org_admin.user_text_html')%> +<% @user_roles = current_user.organisation.user_org_roles %> +<% @user_roles = @user_roles.uniq_by {|u| u.user_id } %> + + + + + + + + <% if current_user.organisation.token_permission_types.count > 0 %> + + <% end %> + + + + + <%= form_tag( admin_api_update_users_path, method: :put) do %> + <% @user_roles.each do |user_id| %> + <% if !user_id.user.nil? then%> + + + + + + <% if current_user.organisation.token_permission_types.count > 0 %> + + <% end %> + + <% end %> + <% end %> + + <%= submit_tag "Update API Privleges" %> + <% end %> +
    <%= t('org_admin.user_full_name') %><%= t('org_admin.user_name') %><%= t('org_admin.last_logged_in') %><%= t('org_admin.how_many_plans') %><%= t('org_admin.api_privleges') %>
    + <% if !user_id.user.name.nil? then%> + <%= user_id.user.name %> + <% end %> + + <%= user_id.user.email %> + + <% if !user_id.user.last_sign_in_at.nil? then%> + <%= l user_id.user.last_sign_in_at.to_date, :formats => :short %> + <% end %> + + <% if !user_id.user.project_groups.nil? then%> + <%= user_id.user.project_groups.count %> + <% end %> + + <%= check_box_tag "user_ids[]", user_id.user.id, user_id.user.api_token !="" %> +
    \ No newline at end of file diff --git a/config/environment/development.rb b/config/environment/development.rb index f594bf2..ac714c2 100644 --- a/config/environment/development.rb +++ b/config/environment/development.rb @@ -6,19 +6,26 @@ # since you don't have to restart the web server when you make code changes. config.cache_classes = false - # Do not eager load code on boot. - config.eager_load = false + # Log error messages when you accidentally call methods on nil. + config.whiny_nils = true - # Show full error reports and disable caching. + # Show full error reports and disable caching config.consider_all_requests_local = true config.action_controller.perform_caching = false - # Don't care if the mailer can't send. - config.action_mailer.raise_delivery_errors = false + # Don't care if the mailer can't send + config.action_mailer.raise_delivery_errors = true - # Print deprecation notices to the Rails logger. + # Print deprecation notices to the Rails logger config.active_support.deprecation = :log + # Only use best-standards-support built into browsers + config.action_dispatch.best_standards_support = :builtin + + # Raise exception on mass assignment protection for Active Record models + config.active_record.mass_assignment_sanitizer = :strict + + # Raise an error on page load if there are pending migrations. config.active_record.migration_error = :page_load @@ -27,6 +34,8 @@ # number of complex assets. config.assets.debug = true + config.assets.compress = false + # Asset digests allow you to set far-future HTTP expiration dates on all assets, # yet still be able to expire them through the digest params. config.assets.digest = true @@ -40,4 +49,10 @@ # config.action_view.raise_on_missing_translations = true # config.action_mailer.perform_deliveries = false + + config.web_console.whitelisted_ips = '192.168.33.1' + + end + +BetterErrors::Midleware.allow_ip! "10.0.2.2" if defined?(BetterErrors) && Rails.env == :development diff --git a/config/locales/en.yml b/config/locales/en.yml index f2c4dcc..7465458 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -107,6 +107,7 @@ permission_description: "Permission Description" token_permission: "Token Permission" org_token_permission: "Organisation Token Permission" +# choose_api_permissions: "Choose all API Permissions that apply." settings_updated: 'Settings updated successfully' choose_themes: 'Choose all themes that apply.' @@ -160,6 +161,7 @@ option_default_label: "Default" user_org_created: 'User org role was successfully created.' user_org_updated: 'User org role was successfully updated.' + api_privleges: 'API Privleges?' guidance: guidance_list: "Guidance list" text_label: "Text" @@ -349,6 +351,13 @@ email_already_registered: 'That email address is already registered.' email_must_valid_confirmation_message: "This must be a valid email address - a message will be sent to it for confirmation." error_registration_check: 'Error processing registration. Please check that you have entered a valid email address and that your chosen password is at least 8 characters long.' + api_token: 'API token' + api_info: 'API Information' + api_use: 'How to use the API' + api_granted: 'You have been granted permission by your organisation to use our API.' + api_view_token: 'Your API token and instructions for using the API endpoints can be found here.' + api_mail_subject: 'API Permission Granted' + text_area: "Text area" text_field: "Text field" @@ -899,4 +908,13 @@ unlock: 'Unlock my account' waiting_for_confirmation: "Currently waiting confirmation for: " resend_unlock: "Resend unlock instructions" + api: + bad_credentials: '{"Error":"Bad credentials"}' + org_dosent_exist: '{"Error":"Organisation does not exist"}' + org_not_funder: '{"Error":"Organisation specified is not a funder"}' + org_multiple_templates: '{"Error":"Organisation has more than one template and template name unspecified or invalid"}' + no_auth_for_endpoint: '{"Error":"You do not have authorisation to view this endpoint"}' + bad_resource: '{"Error":"You do not have authorisation to view this resource"}' + + diff --git a/config/routes.rb b/config/routes.rb index a921b78..9cce7b2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -23,7 +23,13 @@ get "existing_users" => 'existing_users#index', :as => "existing_users" #organisation admin area - get "org/admin/users" => 'organisation_users#admin_index', :as => "org/admin/users" + #match "org/admin/users" => 'organisation_users#admin_index', :as => "org/admin/users" + resources :users, :path =>'org/admin/users', only:[] do + collection do + get 'admin_index' + put 'admin_api_update' + end + end resources :organisations, :path => 'org/admin' do member do @@ -63,7 +69,7 @@ end end - resource :organisation + #resource :organisation #resources :splash_logs @@ -165,6 +171,8 @@ resources :plans end + resources :token_permission_types, only:[:index] + namespace :api, defaults: { format: :json } do namespace :v0 do resources :guidance_groups, only: [ :index, :show ] @@ -175,6 +183,7 @@ get '/api' => redirect('/swagger/dist/index.html?url=/apidocs/api-docs.json') + # The priority is based upon order of creation: # first created -> highest priority. diff --git a/db/migrate/20160719102542_remove_depricated_api_structure.rb b/db/migrate/20160719102542_remove_depricated_api_structure.rb new file mode 100644 index 0000000..d19cfb9 --- /dev/null +++ b/db/migrate/20160719102542_remove_depricated_api_structure.rb @@ -0,0 +1,9 @@ +class RemoveDepricatedApiStructure < ActiveRecord::Migration + def up + drop_table :token_permissions + end + + def down + raise ActiveRecord::IrreversibleMigration + end +end diff --git a/db/schema.rb b/db/schema.rb index 45e8346..52588cc 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160105114044) do +ActiveRecord::Schema.define(version: 20160719102542) do create_table "answers", force: true do |t| t.text "text" @@ -139,6 +139,13 @@ t.datetime "updated_at", null: false end + create_table "org_token_permissions", force: true do |t| + t.integer "organisation_id" + t.integer "token_permission_type_id" + t.datetime "created_at" + t.datetime "updated_at" + end + create_table "organisation_types", force: true do |t| t.string "name" t.text "description" @@ -320,6 +327,13 @@ t.integer "guidance_id" end + create_table "token_permission_types", force: true do |t| + t.string "token_type" + t.text "text_desription" + t.datetime "created_at" + t.datetime "updated_at" + end + create_table "user_org_roles", force: true do |t| t.integer "user_id" t.integer "organisation_id" @@ -376,9 +390,11 @@ t.datetime "invitation_sent_at" t.datetime "invitation_accepted_at" t.string "other_organisation" - t.boolean "dmponline3" t.boolean "accept_terms" t.integer "organisation_id" + t.string "api_token" + t.integer "invited_by_id" + t.string "invited_by_type" end add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree diff --git a/db/seeds.rb b/db/seeds.rb index 84049c1..a1d9869 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -454,7 +454,7 @@ token_permission_types.each do |title,settings| token_permission_type = TokenPermissionType.new token_permission_type.token_type = title - token_permission_type.text_desription = settings(:description) + token_permission_type.text_desription = settings[:description] token_permission_type.save! end diff --git a/test/fixtures/dmptemplates_guidance_groups.yml b/test/fixtures/dmptemplates_guidance_groups.yml new file mode 100644 index 0000000..f49066a --- /dev/null +++ b/test/fixtures/dmptemplates_guidance_groups.yml @@ -0,0 +1,27 @@ +# dcc_template_1: +# guidance_group: dcc_guidance_group_1 +# dmptemplate: dcc_template + +# ahrc_template_1: +# guidance_group: funder_guidance_group_1 +# dmptemplate: ahrc_template + +# bbsrc_template_1: +# guidance_group: funder_guidance_group_2 +# dmptemplate: bbsrc_template + +# aru_template_1: +# guidance_group: institution_guidance_group_1 +# dmptemplate: aru_template + +# au_template_1: +# guidance_group: institution_guidance_group_2 +# dmptemplate: au_template + +# bu_template_1: +# guidance_group: institution_guidance_group_3 +# dmptemplate: bu_template + +# bu_template_2: +# guidance_group: institution_guidance_group_4 +# dmptemplate: bu_template \ No newline at end of file diff --git a/test/fixtures/guidance_groups.yml b/test/fixtures/guidance_groups.yml index 86aa584..ce3dbdd 100644 --- a/test/fixtures/guidance_groups.yml +++ b/test/fixtures/guidance_groups.yml @@ -4,37 +4,50 @@ name: "DCC guidance group 1" organisation: dcc guidances: related_policies, existing_data, licensing_of_existing_data, relationship_to_existing_data, description_of_data_content, data_format, data_volumes, data_type, data_capture_methods, data_organisation, data_quality, documentation, metadata_capture, metadata_standards, discovery_by_users, ethical_issues, ipr_ownership_and_licencing, active_data_storage, backup_procedures, data_security, data_selection, preservation_plan, period_of_preservation, data_repository, audience, expected_reuse, method_for_data_sharing, timeframe_for_data_sharing, embargo_period, restrictions_on_sharing, managed_access_procedures, responsibilities, resourcing_skills_and_training, resourcing_hardware_and_software, resourcing_preservation_and_data_sharing + dmptemplates: dcc_template # funder groups funder_guidance_group_1: name: "Funder guidance group 1" organisation: ahrc guidances: ahrc_funder_guidance + dmptemplates: ahrc_template funder_guidance_group_2: name: "Funder guidance group 2" organisation: bbsrc guidances: bbsrc_funder_guidance + dmptemplates: bbsrc_template # institution groups institution_guidance_group_1: name: "Anglia Ruskin University guidance group" organisation: aru guidances: aru_institution_guidance + dmptemplates: aru_template institution_guidance_group_2: name: "Aston University guidance group" organisation: au guidances: au_institution_guidance_1, au_institution_guidance_2 + dmptemplates: au_template institution_guidance_group_3: name: "Bangor University guidance group 1" organisation: bu guidances: bu_institution_guidance_1 + dmptemplates: bu_template -institution_guidance_group_3: - name: "Bangor University guidance gruop 2" +institution_guidance_group_4: + name: "Bangor University guidance group 2" organisation: bu guidances: bu_institution_guidance_2 + dmptemplates: bu_template +institution_guidance_group_5: + name: "institution child guidance group 1" + organisation: institution_child_one +institution_guidance_group_6: + name: "institution child guidance group 2" + organisation: institution_child_one diff --git a/test/fixtures/option_warnings.yml b/test/fixtures/option_warnings.yml index 97c8505..1a67380 100644 --- a/test/fixtures/option_warnings.yml +++ b/test/fixtures/option_warnings.yml @@ -1,40 +1,40 @@ -#single_select_1_warning: -# option: single_select_1 -# organisation: uog -# text: This warning should display when option 1 of the single item select box example is selected for a project at the University of Glasgow -# -#single_select_2_warning: -# option: single_select_2 -# organisation: hatii -# text: This warning should display when option 2 of the single item select box example is selected for a project at HATII -# -# -#multiple_select_3_warning: -# option: multiple_select_3 -# organisation: uoe -# text: This warning should display when option 3 of the multiple item select box example is selected for a project at the University of Edinburgh -# -#multiple_select_4_warning: -# option: multiple_select_4 -# organisation: uoe_si -# text: This warning should display when option 4 of the multiple item select box example is selected for a project at the School of Informatics -# -#radio_button_1_warning: -# option: radio_button_1 -# organisation: uog -# text: This warning should display when option 1 of the radio button example is selected for a project at the University of Glasgow -# -#radio_button_2_warning: -# option: radio_button_2 -# organisation: hatii -# text: This warning should display when option 2 of the radio button example is selected for a project at HATII -# -#checkbox_3_warning: -# option: checkbox_3 -# organisation: uoe -# text: This warning should display when option 3 of the checkbox example is selected for a project at the University of Edinburgh -# -#checkbox_4_warning: -# option: checkbox_4 -# organisation: uoe_si -# text: This warning should display when option 4 of the checkbox example is selected for a project at the School of Informatics \ No newline at end of file +single_select_1_warning: + option: single_select_1 + organisation: uog + text: This warning should display when option 1 of the single item select box example is selected for a project at the University of Glasgow + +single_select_2_warning: + option: single_select_2 + organisation: hatii + text: This warning should display when option 2 of the single item select box example is selected for a project at HATII + + +multiple_select_3_warning: + option: multiple_select_3 + organisation: uoe + text: This warning should display when option 3 of the multiple item select box example is selected for a project at the University of Edinburgh + +multiple_select_4_warning: + option: multiple_select_4 + organisation: uoe_si + text: This warning should display when option 4 of the multiple item select box example is selected for a project at the School of Informatics + +radio_button_1_warning: + option: radio_button_1 + organisation: uog + text: This warning should display when option 1 of the radio button example is selected for a project at the University of Glasgow + +radio_button_2_warning: + option: radio_button_2 + organisation: hatii + text: This warning should display when option 2 of the radio button example is selected for a project at HATII + +checkbox_3_warning: + option: checkbox_3 + organisation: uoe + text: This warning should display when option 3 of the checkbox example is selected for a project at the University of Edinburgh + +checkbox_4_warning: + option: checkbox_4 + organisation: uoe_si + text: This warning should display when option 4 of the checkbox example is selected for a project at the School of Informatics \ No newline at end of file diff --git a/test/fixtures/options.yml b/test/fixtures/options.yml index e3bc074..866aaf3 100644 --- a/test/fixtures/options.yml +++ b/test/fixtures/options.yml @@ -1,82 +1,82 @@ -#single_select_1: -# question: single_select_box -# text: Option 1 -# number: 1 -# -#single_select_2: -# question: single_select_box -# text: Option 2 -# number: 2 -# -#single_select_3: -# question: single_select_box -# text: Option 3 -# number: 3 -# -#single_select_4: -# question: single_select_box -# text: Option 4 -# number: 4 -# -#multiple_select_1: -# question: multiple_select_box -# text: Option 1 -# number: 1 -# -#multiple_select_2: -# question: multiple_select_box -# text: Option 2 -# number: 2 -# -#multiple_select_3: -# question: multiple_select_box -# text: Option 3 -# number: 3 -# -#multiple_select_4: -# question: multiple_select_box -# text: Option 4 -# number: 4 -# -#radio_button_1: -# question: radio_button -# text: Option 1 -# number: 1 -# -#radio_button_2: -# question: radio_button -# text: Option 2 -# number: 2 -# -#radio_button_3: -# question: radio_button -# text: Option 3 -# number: 3 -# -#radio_button_4: -# question: radio_button -# text: Option 4 -# number: 4 -# -#checkbox_1: -# question: checkbox -# text: Option 1 -# number: 1 -# -#checkbox_2: -# question: checkbox -# text: Option 2 -# number: 2 -# -#checkbox_3: -# question: checkbox -# text: Option 3 -# number: 3 -# -#checkbox_4: -# question: checkbox -# text: Option 4 -# number: 4 +single_select_1: + question: single_select_box + text: Option 1 + number: 1 + +single_select_2: + question: single_select_box + text: Option 2 + number: 2 + +single_select_3: + question: single_select_box + text: Option 3 + number: 3 + +single_select_4: + question: single_select_box + text: Option 4 + number: 4 + +multiple_select_1: + question: multiple_select_box + text: Option 1 + number: 1 + +multiple_select_2: + question: multiple_select_box + text: Option 2 + number: 2 + +multiple_select_3: + question: multiple_select_box + text: Option 3 + number: 3 + +multiple_select_4: + question: multiple_select_box + text: Option 4 + number: 4 + +radio_button_1: + question: radio_button + text: Option 1 + number: 1 + +radio_button_2: + question: radio_button + text: Option 2 + number: 2 + +radio_button_3: + question: radio_button + text: Option 3 + number: 3 + +radio_button_4: + question: radio_button + text: Option 4 + number: 4 + +checkbox_1: + question: checkbox + text: Option 1 + number: 1 + +checkbox_2: + question: checkbox + text: Option 2 + number: 2 + +checkbox_3: + question: checkbox + text: Option 3 + number: 3 + +checkbox_4: + question: checkbox + text: Option 4 + number: 4 mrc_5_2_yes: question: mrc_5_2 diff --git a/test/fixtures/organisations.yml b/test/fixtures/organisations.yml index 4ac384e..5a3f464 100644 --- a/test/fixtures/organisations.yml +++ b/test/fixtures/organisations.yml @@ -891,4 +891,15 @@ ysju: name: York St John University domain: www.yorksj.ac.uk - organisation_type: institution \ No newline at end of file + organisation_type: institution + +institution_parent: + name: "Institution Parent" + domain: "www.example.com" + organisation_type: institution + +institution_child_one: + name: "instituiton Chile 1" + domain: "www.institution_child.com" + organisation_type: instituiton + parent: institution_parent \ No newline at end of file diff --git a/test/fixtures/sections.yml b/test/fixtures/sections.yml index f68a3c0..9adf97f 100644 --- a/test/fixtures/sections.yml +++ b/test/fixtures/sections.yml @@ -427,4 +427,16 @@ title: Required resources number: 7 version: wellcome_template_1_version_1 - organisation: wellcome \ No newline at end of file + organisation: wellcome + +institution_parent_1: + title: first section + number: 1 + version: institution_child_version_1 + organisation: institution_parent + +institution_parent_2: + title: seccond section + number: 2 + version: institution_child_version_1 + organisation: institution_parent \ No newline at end of file diff --git a/test/fixtures/user_org_roles.yml b/test/fixtures/user_org_roles.yml index a1e1b91..b710ec5 100644 --- a/test/fixtures/user_org_roles.yml +++ b/test/fixtures/user_org_roles.yml @@ -9,3 +9,17 @@ # user_id: 1 # organisation_id: 1 # user_role_type_id: 1 +# + +one: + user: user_one + organisation: aru + +two: + user: user_two + organisation: au + +three: + user: user_three + organisation: bu + diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml index 2907d70..04d40ab 100644 --- a/test/fixtures/users.yml +++ b/test/fixtures/users.yml @@ -9,7 +9,7 @@ user_type_id: 1 user_status_id: 1 api_token: "guidances_api_token" - organisation_id: aru.id + #organisation: aru user_two: firstname: MyString @@ -20,7 +20,7 @@ user_type_id: 1 user_status_id: 1 api_token: "plans_api_token" - organisation_id: au.id + #organisation: au user_three: firstname: Mystring @@ -31,7 +31,7 @@ user_type_id: 1 user_status_id: 1 api_token: "plans_api_token" - organisation_id: bu.id + #organisation: bu with_many_projects: diff --git a/test/fixtures/versions.yml b/test/fixtures/versions.yml index cd91ab2..5a8d2f1 100644 --- a/test/fixtures/versions.yml +++ b/test/fixtures/versions.yml @@ -58,4 +58,10 @@ title: "Wellcome Trust Data Management Questions (Version 1)" published: 1 number: 1 - phase: wellcome_template_1 \ No newline at end of file + phase: wellcome_template_1 + +institution_child_version_1: + title: DCC Phase 1 Version 1 + published: 1 + number: 1 + phase: DCC_phase_1 \ No newline at end of file diff --git a/test/unit/dmptemplate_test.rb b/test/unit/dmptemplate_test.rb index db7d287..833a4be 100644 --- a/test/unit/dmptemplate_test.rb +++ b/test/unit/dmptemplate_test.rb @@ -18,7 +18,7 @@ Settings::Dmptemplate::DEFAULT_SETTINGS[:formatting] end - # settings + # ---------- settings ---------- test "settings should use defaults if none defined" do assert(!@template.settings(:export).value?) @@ -200,4 +200,80 @@ assert_equal(default_formatting, @template.settings(:export).formatting) end + # ---------- templates_org_type ---------- + test "templates_org_type returns all published" do + OrganisationType.find_each do |org_type| + result_templates = Dmptemplate.templates_org_type(org_type.name) + my_list = Array.new + org_type.organisations.each do |org| + my_list += org.dmptemplates + end + my_list.each do |template| + if template.published + assert_includes(result_templates, template, "Template: #{template.title}} of type #{org_type.name}, not returned by templates_org_type") + end + end + end + end + + # ---------- funders_templates ---------- + test "funders_templates returns all funder organisation templates" do + result_templates = Dmptemplate.funders_templates + funder_templates = OrganisationType.find_by(name: "funder").organisations do |org| + org.dmptemplates.each do |template| + assert_includes( result_templates, template, "Funder Template: #{template.title} not included in result of funders_templates") + end + end + end + + # ---------- own_institutional_templates ---------- + test "own_institutional_templates returns all templates belonging to given org_id" do + Organisation.find_each do |org| + result_templates = Dmptemplate.own_institutional_templates(org.id) + org.dmptemplates.each do |template| + assert_includes(result_templates, template, "Template: #{template.title} not returned by own_institutional_templates") + end + end + end + + # ---------- funders_and_own_templates ---------- + test "funders_and_own_templates returns all funder and own given org_id templates" do + Organisation.find_each do |org| + result_templates = Dmptemplate.funders_and_own_templates(org.id) + org.dmptemplates.each do |template| + assert_includes(result_templates, template, "Template #{template.title} not returned by funders and own templates") + end + end + funder_templates = OrganisationType.find_by(name: "funder").organisations do |org| + org.dmptemplates.each do |template| + assert_includes( result_templates, template, "Funder Template: #{template.title} not included in result of funders_and_own_templates") + end + end + end + + # ---------- org_type ---------- + test "org_type properly returns the name of the template's organisation's type" do + Dmptemplate.find_each do |template| + assert_equal( template.org_type, template.organisation.organisation_type.name, "Template: #{template.title} returned #{template.org_type}, instead of #{template.organisation.organisation_type.name}") + end + end + + # ---------- has_customisations? ---------- + test "has_customisations? correctly identifies if a given org has customised the template" do + # TODO: Impliment after understanding has_customisations + flunk + end + + # ---------- has_published_versions? ---------- + test "has_published_versions? correctly identifies published versions" do + Dmptemplate.find_each do |template| + template.phases.each do |phase| + unless phase.latest_published_version.nil? + assert(template.has_published_versions? , "there was a published version of phase: #{phase.title}") + end + end + end + end + + end diff --git a/test/unit/guidance_group_test.rb b/test/unit/guidance_group_test.rb new file mode 100644 index 0000000..45a8483 --- /dev/null +++ b/test/unit/guidance_group_test.rb @@ -0,0 +1,156 @@ +require 'test_helper' + +class GuidanceGroupTest < ActiveSupport::TestCase + # ---------- can_view? ---------- + test "DCC guidance groups should be viewable" do + assert GuidanceGroup.can_view?(users(:user_one), guidance_groups(:dcc_guidance_group_1)) + end + + test "Funder guidance groups should be viewable" do + organisation_types(:funder).organisations.each do |org| + org.guidance_groups.each do |funder_group| + assert GuidanceGroup.can_view?(users(:user_one), funder_group) + end + end + end + + test "User's organisation groups should be viewable" do + assert GuidanceGroup.can_view?(users(:user_one), guidance_groups(:institution_guidance_group_1).id) , "user_one cannot view aru_institution_guidance" + + assert GuidanceGroup.can_view?(users(:user_two), guidance_groups(:institution_guidance_group_2).id), "user_two cannot view au_..._1" + + assert GuidanceGroup.can_view?(users(:user_three), guidance_groups(:institution_guidance_group_3).id), "user_three cannot view bu_..._1" + assert GuidanceGroup.can_view?(users(:user_three), guidance_groups(:institution_guidance_group_4).id), "user_three cannot view bu_..._2" + end + + test "No other organisations's groups should be viewable" do + assert_not GuidanceGroup.can_view?(users(:user_one), guidance_groups(:institution_guidance_group_2).id) + assert_not GuidanceGroup.can_view?(users(:user_one), guidance_groups(:institution_guidance_group_3).id) + assert_not GuidanceGroup.can_view?(users(:user_one), guidance_groups(:institution_guidance_group_4).id) + + assert_not GuidanceGroup.can_view?(users(:user_two), guidance_groups(:institution_guidance_group_1).id) + assert_not GuidanceGroup.can_view?(users(:user_two), guidance_groups(:institution_guidance_group_3).id) + assert_not GuidanceGroup.can_view?(users(:user_two), guidance_groups(:institution_guidance_group_4).id) + + assert_not GuidanceGroup.can_view?(users(:user_three), guidance_groups(:institution_guidance_group_1).id) + assert_not GuidanceGroup.can_view?(users(:user_three), guidance_groups(:institution_guidance_group_2).id) + end + + + # ---------- all_viewable ---------- + # ensure that the all_viewable function returns all viewable groups + # should return true for groups owned by funders + # should return true for groups owned by DCC + # should return true for groups owned by the user's organisation + # should not return true for an organisation outwith those above + test "all_viewable returns all dcc groups" do + all_viewable_groups = GuidanceGroup.all_viewable(users(:user_one)) + organisations(:dcc).guidance_groups.each do |group| + assert_includes(all_viewable_groups, group) + end + end + + test "all_viewable returns all funder groups" do + all_viewable_groups = GuidanceGroup.all_viewable(users(:user_one)) + organisation_types(:funder).organisations.each do |org| + org.guidance_groups.each do |group| + assert_includes(all_viewable_groups, group) + end + end + end + + test "all_viewable returns all of a user's organisations's guidances" do + all_viewable_groups_one = GuidanceGroup.all_viewable(users(:user_one)) + organisations(:aru).guidance_groups.each do |group| + assert_includes(all_viewable_groups_one, group) + end + + all_viewable_groups_two = GuidanceGroup.all_viewable(users(:user_two)) + organisations(:au).guidance_groups.each do |group| + assert_includes(all_viewable_groups_two, group) + end + + all_viewable_groups_three = GuidanceGroup.all_viewable(users(:user_three)) + organisations(:bu).guidance_groups.each do |group| + assert_includes(all_viewable_groups_three, group) + end + end + + test "all_viewable does not return any other organisaition's guidance" do + all_viewable_groups = GuidanceGroup.all_viewable(users(:user_one)) + all_viewable_groups.delete_if do |group| + if group.organisation.id == organisations(:dcc).id + true + elsif group.organisation.organisation_type.id == organisation_types(:funder).id + true + elsif group.organisation.id == users(:user_one).organisations.first.id + true + else + false + end + end + assert_empty(all_viewable_groups) + end + + + # ---------- display_name ---------- + test "display_name should return an org name for an org with one guidance" do + assert_equal(guidance_groups(:funder_guidance_group_1).display_name, "Arts and Humanities Research Council", "result of display_name for an org with one group should be the org name") + end + + test "display_name should return an org and group name for an org with more than one guidance" do + assert_equal(guidance_groups(:institution_guidance_group_4).display_name, "Bangor University: Bangor University guidance group 2", "result of display_name for an org with more than one group should be : ") + end + + # ---------- self.guidance_groups_excluding ---------- + test "guidance_groups_excluding should not return a group belonging to specified single org" do + # generate a list + excluding_list = GuidanceGroup.guidance_groups_excluding([organisations(:dcc)]) + excluding_list.each do |group| + refute_equal(group.organisation, organisations(:dcc), "#{group.name} is owned by dcc") + end + end + + test "guidance_groups_excluding should not return a group belonging to specified orgs" do + org_list = [organisations(:ahrc), organisations(:bu)] + excluding_list = GuidanceGroup.guidance_groups_excluding(org_list) + excluding_list.each do |group| + org_list.each do |org| + refute_equal(group.organisation, org, "#{group.name} is owned by specified org: #{org.name}") + end + end + end + + test "guidance_groups_excluding should return all groups not belonging to the specified org" do + excluding_list = GuidanceGroup.guidance_groups_excluding([organisations(:dcc)]) + GuidanceGroup.all.each do |group| + if group.organisation_id != organisations(:dcc).id + assert_includes(excluding_list, group, "#{group.name} is not owned by dcc so should be included") + end + end + end + + test "guidance_groups_excluding should return all groups not belonging to specified orgs" do + excluded =false + org_list = [organisations(:ahrc), organisations(:bu)] + excluding_list = GuidanceGroup.guidance_groups_excluding(org_list) + GuidanceGroup.all.each do |group| + excluded = false + org_list.each do |org| + if group.organisation == org + excluded = true + end + end + unless excluded + assert_includes(excluding_list, group, "#{group.name} is not owned by a specified org so should be included") + end + end + end + +end + + + + + + diff --git a/test/unit/guidance_test.rb b/test/unit/guidance_test.rb index 06d7648..8331207 100644 --- a/test/unit/guidance_test.rb +++ b/test/unit/guidance_test.rb @@ -1,56 +1,56 @@ require 'test_helper' class GuidanceTest < ActiveSupport::TestCase - # ensure that the can_view function returns true all viewable guidances + # ---------- can_view? ---------- + # ensure that the can_view? function returns true all viewable guidances # should return true for groups owned by funders # should return true for groups owned by DCC # should return true for groups owned by the user's organisation # should not return true for an organisation outwith those above test "DCC guidances should be viewable" do guidance_groups(:dcc_guidance_group_1).guidances.each do |guidance| - assert Guidance.can_view(users(:user_one), guidance.id) + assert Guidance.can_view?(users(:user_one), guidance.id) end end test "Funder guidances should be viewable" do - assert Guidance.can_view(users(:user_one), guidances(:ahrc_funder_guidance).id) - assert Guidance.can_view(users(:user_one), guidances(:bbsrc_funder_guidance).id) + assert Guidance.can_view?(users(:user_one), guidances(:ahrc_funder_guidance).id) + assert Guidance.can_view?(users(:user_one), guidances(:bbsrc_funder_guidance).id) end + test "User's organisation guidances should be viewable" do - Organisation.find_by(id: users(:user_one).organisation_id) do |org| - logger.debug "#{org.name}" - end - assert Guidance.can_view(users(:user_one), guidances(:aru_institution_guidance).id) , "user_one cannot view aru_institution_guidance" + assert Guidance.can_view?(users(:user_one), guidances(:aru_institution_guidance).id) , "user_one cannot view aru_institution_guidance" - assert Guidance.can_view(users(:user_two), guidances(:au_institution_guidance_1).id), "user_two cannot view au_..._1" - assert Guidance.can_view(users(:user_two), guidances(:au_institution_guidance_2).id), "user_two cannot view au_..._2" + assert Guidance.can_view?(users(:user_two), guidances(:au_institution_guidance_1).id), "user_two cannot view au_..._1" + assert Guidance.can_view?(users(:user_two), guidances(:au_institution_guidance_2).id), "user_two cannot view au_..._2" - assert Guidance.can_view(users(:user_three), guidances(:bu_institution_guidance_1).id), "user_three cannot view bu_..._1" - assert Guidance.can_view(users(:user_three), guidances(:bu_institution_guidance_2).id), "user_three cannot view bu_..._2" + assert Guidance.can_view?(users(:user_three), guidances(:bu_institution_guidance_1).id), "user_three cannot view bu_..._1" + assert Guidance.can_view?(users(:user_three), guidances(:bu_institution_guidance_2).id), "user_three cannot view bu_..._2" end + test "No other organisations's guidances should be viewable" do # TOOD: add more fixtures with new types of guidances(i.e. not institution) # and add test cases - assert_not Guidance.can_view(users(:user_one), guidances(:au_institution_guidance_1).id) - assert_not Guidance.can_view(users(:user_one), guidances(:au_institution_guidance_2).id) - assert_not Guidance.can_view(users(:user_one), guidances(:bu_institution_guidance_1).id) - assert_not Guidance.can_view(users(:user_one), guidances(:bu_institution_guidance_2).id) + assert_not Guidance.can_view?(users(:user_one), guidances(:au_institution_guidance_1).id) + assert_not Guidance.can_view?(users(:user_one), guidances(:au_institution_guidance_2).id) + assert_not Guidance.can_view?(users(:user_one), guidances(:bu_institution_guidance_1).id) + assert_not Guidance.can_view?(users(:user_one), guidances(:bu_institution_guidance_2).id) - assert_not Guidance.can_view(users(:user_two), guidances(:aru_institution_guidance).id) - assert_not Guidance.can_view(users(:user_two), guidances(:bu_institution_guidance_1).id) - assert_not Guidance.can_view(users(:user_two), guidances(:bu_institution_guidance_2).id) + assert_not Guidance.can_view?(users(:user_two), guidances(:aru_institution_guidance).id) + assert_not Guidance.can_view?(users(:user_two), guidances(:bu_institution_guidance_1).id) + assert_not Guidance.can_view?(users(:user_two), guidances(:bu_institution_guidance_2).id) - assert_not Guidance.can_view(users(:user_three), guidances(:aru_institution_guidance).id) - assert_not Guidance.can_view(users(:user_three), guidances(:au_institution_guidance_1).id) - assert_not Guidance.can_view(users(:user_three), guidances(:au_institution_guidance_2).id) + assert_not Guidance.can_view?(users(:user_three), guidances(:aru_institution_guidance).id) + assert_not Guidance.can_view?(users(:user_three), guidances(:au_institution_guidance_1).id) + assert_not Guidance.can_view?(users(:user_three), guidances(:au_institution_guidance_2).id) end - +# ---------- all_viewable ---------- # ensure that the all_viewable function returns all viewable guidances # should return true for groups owned by funders # should return true for groups owned by DCC @@ -58,8 +58,10 @@ # should not return true for an organisation outwith those above test "all_viewable returns all DCC guidances" do all_viewable_guidances = Guidance.all_viewable(users(:user_one)) - guidance_groups(:dcc_guidance_group_1).guidances.each do |guidance| - assert_includes(all_viewable_guidances, guidance) + organisations(:dcc).guidance_groups.each do |group| + group.guidances.each do |guidance| + assert_includes(all_viewable_guidances, guidance) + end end end @@ -73,6 +75,7 @@ end end + test "all_viewable returns all of a user's organisations's guidances" do all_viewable_guidances_one = Guidance.all_viewable(users(:user_one)) organisations(:aru).guidance_groups.each do |group| @@ -96,8 +99,75 @@ end end + test "all_viewable does not return any other organisation's guidance" do # TODO: Add in a suitable test. should we check for non-institutions? - flunk() + all_viewable_guidances = Guidance.all_viewable(users(:user_one)) + # remove all of the user's organisation + # remove all of each funder's organisations + # remove each of the dcc's organisations + # check if nill + all_viewable_guidances.delete_if do |guidance| + guidance.guidance_groups.each do |group| + if group.organisation.id == organisations(:dcc).id + true + elsif group.organisation.organisation_type.id == organisation_types(:funder).id + true + elsif group.organisation.id == users(:user_one).organisations.first.id + true + else + false + end + end + end + assert_empty(all_viewable_guidances, "there must not be any guidances which are not funders, DCC, or our own organisation") end + + # ---------- in_group_belonging_to? ---------- + test "in_group_belonging_to correctly identifies parent orgs" do + # test that the association works for all correct usages + Guidance.all.each do |guidance| + guidance.guidance_groups.each do |group| + assert(guidance.in_group_belonging_to?(group.organisation.id), "Guidance: #{guidance.text} should belong to organisation #{group.organisation.name}") + end + end + end + + test "in_group_belonging_to rejects non-parent orgs" do + # test that in_group_belonging_to rejects a few interesting organisation-guidance pairs + assert_not(guidances(:related_policies).in_group_belonging_to?(organisations(:ahrc)), "Organisation ahrc does not own guidance: related policies") + assert_not(guidances(:ahrc_funder_guidance).in_group_belonging_to?(organisations(:dcc)), "Organisation dcc does not own guidance: ahrc_funder_guidance") + end + + # ---------- by_organisation ---------- + test "by_organisation correctly returns all guidance belonging to a given org" do + Organisation.all.each do |org| + org_guidance = Guidance.by_organisation(org) + org.guidance_groups.each do |group| + group.guidances.each do |guidance| + assert_includes(org_guidance, guidance, "Guidance #{guidance.text} should belong to organisation: #{org.name}") + end + end + end + end + + # ---------- get_guidance_group_templates ---------- + ## the main function is completely bugged, so ask to remove it + # test "get_guidance_group_templates retuns all templates belonging to a guidance group" do + # GuidanceGroup.all.each do |group| + # group_templates = guidances(:related_policies).get_guidance_group_templates?(group) + # group.dmptemplates.each do |template| + # assert_includes(group_templates, template, "group #{group.name} should include template #{template.title}") + # end + # end + # end + end + + + + + + + + diff --git a/test/unit/organisation_test.rb b/test/unit/organisation_test.rb index 8dc35ff..e503b4c 100644 --- a/test/unit/organisation_test.rb +++ b/test/unit/organisation_test.rb @@ -1,7 +1,85 @@ require 'test_helper' class OrganisationTest < ActiveSupport::TestCase - # test "the truth" do - # assert true - # end + + # ---------- short_name ---------- + test "short_name should return the abbreviation if it exists" do + assert_equal(organisations(:dcc).short_name, organisations(:dcc).abbreviation, "Org: DCC has an abreviation and should return it") + end + + test "short_name should return the name if no abbreviation exists" do + assert_equal(organisations(:aru).short_name, organisations(:aru).name, "Org: ARU has no abbreviation and should return it's full name") + end + + # ---------- self.orgs_with_parent_of_type ---------- + test "self.orgs_with_parent_of_type correctly identifies organisation trees" do + children = Organisation.orgs_with_parent_of_type("institution") + assert_includes(children, organisations(:institution_child_one), "Org: institution_child_one is a child of an institution") + end + + # ---------- self.other_organisations ---------- + test "self.other_organisations correctly returns ___" do + + end + + # ---------- all_sections ---------- + test "all_sections returns correct sections" do + sections = organisations(:dcc).all_sections(versions(:DCC_phase_1_version_1).id) + org_sections = Section.find_by(organisation: organisations(:dcc)) + org_sections.each do |section| + if section.version_id == versions(:DCC_phase_1_version_1).id + assert_includes(sections, section, "Section: #{section.title} should be included") + end + end + end + + test "all_sections returns a parents sections" do + sections = organisations(:institution_child_one).all_sections(versions(:institution_child_version_1).id) + assert_includes( sections, sections(:institution_parent_1), "all_sections should return it's parent's sections") + assert_includes( sections, sections(:institution_parent_2), "all_sections should return it's parent's sections") + end + + test "all_sections returns [] if no sections are found" do + sections = organisations(:dcc).all_sections(versions(:institution_child_version_1).id) + assert_empty( sections, "no sections of that version exist") + end + + # ---------- all_guidance_groups ---------- + test "all_guidance_groups returns all of the organisations guidance groups" do + all_groups = organisations(:dcc).all_guidance_groups + organisations(:dcc).guidance_groups.each do |group| + assert_includes(all_groups, group, "group: #{group.name} belongs to the specified org") + end + end + + test "all_guidance_groups returns all of the organisations children's guidance groups" do + all_groups = organisations(:institution_parent).all_guidance_groups + organisations(:institution_child_one).guidance_groups.each do |group| + assert_includes(all_groups, group, "group: #{group.name} belongs to the specified org") + end + end + + # ---------- root ---------- + test "root correctly identifies the parent organisation" do + assert_equal(organisations(:institution_child_one).root, organizations(:institution_parent), "institution parent is the parent of institution child one") + end + + test "root returns self if an organisation has no parents" do + assert_equal(organisations(:dcc).root, organisations(:dcc), "dcc has no parent, so is root") + end + + # ---------- warning ---------- + test "warning returns specified warning if not nil" do + flunk + end + + test "warning returns the parent's warning if nil" do + flunk + end + + # ---------- published_templates ---------- + test "published_templates returns all owned and published templates" do + flunk + end + end