authegy 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/README.md +70 -0
  4. data/app/assets/config/authegy_manifest.js +2 -0
  5. data/app/assets/javascripts/authegy/application.js +15 -0
  6. data/app/assets/stylesheets/authegy/application.css +15 -0
  7. data/app/controllers/authegy/application_controller.rb +5 -0
  8. data/app/helpers/authegy/application_helper.rb +4 -0
  9. data/app/jobs/authegy/application_job.rb +4 -0
  10. data/app/mailers/authegy/application_mailer.rb +6 -0
  11. data/app/models/authegy/application_record.rb +5 -0
  12. data/app/views/layouts/authegy/application.html.erb +16 -0
  13. data/lib/authegy.rb +27 -0
  14. data/lib/authegy/authorizable.rb +57 -0
  15. data/lib/authegy/controller_helpers.rb +62 -0
  16. data/lib/authegy/engine.rb +5 -0
  17. data/lib/authegy/models/person.rb +24 -0
  18. data/lib/authegy/models/role.rb +18 -0
  19. data/lib/authegy/models/role_assignment.rb +16 -0
  20. data/lib/authegy/models/user.rb +24 -0
  21. data/lib/authegy/version.rb +3 -0
  22. data/lib/devise/models/database_authenticatable_with_person_email.rb +30 -0
  23. data/lib/devise/models/validatable_with_person_email.rb +41 -0
  24. data/lib/generators/authegy/USAGE +8 -0
  25. data/lib/generators/authegy/install_generator.rb +29 -0
  26. data/lib/generators/authegy/models_generator.rb +46 -0
  27. data/lib/generators/authegy/orm_helpers.rb +39 -0
  28. data/lib/generators/authegy/templates/models_migration.erb +83 -0
  29. data/lib/generators/authegy/templates/person_model.rb +9 -0
  30. data/lib/generators/authegy/templates/role_assignment_model.rb +6 -0
  31. data/lib/generators/authegy/templates/role_model.rb +6 -0
  32. data/lib/generators/authegy/templates/user_model.rb +15 -0
  33. data/lib/tasks/authegy_tasks.rake +4 -0
  34. metadata +183 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d07d7606ab2766ec64bdec8b4755b033c697bc5d6eccda20f39d8fc308c2489d
