hydra-grouper 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 56bf00c1162533a8c0d49cc65f8722350ac1d4b3
4
+ data.tar.gz: bd9e73eb4d9696cad372d1ff8cdb6e47217602c9
5
+ SHA512:
6
+ metadata.gz: '08123d9e3567c7a2017fd8ad4f70cceec6a6ead817cd994322ff8b5c99c5cea93b22d397fc31a086a1057f7880e3119b7fa01603bea48e78b9e15e1be75fcaf9'
7
+ data.tar.gz: 2bc243cba30de26f97318f7b0a6cf856010367b720313e8e621ea06188e0c48ccccd55b63147e14fb29b153a28cee3995c1d3e4b0f477e907e91e5cffc6022c2
@@ -0,0 +1,25 @@
1
+ ---
2
+ engines:
3
+ duplication:
4
+ enabled: true
5
+ config:
6
+ languages:
7
+ - ruby
8
+ - javascript
9
+ - python
10
+ - php
11
+ fixme:
12
+ enabled: true
13
+ rubocop:
14
+ enabled: true
15
+ ratings:
16
+ paths:
17
+ - "**.inc"
18
+ - "**.js"
19
+ - "**.jsx"
20
+ - "**.module"
21
+ - "**.php"
22
+ - "**.py"
23
+ - "**.rb"
24
+ exclude_paths:
25
+ - spec/
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .ruby-version
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,59 @@
1
+ require: rubocop-rspec
2
+
3
+ AllCops:
4
+ TargetRubyVersion: 2.1
5
+ DisplayCopNames: true
6
+ Include:
7
+ - '**/Rakefile'
8
+ - '**/config.ru'
9
+
10
+ Metrics/LineLength:
11
+ Max: 140
12
+
13
+ Metrics/MethodLength:
14
+ Max: 10
15
+
16
+ Metrics/BlockLength:
17
+ Exclude:
18
+ - 'spec/**/*_spec.rb'
19
+
20
+ Style/IndentationConsistency:
21
+ EnforcedStyle: rails
22
+
23
+ Style/CollectionMethods:
24
+ PreferredMethods:
25
+ collect: 'map'
26
+ collect!: 'map!'
27
+ inject: 'reduce'
28
+ detect: 'find'
29
+ find_all: 'select'
30
+
31
+ Style/WordArray:
32
+ Enabled: false
33
+
34
+ Style/RegexpLiteral:
35
+ Enabled: false
36
+
37
+ Style/StringLiterals:
38
+ Enabled: false
39
+
40
+ Rails:
41
+ Enabled: true
42
+
43
+ # By default RSpec/MessageSpies has the following:
44
+ # Prefer have_received for setting message expectations. Setup form as a spy using allow or instance_spy.
45
+ # The default assumes EnforcedStyle is 'have_received'. Most of our specs are 'receive'
46
+ RSpec/MessageSpies:
47
+ Enabled: true
48
+ EnforcedStyle: receive
49
+
50
+ RSpec/MultipleExpectations:
51
+ Enabled: false
52
+
53
+ Style/FileName:
54
+ Exclude:
55
+ - Gemfile
56
+ - hydra-grouper.gemspec
57
+
58
+ Style/SymbolArray:
59
+ Enabled: false
@@ -0,0 +1,20 @@
1
+ language: ruby
2
+ sudo: false
3
+
4
+ cache:
5
+ bundler: true
6
+
7
+ before_install:
8
+ - gem update --system
9
+ rvm:
10
+ - 2.3.3
11
+ - 2.4.0
12
+ env:
13
+ global:
14
+ - NOKOGIRI_USE_SYSTEM_LIBRARIES=true
15
+ matrix:
16
+ - "RAILS_VERSION=5.0.1"
17
+
18
+ addons:
19
+ code_climate:
20
+ repo_token: bb4cf766a96a21a484f4a6f147b97aade80919bf278296b0e3e8a662d6507c81
@@ -0,0 +1,159 @@
1
+ # How to Contribute
2
+
3
+ We want your help to make Project Hydra great.
4
+ There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things.
5
+
6
+ ## Code of Conduct
7
+
8
+ The Hydra community is dedicated to providing a welcoming and positive experience for all its
9
+ members, whether they are at a formal gathering, in a social setting, or taking part in activities
10
+ online. Please see our [Code of Conduct](https://wiki.duraspace.org/display/hydra/Code+of+Conduct)
11
+ for more information.
12
+
13
+ ## Hydra Project Intellectual Property Licensing and Ownership
14
+
15
+ All code contributors must have an Individual Contributor License Agreement (iCLA) on file with the Hydra Project Steering Group.
16
+ If the contributor works for an institution, the institution must have a Corporate Contributor License Agreement (cCLA) on file.
17
+
18
+ https://wiki.duraspace.org/display/hydra/Hydra+Project+Intellectual+Property+Licensing+and+Ownership
19
+
20
+ You should also add yourself to the `CONTRIBUTORS.md` file in the root of the project.
21
+
22
+ ## Contribution Tasks
23
+
24
+ * Reporting Issues
25
+ * Making Changes
26
+ * Documenting Code
27
+ * Committing Changes
28
+ * Submitting Changes
29
+ * Reviewing and Merging Changes
30
+
31
+ ### Reporting Issues
32
+
33
+ * Make sure you have a [GitHub account](https://github.com/signup/free)
34
+ * Submit a [Github issue](./issues) by:
35
+ * Clearly describing the issue
36
+ * Provide a descriptive summary
37
+ * Explain the expected behavior
38
+ * Explain the actual behavior
39
+ * Provide steps to reproduce the actual behavior
40
+
41
+ ### Making Changes
42
+
43
+ * Fork the repository on GitHub
44
+ * Create a topic branch from where you want to base your work.
45
+ * This is usually the master branch.
46
+ * To quickly create a topic branch based on master; `git branch fix/master/my_contribution master`
47
+ * Then checkout the new branch with `git checkout fix/master/my_contribution`.
48
+ * Please avoid working directly on the `master` branch.
49
+ * You may find the [hub suite of commands](https://github.com/defunkt/hub) helpful
50
+ * Make sure you have added sufficient tests and documentation for your changes.
51
+ * Test functionality with RSpec; est features / UI with Capybara.
52
+ * Run _all_ the tests to assure nothing else was accidentally broken.
53
+
54
+ ### Documenting Code
55
+
56
+ * All new public methods, modules, and classes should include inline documentation in [YARD](http://yardoc.org/).
57
+ * Documentation should seek to answer the question "why does this code exist?"
58
+ * Document private / protected methods as desired.
59
+ * If you are working in a file with no prior documentation, do try to document as you gain understanding of the code.
60
+ * If you don't know exactly what a bit of code does, it is extra likely that it needs to be documented. Take a stab at it and ask for feedback in your pull request. You can use the 'blame' button on GitHub to identify the original developer of the code and @mention them in your comment.
61
+ * This work greatly increases the usability of the code base and supports the on-ramping of new committers.
62
+ * We will all be understanding of one another's time constraints in this area.
63
+ * YARD examples:
64
+ * [Hydra::Works::RemoveGenericFile](https://github.com/projecthydra-labs/hydra-works/blob/master/lib/hydra/works/services/generic_work/remove_generic_file.rb)
65
+ * [ActiveTriples::LocalName::Minter](https://github.com/ActiveTriples/active_triples-local_name/blob/master/lib/active_triples/local_name/minter.rb)
66
+ * [Getting started with YARD](http://www.rubydoc.info/gems/yard/file/docs/GettingStarted.md)
67
+
68
+ ### Committing changes
69
+
70
+ * Make commits of logical units.
71
+ * Your commit should include a high level description of your work in HISTORY.textile
72
+ * Check for unnecessary whitespace with `git diff --check` before committing.
73
+ * Make sure your commit messages are [well formed](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
74
+ * If you created an issue, you can close it by including "Closes #issue" in your commit message. See [Github's blog post for more details](https://github.com/blog/1386-closing-issues-via-commit-messages)
75
+
76
+ ```
77
+ Present tense short summary (50 characters or less)
78
+
79
+ More detailed description, if necessary. It should be wrapped to 72
80
+ characters. Try to be as descriptive as you can, even if you think that
81
+ the commit content is obvious, it may not be obvious to others. You
82
+ should add such description also if it's already present in bug tracker,
83
+ it should not be necessary to visit a webpage to check the history.
84
+
85
+ Include Closes #<issue-number> when relavent.
86
+
87
+ Description can have multiple paragraphs and you can use code examples
88
+ inside, just indent it with 4 spaces:
89
+
90
+ class PostsController
91
+ def index
92
+ respond_to do |wants|
93
+ wants.html { render 'index' }
94
+ end
95
+ end
96
+ end
97
+
98
+ You can also add bullet points:
99
+
100
+ - you can use dashes or asterisks
101
+
102
+ - also, try to indent next line of a point for readability, if it's too
103
+ long to fit in 72 characters
104
+ ```
105
+
106
+ ### Submitting Changes
107
+
108
+ * Read the article ["Using Pull Requests"](https://help.github.com/articles/using-pull-requests) on GitHub.
109
+ * Make sure your branch is up to date with its parent branch (i.e. master)
110
+ * `git checkout master`
111
+ * `git pull --rebase`
112
+ * `git checkout <your-branch>`
113
+ * `git rebase master`
114
+ * It is a good idea to run your tests again.
115
+ * If you've made more than one commit take a moment to consider whether squashing commits together would help improve their logical grouping.
116
+ * [Detailed Walkthrough of One Pull Request per Commit](http://ndlib.github.io/practices/one-commit-per-pull-request/)
117
+ * `git rebase --interactive master` ([See Github help](https://help.github.com/articles/interactive-rebase))
118
+ * Squashing your branch's changes into one commit is "good form" and helps the person merging your request to see everything that is going on.
119
+ * Push your changes to a topic branch in your fork of the repository.
120
+ * Submit a pull request from your fork to the project.
121
+
122
+ ### Reviewing and Merging Changes
123
+
124
+ We adopted [Github's Pull Request Review](https://help.github.com/articles/about-pull-request-reviews/) for our repositories.
125
+ Common checks that may occur in our repositories:
126
+
127
+ 1. Travis CI - where our automated tests are running
128
+ 2. Hound CI - where we check for style violations
129
+ 3. Approval Required - Github enforces at least one person approve a pull request. Also, all reviewers that have chimed in must approve.
130
+ 4. CodeClimate - is our code remaining healthy (at least according to static code analysis)
131
+
132
+ If one or more of the required checks failed (or are incomplete), the code should not be merged (and the UI will not allow it). If all of the checks have passed, then anyone on the project (including the pull request submitter) may merge the code.
133
+
134
+ *Example: Carolyn submits a pull request, Justin reviews the pull request and approves. However, Justin is still waiting on other checks (Travis CI is usually the culprit), so he does not merge the pull request. Eventually, all of the checks pass. At this point, Carolyn or anyone else may merge the pull request.*
135
+
136
+ #### Things to Consider When Reviewing
137
+
138
+ First, the person contributing the code is putting themselves out there. Be mindful of what you say in a review.
139
+
140
+ * Ask clarifying questions
141
+ * State your understanding and expectations
142
+ * Provide example code or alternate solutions, and explain why
143
+
144
+ This is your chance for a mentoring moment of another developer. Take time to give an honest and thorough review of what has changed. Things to consider:
145
+
146
+ * Does the commit message explain what is going on?
147
+ * Does the code changes have tests? _Not all changes need new tests, some changes are refactors_
148
+ * Do new or changed methods, modules, and classes have documentation?
149
+ * Does the commit contain more than it should? Are two separate concerns being addressed in one commit?
150
+ * Does the description of the new/changed specs match your understanding of what the spec is doing?
151
+
152
+ If you are uncertain, bring other contributors into the conversation by assigning them as a reviewer.
153
+
154
+ # Additional Resources
155
+
156
+ * [General GitHub documentation](http://help.github.com/)
157
+ * [GitHub pull request documentation](http://help.github.com/send-pull-requests/)
158
+ * [Pro Git](http://git-scm.com/book) is both a free and excellent book about Git.
159
+ * [A Git Config for Contributing](http://ndlib.github.io/practices/my-typical-per-project-git-config/)
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in hydra-grouper.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ##########################################################################
2
+ # Copyright 2017 University of Notre Dame
3
+ # Additional copyright may be held by others, as reflected in the commit log
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
@@ -0,0 +1,129 @@
1
+ # Hydra::Grouper
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/hydra-grouper.png)](https://badge.fury.io/rb/hydra-grouper)
4
+ [![Build Status](https://travis-ci.org/projecthydra-labs/hydra-grouper.png?branch=master)](https://travis-ci.org/projecthydra-labs/hydra-grouper)
5
+ [![Code Climate](https://codeclimate.com/github/projecthydra-labs/hydra-grouper/badges/gpa.svg)](https://codeclimate.com/github/projecthydra-labs/hydra-grouper)
6
+ [![Test Coverage](https://codeclimate.com/github/projecthydra-labs/hydra-grouper/badges/coverage.svg)](https://codeclimate.com/github/projecthydra-labs/hydra-grouper/coverage)
7
+ [![Documentation Status](http://inch-ci.org/github/projecthydra-labs/hydra-grouper.svg?branch=master)](http://inch-ci.org/github/projecthydra-labs/hydra-grouper)
8
+ [![APACHE 2 License](http://img.shields.io/badge/APACHE2-license-blue.svg)](./LICENSE)
9
+ [![Contributing Guidelines](http://img.shields.io/badge/CONTRIBUTING-Guidelines-blue.svg)](./CONTRIBUTING.md)
10
+
11
+ ## Details
12
+
13
+ A work in progress. See the example implementation for details. The big benefit of this refactor is we can say:
14
+
15
+ For a given user, what are all of my application abilities; That is to say what can I specifically do. It still requires reading the ruby code for the specific details of each ApplicationAbility that I have.
16
+
17
+ ### Glossary
18
+
19
+ * User - A single person
20
+ * Group - Users may be members of groups
21
+ * FunctionalRole - For combining the application abilities that are all needed to perform a conceptual activity (think of this as a molecule). There is a relationship between a FunctionalRole and either a User or a Group. We are working on naming that concept (for now lets call it assignee).
22
+ * Hyrax::ApplicationAbility - see below (think of this as an atom)
23
+
24
+ ### Example Implementation
25
+
26
+ ```ruby
27
+ class User < ActiveRecord::Base
28
+ has_many :groups, through: :group_memberships
29
+ has_many :group_memberships
30
+ has_many :functional_roles, as: :assignee
31
+ end
32
+
33
+ class GroupMembership < ActiveRecord::Base
34
+ belongs_to :user
35
+ belongs_to :group
36
+ end
37
+
38
+ class Group < ActiveRecord::Base
39
+ has_many :group_memberships
40
+ has_many :users, through: :group_memberships
41
+ has_many :functional_roles, as: :assignee
42
+ end
43
+
44
+ class FunctionalRole < ActiveRecord::Base
45
+ belongs_to :assignee, polymorphic: true
46
+ has_many :functional_abilities
47
+ end
48
+
49
+ class FunctionalAbility < ActiveRecord::Base
50
+ belongs_to :functional_role
51
+
52
+ def application_ability_class
53
+ # We have a column :application_ability_class_name
54
+ # with an example value of Hyrax::ApplicationAbility::AdminApplicationAbility
55
+ application_ability_class_name.constantize
56
+ end
57
+ end
58
+
59
+ module Hyrax # This should perhaps be pushed into the Hydra namespace.
60
+ module ApplicationAbility
61
+ # @api public
62
+ #
63
+ # Applies the functional abilities to the given ability based on the given ability's current_user.
64
+ # This allows for us to plugin additional abilities in implementing applications without the explicit need
65
+ # to re-open the Ability class. (more on that later).
66
+ #
67
+ # @param [Ability] ability - an object that implements the CanCan::Ability interface
68
+ # @return [Ability]
69
+ def self.append_abilities_to!(ability:)
70
+ functionality_abilities_for(user: ability.current_user).each do |functional_ability|
71
+ functional_ability.new(ability: ability).apply
72
+ end
73
+ ability
74
+ end
75
+
76
+ # @api public
77
+ #
78
+ # For the given user, return an enumerable of all of the ApplicationAbility objects
79
+ # that apply, based on the user and their group memberships relation to their Functional Role
80
+ # at the institution
81
+ #
82
+ # @param [User] user for which we are looking up their assigned functional abilities.
83
+ # @return [Array<Hyrax::ApplicationAbility::BaseApplicationAbility]
84
+ # @note This is the place for the new and improved user groups to be leveraged
85
+ def self.functionality_abilities_for(user:)
86
+ # TODO: Define an implementation of how this is looked up
87
+ end
88
+
89
+ # An abstract class that defines the interface for implementations of a ApplicationAbility.
90
+ # A ApplicationAbility is a name-able atomic unit of permissions.
91
+ class BaseApplicationAbility
92
+ extend Forwardable
93
+ def initialize(ability:)
94
+ @ability = ability
95
+ end
96
+ def_delegators :@ability, :can, all # etc.
97
+
98
+ def apply
99
+ raise NotImplementedError, "Subclasses must implement #apply"
100
+ end
101
+ end
102
+
103
+ # The set of specific cans and cannots that are applicable for an Admin.
104
+ class AdminApplicationAbility < BaseApplicationAbility
105
+ def apply
106
+ # NOTE: We are removing the short-circuit tradition of a guard `return unless admin?`
107
+ # This ApplicationAbility will not be applied if it is not one of your functional roles at the institution.
108
+ can :read, :admin_dashboard
109
+ end
110
+ end
111
+ end
112
+
113
+ module Ability
114
+ extend ActiveSupport::Concern
115
+
116
+ # @note assumes we are previously including Hydra::Ability
117
+ def hydra_default_permissions
118
+ super
119
+ apply_functional_abilities
120
+ end
121
+
122
+ private
123
+
124
+ def apply_functional_abilities
125
+ Hyrax::ApplicationAbility.append_abilities_to!(ability: self)
126
+ end
127
+ end
128
+ end
129
+ ```
@@ -0,0 +1,40 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ begin
7
+ require 'rubocop/rake_task'
8
+
9
+ desc 'Run style checker'
10
+ RuboCop::RakeTask.new(:rubocop) do |task|
11
+ task.requires << 'rubocop-rspec'
12
+ task.fail_on_error = true
13
+ end
14
+ task spec: :rubocop
15
+ rescue LoadError
16
+ $stderr.puts "Unable to load Rubocop"
17
+ end
18
+
19
+ task :configure_test_for_code_coverage do
20
+ ENV['COVERAGE'] = 'true'
21
+ end
22
+
23
+ task :code_coverage do
24
+ require 'json'
25
+ $stdout.puts "Checking code_coverage"
26
+ coverage_percentage = JSON.parse(File.read('coverage/.last_run.json')).fetch('result').fetch('covered_percent').to_i
27
+ goal = 100
28
+ if goal > coverage_percentage
29
+ abort("Code Coverage Goal Not Met:\n\t#{coverage_percentage}%\tExpected\n\t#{goal}%\tActual")
30
+ end
31
+ end
32
+
33
+ task(
34
+ default: [
35
+ 'rubocop',
36
+ 'configure_test_for_code_coverage',
37
+ 'spec',
38
+ 'code_coverage'
39
+ ]
40
+ )
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "hydra/grouper"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,34 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'hydra/grouper/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "hydra-grouper"
8
+ spec.version = Hydra::Grouper::VERSION
9
+ spec.authors = ["Jeremy Friesen"]
10
+ spec.email = ["jeremy.n.friesen@gmail.com"]
11
+ spec.license = "Apache-2.0"
12
+
13
+ spec.summary = "Hydra Group / Role and General Conjecture"
14
+ spec.description = "The long awaited separation of groups and roles for Project Hydra."
15
+ spec.homepage = "https://github.com/projecthydra-labs/hydra-grouper"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_dependency 'dry-equalizer', "~> 0.2"
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.13"
27
+ spec.add_development_dependency "codeclimate-test-reporter"
28
+ spec.add_development_dependency "rails", ">= 4.2"
29
+ spec.add_development_dependency "rake", "~> 10.0"
30
+ spec.add_development_dependency "rspec", "~> 3.0"
31
+ spec.add_development_dependency "rubocop"
32
+ spec.add_development_dependency "rubocop-rspec"
33
+ spec.add_development_dependency "simplecov"
34
+ end
@@ -0,0 +1,60 @@
1
+ require "hydra/grouper/version"
2
+ require 'hydra/grouper/configuration'
3
+ require 'hydra/grouper/exceptions'
4
+ require 'hydra/grouper/railtie' if defined?(Rails)
5
+
6
+ # Namespace for projecthydra modules
7
+ module Hydra
8
+ # A namespace module for configuring and managing group and role adapters
9
+ module Grouper
10
+ # @api public
11
+ # @return an object that conforms to the Hydra::Grouper::GroupAdapterInterface
12
+ def self.group_adapter
13
+ configuration.group_adapter
14
+ end
15
+
16
+ # @api public
17
+ # @return an object that conforms to the Hydra::Grouper::InstitutionFunctionAdapterInterface
18
+ def self.institution_function_adapter
19
+ configuration.institution_function_adapter
20
+ end
21
+
22
+ # @api public
23
+ #
24
+ # Contains the Hydra::Grouper configuration information that is referenceable from wit
25
+ #
26
+ # @return [Hydra::Group::Configuration]
27
+ # @see Hydra::Group::Configuration
28
+ def self.configuration
29
+ @configuration ||= Configuration.new
30
+ end
31
+
32
+ # @api public
33
+ #
34
+ # Capture the configuration information
35
+ #
36
+ # @yield [Hydra::Group::Configuration]
37
+ # @see Hydra::Group::Configuration
38
+ # @see .configuration
39
+ # @see Hydra::Group::Railtie
40
+ def self.configure(&block)
41
+ @configuration_block = block
42
+ # The Rails load sequence means that some of the configured Targets may
43
+ # not be loaded; As such I am not calling configure! instead relying on
44
+ # Hydra::Group::Railtie to handle the configure! call
45
+ configure! unless defined?(Rails)
46
+ end
47
+
48
+ # Responsible for performing the configuration operation.
49
+ #
50
+ # @return [TrueClass] if configuration was performed
51
+ # @return [FalseClass] if configuration was not performed
52
+ # @api private
53
+ def self.configure!
54
+ return false unless @configuration_block.respond_to?(:call)
55
+ @configuration_block.call(configuration)
56
+ @configuration_block = nil
57
+ true
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,27 @@
1
+ module Hydra
2
+ # :nodoc:
3
+ module Grouper
4
+ # @api public
5
+ #
6
+ # Responsible for the configuration of the Hydra::Grouper
7
+ class Configuration
8
+ # @api public
9
+ # @return an object that conforms to the Hydra::Grouper::Interfaces::GroupAdapterInterface
10
+ attr_reader :group_adapter
11
+
12
+ # @api public
13
+ # @param input an object that conforms to the Hydra::Grouper::Interfaces::GroupAdapterInterface
14
+ # @todo Enfroce interface when set
15
+ attr_writer :group_adapter
16
+
17
+ # @api public
18
+ # @return an object that conforms to the Hydra::Grouper::Interfaces::InstitutionFunctionAdapterInterface
19
+ attr_reader :institution_function_adapter
20
+
21
+ # @api public
22
+ # @param input an object that conforms to the Hydra::Grouper::Interfaces::InstitutionFunctionAdapterInterface
23
+ # @todo Enfroce interface when set
24
+ attr_writer :institution_function_adapter
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,10 @@
1
+ module Hydra
2
+ module Grouper
3
+ # The container for exceptions for Hydra::Grouper
4
+ module Exceptions
5
+ # Isolating a common exception to assist with debugging.
6
+ class RuntimeError < ::RuntimeError
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,17 @@
1
+ module Hydra
2
+ module Grouper
3
+ # Exposes the interface we are expecting for Group interactions
4
+ class GroupAdapterInterface
5
+ # @return [Array<GroupValueOjbect>] A list of unique GroupValueObject
6
+ def all_groups; end
7
+
8
+ # @param [String] user_key
9
+ # @return [Array<GroupValueOjbect>] A list of unique GroupValueObject
10
+ def groups_for(user_key:); end
11
+
12
+ # @param [String] group_key
13
+ # @return [Array<String>] A list of user keys
14
+ def members_of(group_key:); end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ require 'dry-equalizer'
2
+ module Hydra
3
+ module Grouper
4
+ # A simple PORO that defines the basics of what we mean by a group.
5
+ #
6
+ # A Group is a set of people/users
7
+ class GroupValueObject
8
+ include Dry::Equalizer(:key)
9
+
10
+ def initialize(name:, key:)
11
+ @name = name
12
+ @key = key
13
+ end
14
+
15
+ attr_reader :name, :key
16
+ alias group_key key
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ module Hydra
2
+ module Grouper
3
+ # Exposes the interface we are expecting for InstitutionFunction interactions
4
+ class InstitutionFunctionAdapterInterface
5
+ # @return [Array<InstitutionFunctionValueOjbect>] A list of unique InstitutionFunctionValueOjbect
6
+ def all_institution_functions; end
7
+
8
+ # @param [String] user_key
9
+ # @return [InstitutionFunctionSet>]
10
+ def institution_functions_for(user_key:); end
11
+
12
+ # @param [String] institution_function_key
13
+ # @return [Array<String>]
14
+ def members_of(institution_function_key:); end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ module Hydra
2
+ module Grouper
3
+ # A container object that exposes convenience methods related to the underlying institution_functions set.
4
+ #
5
+ # For a given InstitutionFunctionSet we can ask "are you an admin?"
6
+ class InstitutionFunctionSet
7
+ def initialize(institution_functions: [])
8
+ @institution_functions = institution_functions
9
+ end
10
+
11
+ def admin?
12
+ @institution_functions.detect { |institution_function| institution_function.name == 'admin' }
13
+ end
14
+
15
+ def superadmin?
16
+ @institution_functions.detect { |institution_function| institution_function.name == 'superadmin' }
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ module Hydra
2
+ module Grouper
3
+ # A simple PORO that defines what an agent of an institution can do?
4
+ #
5
+ # The concept formerly known as Roles (because Roles and Groups are getting conflated)
6
+ class InstitutionFunctionValueObject
7
+ include Dry::Equalizer(:key)
8
+
9
+ def initialize(name:, key:)
10
+ @name = name
11
+ @key = key
12
+ end
13
+
14
+ attr_reader :name, :key
15
+ alias institution_function_key key
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ require 'rails/railtie'
2
+
3
+ module Hydra
4
+ module Grouper
5
+ # Connect into the boot sequence of a Rails application
6
+ class Railtie < Rails::Railtie
7
+ config.to_prepare do
8
+ Hydra::Grouper.configure!
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,25 @@
1
+ RSpec.shared_examples 'a Hydra::Grouper group adapter interface' do
2
+ before do
3
+ raise 'adapter must be set with `let(:adapter)`' unless
4
+ defined? adapter
5
+ end
6
+ it { is_expected.to respond_to(:all_groups) }
7
+ describe '#all_groups' do
8
+ it 'requires no parameters' do
9
+ expect(adapter.method(:all_groups).parameters).to eq([])
10
+ end
11
+ end
12
+ it { is_expected.to respond_to(:groups_for) }
13
+ describe '#groups_for' do
14
+ it 'requires a user: keyword arg' do
15
+ expect(adapter.method(:groups_for).parameters).to eq([[:keyreq, :user_key]])
16
+ end
17
+ end
18
+
19
+ it { is_expected.to respond_to(:members_of) }
20
+ describe '#members_of' do
21
+ it 'requires a user: keyword arg' do
22
+ expect(adapter.method(:members_of).parameters).to eq([[:keyreq, :group_key]])
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ RSpec.shared_examples 'a Hydra::Grouper institution function adapter interface' do
2
+ before do
3
+ raise 'adapter must be set with `let(:adapter)`' unless
4
+ defined? adapter
5
+ end
6
+ it { is_expected.to respond_to(:all_institution_functions) }
7
+ describe '#all_institution_functions' do
8
+ it 'requires no parameters' do
9
+ expect(adapter.method(:all_institution_functions).parameters).to eq([])
10
+ end
11
+ end
12
+ it { is_expected.to respond_to(:institution_functions_for) }
13
+ describe '#institution_functions_for' do
14
+ it 'requires a user: keyword arg' do
15
+ expect(adapter.method(:institution_functions_for).parameters).to eq([[:keyreq, :user_key]])
16
+ end
17
+ end
18
+
19
+ it { is_expected.to respond_to(:members_of) }
20
+ describe '#members_of' do
21
+ it 'requires a user: keyword arg' do
22
+ expect(adapter.method(:members_of).parameters).to eq([[:keyreq, :institution_function_key]])
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,6 @@
1
+ module Hydra
2
+ module Grouper
3
+ # Current version of Hydra::Grouper
4
+ VERSION = "0.1.0".freeze
5
+ end
6
+ end
metadata ADDED
@@ -0,0 +1,195 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hydra-grouper
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jeremy Friesen
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-04-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dry-equalizer
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.13'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.13'
41
+ - !ruby/object:Gem::Dependency
42
+ name: codeclimate-test-reporter
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '4.2'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '4.2'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: simplecov
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: The long awaited separation of groups and roles for Project Hydra.
140
+ email:
141
+ - jeremy.n.friesen@gmail.com
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - ".codeclimate.yml"
147
+ - ".gitignore"
148
+ - ".rspec"
149
+ - ".rubocop.yml"
150
+ - ".travis.yml"
151
+ - CONTRIBUTING.md
152
+ - Gemfile
153
+ - LICENSE
154
+ - README.md
155
+ - Rakefile
156
+ - bin/console
157
+ - bin/setup
158
+ - hydra-grouper.gemspec
159
+ - lib/hydra/grouper.rb
160
+ - lib/hydra/grouper/configuration.rb
161
+ - lib/hydra/grouper/exceptions.rb
162
+ - lib/hydra/grouper/group_adapter_interface.rb
163
+ - lib/hydra/grouper/group_value_object.rb
164
+ - lib/hydra/grouper/institution_function_adapter_interface.rb
165
+ - lib/hydra/grouper/institution_function_set.rb
166
+ - lib/hydra/grouper/institution_function_value_object.rb
167
+ - lib/hydra/grouper/railtie.rb
168
+ - lib/hydra/grouper/specs/shared_specs/group_adapter_interface.rb
169
+ - lib/hydra/grouper/specs/shared_specs/institution_function_adapter_interface.rb
170
+ - lib/hydra/grouper/version.rb
171
+ homepage: https://github.com/projecthydra-labs/hydra-grouper
172
+ licenses:
173
+ - Apache-2.0
174
+ metadata: {}
175
+ post_install_message:
176
+ rdoc_options: []
177
+ require_paths:
178
+ - lib
179
+ required_ruby_version: !ruby/object:Gem::Requirement
180
+ requirements:
181
+ - - ">="
182
+ - !ruby/object:Gem::Version
183
+ version: '0'
184
+ required_rubygems_version: !ruby/object:Gem::Requirement
185
+ requirements:
186
+ - - ">="
187
+ - !ruby/object:Gem::Version
188
+ version: '0'
189
+ requirements: []
190
+ rubyforge_project:
191
+ rubygems_version: 2.6.8
192
+ signing_key:
193
+ specification_version: 4
194
+ summary: Hydra Group / Role and General Conjecture
195
+ test_files: []