4
+ data.tar.gz: 51685f9e90d411e8514d14c795ef5a6a2b57a0e9234f339ebf591c0ebe03718e
5
+ SHA512:
6
+ metadata.gz: 05a858a671eab9e43fc0c7bf49d77e8abe1ddf81f92c7f60ee71041d0c33e3e4ac0b12abb34ee6282192f16717b196858139583519f4ed1be06abd30dc129403
7
+ data.tar.gz: cc880a11cbaff90d3e037f6058e215f5cfbdf9880df258df0d0db6d0c1ffc1703bf86207e0a42fbdfc2f278e9aeab52ade142d0966b0c6d4d72575ea8f76fdc0
@@ -0,0 +1,5 @@
1
+ # Authegy Changelog
2
+
3
+ ## Version 0.0.1
4
+
5
+ - Initial Implementation
@@ -0,0 +1,70 @@
1
+ # Authegy
2
+
3
+ The Authegy gem is a library that combines several useful ruby libraries to
4
+ provide an opinionated authentication and role-based authorization models for
5
+ your rails apps.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'authegy'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install authegy
22
+
23
+ ## Usage
24
+
25
+ ### Basic Use Case: The User & Role models
26
+
27
+ - Use only a single "User" class, with several roles associated to it - instead
28
+ of having multiple "user" classes, which tend to have duplicated code &
29
+ functionality between them.
30
+ - Roles can also be optionally associated to different "Resource" models, so we
31
+ can limit the authorization to certain objects. Examples:
32
+ - "User 2" is an "Administrator" of "Website 2" (so he/she can change the
33
+ Website 2's URL)
34
+ - "User 3" is a "Procurement Manager" of "Company 4" (so he/she can place
35
+ orders on behalf of the Company 4)
36
+
37
+ ![Base Use Case](docs/use-cases/base-use-case.svg)
38
+
39
+
40
+
41
+
42
+ ## Development
43
+
44
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run
45
+ `rake spec` to run the tests. You can also run `bin/console` for an interactive
46
+ prompt that will allow you to experiment.
47
+
48
+ To install this gem onto your local machine, run `bundle exec rake install`. To
49
+ release a new version, update the version number in `version.rb`, and then run
50
+ `bundle exec rake release`, which will create a git tag for the version, push
51
+ git commits and tags, and push the `.gem` file to
52
+ [rubygems.org](https://rubygems.org).
53
+
54
+ ## Contributing
55
+
56
+ Bug reports and pull requests are welcome on GitHub at
57
+ https://github.com/vovimayhem/authegy. This project is intended to be a safe,
58
+ welcoming space for collaboration, and contributors are expected to adhere to
59
+ the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
60
+
61
+ ## License
62
+
63
+ The gem is available as open source under the terms of the
64
+ [MIT License](https://opensource.org/licenses/MIT).
65
+
66
+ ## Code of Conduct
67
+
68
+ Everyone interacting in the A2 project’s codebases, issue trackers, chat rooms
69
+ and mailing lists is expected to follow the
70
+ [Code of Conduct](https://github.com/vovimayhem/authegy/blob/master/CODE_OF_CONDUCT.md).
@@ -0,0 +1,2 @@
1
+ //= link_directory ../javascripts/authegy .js
2
+ //= link_directory ../stylesheets/authegy .css
@@ -0,0 +1,15 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file. JavaScript code in this file should be added after the last require_* statement.
9
+ //
10
+ // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require rails-ujs
14
+ //= require activestorage
15
+ //= require_tree .
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,5 @@
1
+ module Authegy
2
+ class ApplicationController < ActionController::Base
3
+ protect_from_forgery with: :exception
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ module Authegy
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Authegy
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module Authegy
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: 'from@example.com'
4
+ layout 'mailer'
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module Authegy
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,16 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Authegy</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <%= stylesheet_link_tag "authegy/application", media: "all" %>
9
+ <%= javascript_include_tag "authegy/application" %>
10
+ </head>
11
+ <body>
12
+
13
+ <%= yield %>
14
+
15
+ </body>
16
+ </html>
@@ -0,0 +1,27 @@
1
+ require 'active_support/dependencies'
2
+ require 'devise'
3
+ require 'authegy/engine'
4
+
5
+ module Authegy
6
+ autoload :Authorizable, 'authegy/authorizable'
7
+
8
+ autoload :Person, 'authegy/models/person'
9
+ autoload :RoleAssignment, 'authegy/models/role_assignment'
10
+ autoload :Role, 'authegy/models/role'
11
+ autoload :User, 'authegy/models/user'
12
+
13
+ autoload :ControllerHelpers, 'authegy/controller_helpers'
14
+
15
+ def self.extract_resource_attributes(resource_type_or_instance)
16
+ return { resource_type: resource_type_or_instance } \
17
+ if resource_type_or_instance.is_a? String
18
+
19
+ return { resource_type: resource_type_or_instance.name } \
20
+ if resource_type_or_instance.is_a? Class
21
+
22
+ return {
23
+ resource_type: resource_type_or_instance.class.name,
24
+ resource_id: resource_type_or_instance.id
25
+ } if resource_type_or_instance.respond_to? :id
26
+ end
27
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Authegy
4
+ module Authorizable
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ has_many :role_assignments,
9
+ class_name: '::RoleAssignment',
10
+ inverse_of: :actor,
11
+ foreign_key: :actor_id
12
+
13
+ has_many :assigned_roles,
14
+ -> { distinct },
15
+ through: :role_assignments,
16
+ source: :role
17
+ end
18
+
19
+ def assign_role(role_name, resource_type_or_instance = nil)
20
+ assignment_attributes = {
21
+ role: ::Role.find_or_create_by(name: role_name)
22
+ }
23
+
24
+ if resource_type_or_instance.present?
25
+ assignment_attributes.merge! Authegy
26
+ .extract_resource_attributes(resource_type_or_instance)
27
+ end
28
+
29
+ role_assignments.find_or_create_by assignment_attributes
30
+ end
31
+
32
+ def has_role?(role_name, resource_type_or_instance = nil)
33
+ matching_attributes = { role: role_name.to_s }
34
+
35
+ return role_assignment_list.select do |assignment|
36
+ assignment[:role] == matching_attributes[:role]
37
+ end.any? if resource_type_or_instance.blank?
38
+
39
+ matching_attributes.merge! Authegy
40
+ .extract_resource_attributes(resource_type_or_instance)
41
+
42
+ role_assignment_list.select do |assignment|
43
+ assignment == matching_attributes
44
+ end.any?
45
+ end
46
+
47
+ private
48
+
49
+ def role_assignment_list
50
+ @role_assignment_list ||= role_assignments.includes(:role).map do |assgn|
51
+ assgn.attributes.slice('resource_type', 'resource_id').merge!(
52
+ role: assgn.role.name
53
+ ).symbolize_keys!
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Authegy
4
+ # = AuthorizationHelper
5
+ #
6
+ # Methods that deal with defining access to resources by user roles
7
+ module ControllerHelpers
8
+ # authorize_action!
9
+ # Usage:
10
+ # ```
11
+ # class ThingsController < ApplicationController
12
+ # before_action do
13
+ # authorize_action! to: 'thing.owner'
14
+ # authorize_action! :administrator, :manager, of: 'thing.other_thing'
15
+ # authorize_action! :anyone, from: 'thing.company'
16
+ # end, only: [:index, :show]
17
+ # end
18
+ # ```
19
+ def authorize_action!(*given_roles)
20
+ given_roles, options = AuthorizationHelper.parse_given_roles(given_roles)
21
+ auth_request_env['match_roles_on'] = options[:match_roles_on] if options.key?(:match_roles_on)
22
+
23
+ return auth_request_env['authorized_roles'] = Role.all if super_admin_user?
24
+ auth_request_env['authorized_roles'] = current_user_roles.where(name: given_roles)
25
+
26
+ # error if only general manager, plant managers can create
27
+
28
+ raise ActionErrors::Forbidden if authorized_roles.map(&:name).count == 1 && current_user_roles.first.name == 'manager' && current_user_roles.where(name: 'manager').where.not(target_id: nil).empty?
29
+ raise ActionErrors::Forbidden unless authorized_roles.any?
30
+ end
31
+
32
+ def authorize_action(*given_roles)
33
+ authorize_action!(*given_roles)
34
+ rescue
35
+ false
36
+ end
37
+
38
+ def super_admin_user?
39
+ auth_request_env['super_admin_user'] ||= current_user_roles
40
+ .where(name: :administrator, target_id: nil)
41
+ .any?
42
+ end
43
+
44
+ # :nodoc:
45
+ # Reek complains about multiple calls to `request.env` and/or not refering to object state...
46
+ define_method(:auth_request_env) { request.env }
47
+
48
+ define_method(:current_user_roles) { current_user.roles }
49
+ define_method(:authorized_roles) { auth_request_env['authorized_roles'] }
50
+ #
51
+ # def match_roles_on
52
+ # auth_request_env['match_roles_on']
53
+ # end
54
+
55
+ def self.parse_given_roles(given_roles = [])
56
+ given_roles = [:administrator] unless given_roles.any?
57
+ options = given_roles.last.is_a?(Hash) ? given_roles.pop.with_indifferent_access : {}
58
+ [given_roles, options]
59
+ end
60
+ end
61
+
62
+ end
@@ -0,0 +1,5 @@
1
+ module Authegy
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Authegy
4
+ end
5
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Authegy
4
+ # Person holds the "Profile" for a given User, but we can also have just
5
+ # Person profiles without a user, as is the case for "Board Members"
6
+ class Person < ApplicationRecord
7
+ include Authegy::Authorizable
8
+
9
+ self.table_name = :people
10
+ self.abstract_class = true
11
+
12
+ # Validations from 'validatable':
13
+ validates_uniqueness_of :email,
14
+ allow_blank: true,
15
+ if: :will_save_change_to_email?
16
+
17
+ validates_format_of :email,
18
+ with: Devise.email_regexp,
19
+ allow_blank: true,
20
+ if: :will_save_change_to_email?
21
+
22
+ has_one :user, class_name: '::User', inverse_of: :person, foreign_key: :id
23
+ end
24
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Authegy
4
+ #= Authegy::Role
5
+ # A `Role`
6
+ class Role < ApplicationRecord
7
+ self.table_name = :roles
8
+ self.abstract_class = true
9
+
10
+ validates :name, format: {
11
+ with: /\A[a-z_]+\z/,
12
+ message: 'only allows letters and underscores'
13
+ }
14
+
15
+ has_many :assignments, class_name: '::RoleAssignment', inverse_of: :role
16
+ has_many :actors, -> { distinct }, through: :assignments, source: :actor
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Authegy
4
+ # A `RoleAssignment` associates a `Person` to an optional "resource", and
5
+ # assigns a particular roleholds the "Profile" for a given User, but we can
6
+ # also have just Person profiles without a user, as is the case for
7
+ # "Board Members"
8
+ class RoleAssignment < ApplicationRecord
9
+ self.table_name = :role_assignments
10
+ self.abstract_class = true
11
+
12
+ belongs_to :actor, class_name: '::Person', foreign_key: :actor_id
13
+ belongs_to :role
14
+ belongs_to :resource, optional: true, polymorphic: true
15
+ end
16
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'devise/models/validatable_with_person_email'
4
+ require 'devise/models/database_authenticatable_with_person_email'
5
+
6
+ module Authegy
7
+ #= User
8
+ #
9
+ # Represents a person which is able to sign-in to the application.
10
+ # Users are intended for authentification, the actual profile sits in Person.
11
+ class User < ApplicationRecord
12
+ self.table_name = :users
13
+ self.abstract_class = true
14
+
15
+ devise :database_authenticatable_with_person_email,
16
+ :validatable_with_person_email
17
+
18
+ belongs_to :person, inverse_of: :user, foreign_key: :id
19
+ delegate :email, :email=, :name, to: :person, allow_nil: true
20
+
21
+ delegate :assigned_roles, :assign_role, :has_role?, :has_any_role?,
22
+ :remove_role, :role_assignments, to: :person
23
+ end
24
+ end
@@ -0,0 +1,3 @@
1
+ module Authegy
2
+ VERSION = '0.0.1'.freeze
3
+ end
@@ -0,0 +1,30 @@
1
+ module Devise
2
+ module Models
3
+ #= DatabaseAuthenticatableWithPersonEmail
4
+ #
5
+ # Overrides Devise::Models::DatabaseAuthenticatable, so but instead of
6
+ # expecting the `email` field to be in the authenticatable model, is located
7
+ # instead in the associated `Person` model
8
+ module DatabaseAuthenticatableWithPersonEmail
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ # Include the original module:
13
+ devise :database_authenticatable
14
+ end
15
+
16
+ module ClassMethods
17
+ Devise::Models.config self
18
+
19
+ # Override of
20
+ # Devise::Models::Authenticatable.find_first_by_auth_conditions:
21
+ def find_first_by_auth_conditions(tainted_conditions, opts={})
22
+ filter = devise_parameter_filter.filter(tainted_conditions).merge opts
23
+ person_filter = filter.extract! :email
24
+ matching_person_scope = Person.where person_filter
25
+ User.where(filter).joins(:person).merge(matching_person_scope).first
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,41 @@
1
+ module Devise
2
+ module Models
3
+ #= ValidatableWithPersonEmail
4
+ #
5
+ # A re-implementation of Devise::Models::Validatable, but instead of
6
+ # expecting the `email` field to be in the authenticatable model, is located
7
+ # instead in the `Person` associated model
8
+ module ValidatableWithPersonEmail
9
+ extend ActiveSupport::Concern
10
+
11
+ included do
12
+ validates_presence_of :password, if: :password_required?
13
+ validates_confirmation_of :password, if: :password_required?
14
+
15
+ validates_length_of :password,
16
+ within: password_length,
17
+ allow_blank: true
18
+
19
+ validate :person_email_must_be_present
20
+ end
21
+
22
+ module ClassMethods
23
+ Devise::Models.config self, :email_regexp, :password_length
24
+ end
25
+
26
+ protected
27
+
28
+ # Checks whether a password is needed or not. For validations only.
29
+ # Passwords are always required if it's a new record, or if the password
30
+ # or confirmation are being set somewhere.
31
+ def password_required?
32
+ !persisted? || !password.nil? || !password_confirmation.nil?
33
+ end
34
+
35
+ def person_email_must_be_present
36
+ return if person&.email.present?
37
+ errors.add :base, 'Person email must be present'
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,8 @@
1
+ Description:
2
+ Explain the generator
3
+
4
+ Example:
5
+ rails generate authegy Thing
6
+
7
+ This will create:
8
+ what/will/it/create
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators/base'
4
+
5
+ class InstallGenerator < Rails::Generators::Base
6
+ namespace 'authegy:install'
7
+ source_root File.expand_path('templates', __dir__)
8
+
9
+
10
+ def generate_customized_devise_install
11
+ generate 'devise:install'
12
+
13
+ gsub_file 'config/initializers/devise.rb',
14
+ 'config.sign_out_via = :delete',
15
+ 'config.sign_out_via = %i[get delete]'
16
+ end
17
+
18
+ def generate_authegy_install
19
+ generate 'authegy:models People'
20
+ end
21
+
22
+ def add_devise_routes
23
+ route <<~STRING
24
+ devise_for :users,
25
+ path: '/',
26
+ path_names: { sign_in: 'sign-in', sign_out: 'sign-out' }
27
+ STRING
28
+ end
29
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators/active_record'
4
+ require 'generators/authegy/orm_helpers'
5
+
6
+ class ModelsGenerator < ActiveRecord::Generators::Base
7
+ namespace 'authegy:models'
8
+ include Authegy::Generators::OrmHelpers
9
+ source_root File.expand_path('templates', __dir__)
10
+
11
+ argument :attributes,
12
+ type: :array,
13
+ default: [],
14
+ banner: 'field:type field:type'
15
+
16
+ # class_option :primary_key_type, type: :string, desc: 'The type for primary key'
17
+
18
+ def copy_authegy_migration
19
+ # if (behavior == :invoke && model_exists?) || (behavior == :revoke && migration_exists?(table_name))
20
+ # migration_template "migration_existing.rb", "#{migration_path}/add_devise_to_#{table_name}.rb", migration_version: migration_version
21
+ # else
22
+ migration_template(
23
+ 'models_migration.erb',
24
+ "#{migration_path}/create_authegy_model_tables.rb",
25
+ migration_version: migration_version
26
+ )
27
+ # end
28
+ end
29
+
30
+ def generate_app_models
31
+ copy_file 'person_model.rb', 'app/models/person.rb'
32
+ copy_file 'role_model.rb', 'app/models/role.rb'
33
+ copy_file 'user_model.rb', 'app/models/user.rb'
34
+ copy_file 'role_assignment_model.rb', 'app/models/role_assignment.rb'
35
+ end
36
+
37
+ def rails5_and_up?
38
+ Rails::VERSION::MAJOR >= 5
39
+ end
40
+
41
+ def migration_version
42
+ if rails5_and_up?
43
+ "[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Authegy
4
+ module Generators
5
+ module OrmHelpers
6
+ def model_contents
7
+ buffer = <<-CONTENT
8
+ # Include default devise modules. Others available are:
9
+ # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
10
+ devise :database_authenticatable, :registerable,
11
+ :recoverable, :rememberable, :validatable
12
+ CONTENT
13
+ buffer
14
+ end
15
+
16
+ private
17
+
18
+ def model_exists?
19
+ File.exist?(File.join(destination_root, model_path))
20
+ end
21
+
22
+ def migration_exists?(table_name)
23
+ Dir.glob("#{File.join(destination_root, migration_path)}/[0-9]*_*.rb").grep(/\d+_add_devise_to_#{table_name}.rb$/).first
24
+ end
25
+
26
+ def migration_path
27
+ if Rails.version >= '5.0.3'
28
+ db_migrate_path
29
+ else
30
+ @migration_path ||= File.join("db", "migrate")
31
+ end
32
+ end
33
+
34
+ def model_path
35
+ @model_path ||= File.join("app", "models", "#{file_path}.rb")
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateAuthegyModelTables < ActiveRecord::Migration<%= migration_version %>
4
+ def change
5
+ create_people_table
6
+ create_users_table
7
+ create_roles_table
8
+ create_role_assignments_table
9
+ end
10
+
11
+ def create_people_table
12
+ create_table :people do |t|
13
+ t.string :first_name, null: false
14
+ t.string :last_name, null: false
15
+ t.string :email, index: { unique: true }
16
+
17
+ # Feel free to add additional fields, such as 'nickname', etc:
18
+ # t.string :phone
19
+
20
+ t.timestamps null: false
21
+ end
22
+ end
23
+
24
+ def create_users_table
25
+ create_table :users do |t|
26
+ ## Database authenticatable
27
+ t.string :encrypted_password, null: false, default: ''
28
+
29
+ ## Recoverable
30
+ t.string :reset_password_token, index: { unique: true }
31
+ t.datetime :reset_password_sent_at
32
+
33
+ ## Rememberable
34
+ t.datetime :remember_created_at
35
+
36
+ ## Trackable
37
+ # t.integer :sign_in_count, default: 0, null: false
38
+ # t.datetime :current_sign_in_at
39
+ # t.datetime :last_sign_in_at
40
+ # t.inet :current_sign_in_ip
41
+ # t.inet :last_sign_in_ip
42
+
43
+ ## Confirmable
44
+ # t.string :confirmation_token, index: { unique: true }
45
+ # t.datetime :confirmed_at
46
+ # t.datetime :confirmation_sent_at
47
+ # t.string :unconfirmed_email # Only if using reconfirmable
48
+
49
+ ## Lockable
50
+ # # Only if lock strategy is :failed_attempts:
51
+ # t.integer :failed_attempts, default: 0, null: false
52
+ # # Only if unlock strategy is :email or :both:
53
+ # t.string :unlock_token, index: { unique: true }
54
+ # t.datetime :locked_at
55
+
56
+ t.timestamps null: false
57
+ end
58
+
59
+ # The `users.id` column is actually a foreign key to the `people` table:
60
+ add_foreign_key :users, :people, column: :id
61
+ end
62
+
63
+ def create_roles_table
64
+ create_table :roles do |t|
65
+ t.string :name, null: false, comment: 'Name of the role'
66
+ t.text :description, comment: 'Description of the role'
67
+
68
+ t.timestamps null: false
69
+ end
70
+ end
71
+
72
+ def create_role_assignments_table
73
+ create_table :role_assignments do |t|
74
+ t.references :actor, foreign_key: { to_table: :people }
75
+
76
+ t.references :role,
77
+ foreign_key: { to_table: :roles },
78
+ comment: 'The role assigned to the actor'
79
+
80
+ t.references :resource, polymorphic: true
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Person holds the "Profile" for a given User, but we can also have just Person
4
+ # profiles without a user, as is the case for "Board Members"
5
+ class Person < Authegy::Person
6
+ # Authegy::Person already includes validations for the email field, and
7
+ # associations for :user, :role_assignments, :assigned_roles, and methods
8
+ # for authorization, such as :assign_role, :has_role?, etc.
9
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RoleAssignment < Authegy::RoleAssignment
4
+ # Authegy::RoleAssignment already defines associations to :actor, :role and
5
+ # :resource
6
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ #= Role
4
+ class Role < Authegy::Role
5
+ # Authegy::Role already defines associations to :assignments and :actors
6
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ #= User
4
+ #
5
+ # Represents a person which is able to sign-in to the application.
6
+ # Users are intended for authentification, the actual profile sits in Person.
7
+ class User < Authegy::User
8
+ # Authegy::User class already includes associations to :person,
9
+ # and delegations to :person such as :email, :has_role?, etc.
10
+
11
+ # Include devise modules. Others available are:
12
+ # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
13
+ devise :database_authenticatable_with_person_email, :registerable,
14
+ :recoverable, :rememberable, :validatable_with_person_email
15
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :authegy do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,183 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: authegy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Roberto Quintanilla
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-03-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: devise
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.6'
34
+ - - ">="
35
+ - !ruby/object:Gem::Version
36
+ version: 4.6.1
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '4.6'
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: 4.6.1
47
+ - !ruby/object:Gem::Dependency
48
+ name: sqlite3
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: 1.3.6
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: 1.3.6
61
+ - !ruby/object:Gem::Dependency
62
+ name: bundler
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1.17'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.17'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rake
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '10.0'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '10.0'
89
+ - !ruby/object:Gem::Dependency
90
+ name: rspec
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '3.0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '3.0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: rspec-rails
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ description: Opinionated app strategy used for authentication & role-based authorization.
118
+ email:
119
+ - vov@icalialabs.com
120
+ executables: []
121
+ extensions: []
122
+ extra_rdoc_files: []
123
+ files:
124
+ - CHANGELOG.md
125
+ - README.md
126
+ - app/assets/config/authegy_manifest.js
127
+ - app/assets/javascripts/authegy/application.js
128
+ - app/assets/stylesheets/authegy/application.css
129
+ - app/controllers/authegy/application_controller.rb
130
+ - app/helpers/authegy/application_helper.rb
131
+ - app/jobs/authegy/application_job.rb
132
+ - app/mailers/authegy/application_mailer.rb
133
+ - app/models/authegy/application_record.rb
134
+ - app/views/layouts/authegy/application.html.erb
135
+ - lib/authegy.rb
136
+ - lib/authegy/authorizable.rb
137
+ - lib/authegy/controller_helpers.rb
138
+ - lib/authegy/engine.rb
139
+ - lib/authegy/models/person.rb
140
+ - lib/authegy/models/role.rb
141
+ - lib/authegy/models/role_assignment.rb
142
+ - lib/authegy/models/user.rb
143
+ - lib/authegy/version.rb
144
+ - lib/devise/models/database_authenticatable_with_person_email.rb
145
+ - lib/devise/models/validatable_with_person_email.rb
146
+ - lib/generators/authegy/USAGE
147
+ - lib/generators/authegy/install_generator.rb
148
+ - lib/generators/authegy/models_generator.rb
149
+ - lib/generators/authegy/orm_helpers.rb
150
+ - lib/generators/authegy/templates/models_migration.erb
151
+ - lib/generators/authegy/templates/person_model.rb
152
+ - lib/generators/authegy/templates/role_assignment_model.rb
153
+ - lib/generators/authegy/templates/role_model.rb
154
+ - lib/generators/authegy/templates/user_model.rb
155
+ - lib/tasks/authegy_tasks.rake
156
+ homepage: https://github.com/vovimayhem/authegy-gem
157
+ licenses:
158
+ - MIT
159
+ metadata:
160
+ allowed_push_host: https://rubygems.org
161
+ homepage_uri: https://github.com/vovimayhem/authegy-gem
162
+ source_code_uri: https://github.com/vovimayhem/authegy
163
+ changelog_uri: https://github.com/vovimayhem/authegy/blob/master/CHANGELOG.md
164
+ post_install_message:
165
+ rdoc_options: []
166
+ require_paths:
167
+ - lib
168
+ required_ruby_version: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ">="
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
173
+ required_rubygems_version: !ruby/object:Gem::Requirement
174
+ requirements:
175
+ - - ">="
176
+ - !ruby/object:Gem::Version
177
+ version: '0'
178
+ requirements: []
179
+ rubygems_version: 3.0.1
180
+ signing_key:
181
+ specification_version: 4
182
+ summary: Opinionated app strategy used for authentication & role-based authorization.
183
+ test_files: []