private_person 0.4.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +57 -0
  3. data/.gitignore +13 -0
  4. data/.rspec +1 -1
  5. data/.rubocop.yml +28 -0
  6. data/.rubocop_todo.yml +57 -0
  7. data/.simplecov +5 -0
  8. data/CHANGELOG.md +57 -0
  9. data/CLAUDE.md +5 -0
  10. data/Gemfile +25 -7
  11. data/LICENSE.txt +1 -1
  12. data/README.md +93 -0
  13. data/Rakefile +5 -23
  14. data/lib/generators/private_person/install/install_generator.rb +21 -19
  15. data/lib/generators/private_person/install/templates/migrate/create_permissions_table.rb +7 -14
  16. data/lib/generators/private_person/utils.rb +2 -7
  17. data/lib/private_person/extensions/acts_as_permissible.rb +9 -8
  18. data/lib/private_person/extensions/acts_as_permissor.rb +25 -28
  19. data/lib/private_person/extensions/acts_as_permitted.rb +21 -31
  20. data/lib/private_person/models/permission.rb +29 -21
  21. data/lib/private_person/version.rb +3 -1
  22. data/lib/private_person.rb +6 -4
  23. data/private_person.gemspec +35 -124
  24. data/spec/dummy/.rspec +1 -1
  25. data/spec/dummy/Rakefile +3 -1
  26. data/spec/dummy/app/models/application_record.rb +5 -0
  27. data/spec/dummy/app/models/page.rb +4 -2
  28. data/spec/dummy/app/models/user.rb +12 -9
  29. data/spec/dummy/bin/rails +6 -0
  30. data/spec/dummy/config/application.rb +23 -36
  31. data/spec/dummy/config/boot.rb +5 -8
  32. data/spec/dummy/config/database.yml +9 -9
  33. data/spec/dummy/config/environment.rb +6 -4
  34. data/spec/dummy/config/environments/development.rb +12 -12
  35. data/spec/dummy/config/environments/test.rb +20 -12
  36. data/spec/dummy/db/migrate/20260902000001_create_users_table.rb +9 -0
  37. data/spec/dummy/db/migrate/20260902000002_create_connections.rb +13 -0
  38. data/spec/dummy/db/migrate/20260902000003_create_pages_table.rb +11 -0
  39. data/spec/dummy/db/migrate/20260902000004_create_permissions.rb +11 -0
  40. data/spec/dummy/db/schema.rb +38 -56
  41. data/spec/factories/pages.rb +7 -5
  42. data/spec/factories/permissions.rb +6 -4
  43. data/spec/factories/users.rb +6 -4
  44. data/spec/models/page_spec.rb +5 -2
  45. data/spec/models/permission_spec.rb +58 -39
  46. data/spec/models/user_spec.rb +83 -40
  47. data/spec/private_person_spec.rb +4 -2
  48. data/spec/spec_helper.rb +40 -23
  49. data/spec/support/permissions_support.rb +41 -18
  50. data/spec/support/permissor_support.rb +7 -5
  51. data/spec/support/users_support.rb +9 -7
  52. metadata +93 -90
  53. data/.document +0 -5
  54. data/.idea/scopes/scope_settings.xml +0 -5
  55. data/README.rdoc +0 -22
  56. data/VERSION +0 -1
  57. data/script/rails +0 -6
  58. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
  59. data/spec/dummy/config/initializers/inflections.rb +0 -15
  60. data/spec/dummy/config/initializers/mime_types.rb +0 -5
  61. data/spec/dummy/config/initializers/secret_token.rb +0 -7
  62. data/spec/dummy/config/initializers/session_store.rb +0 -8
  63. data/spec/dummy/config/locales/devise.en.yml +0 -59
  64. data/spec/dummy/config/locales/en.yml +0 -5
  65. data/spec/dummy/config/routes.rb +0 -59
  66. data/spec/dummy/config.ru +0 -4
  67. data/spec/dummy/db/development.sqlite3 +0 -0
  68. data/spec/dummy/db/migrate/20130906213557_create_users_table.rb +0 -13
  69. data/spec/dummy/db/migrate/20130906213612_create_pages_table.rb +0 -15
  70. data/spec/dummy/db/test.sqlite3 +0 -0
  71. data/spec/dummy/script/rails +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 8fc5ea2ff01d3b1c9aa4fdf1d08b1e89d4b59fda
4
- data.tar.gz: 53cdaee285d896caf9591c4bfed3d4897af94e40
2
+ SHA256:
3
+ metadata.gz: fb0dc73f8b0f56d09feec4fafa8255e374fe6e430361f85ff34806fc5e908e5b
4
+ data.tar.gz: 1add348c75fc0a2a270c0647811e3e4e6af64d92c11ed37380fbbff33d9fdeba
5
5
  SHA512:
6
- metadata.gz: f7fa47f819e68afc2931b7cf9a0f8ac845fe559dee7948b3616e51498957a9f5d7ae42490a263593a850abc656e4e9cbbdfae91c13bb31aef23964d0daaabdf4
7
- data.tar.gz: f760e1935c191e8f78fbde750decc436dcd80993b70eb080a2ecd9e3a50a0900308e9e0323b6c12b58c5f57e1a6875b5f03c4e104c4762a2eeeeb7d010c9d461
6
+ metadata.gz: 4799c45274e7f19bc7ee3184bfb42f9bb57a2c3228ef5d8d17705deceb92123cd383963be9606471ee6b4cf5dbd9aa4a848c06759522a724e034b7385dcb3dca
7
+ data.tar.gz: 26d4586cbd765cf4018f47ae170d22f22b36212ad1c76cb2721e218821f4ee829a5be02589b104386cd09a9d6d3e3b957d470d5c57f53ed8a3e9d62fbeb115bc
@@ -0,0 +1,57 @@
1
+ name: CI
2
+ on:
3
+ push:
4
+ pull_request:
5
+
6
+ jobs:
7
+ lint:
8
+ runs-on: ubuntu-latest
9
+ steps:
10
+ - uses: actions/checkout@v4
11
+ - uses: ruby/setup-ruby@v1
12
+ with:
13
+ ruby-version: '3.4'
14
+ bundler-cache: true
15
+ - run: bundle exec rubocop
16
+
17
+ test:
18
+ runs-on: ubuntu-latest
19
+ strategy:
20
+ fail-fast: false
21
+ matrix:
22
+ ruby: ['3.4', '4.0']
23
+ env:
24
+ RAILS_ENV: test
25
+ TZ: America/Denver
26
+ permissions:
27
+ contents: write
28
+ steps:
29
+ - uses: actions/checkout@v4
30
+ - uses: ruby/setup-ruby@v1
31
+ with:
32
+ ruby-version: ${{ matrix.ruby }}
33
+ bundler-cache: true
34
+ - name: Set up test database
35
+ run: bundle exec rails db:create db:schema:load
36
+ working-directory: spec/dummy
37
+ - run: bundle exec rspec
38
+ - uses: actions/upload-artifact@v4
39
+ if: always()
40
+ with:
41
+ name: coverage-ruby-${{ matrix.ruby }}
42
+ path: coverage/
43
+ # Publishes a self-hosted coverage badge (badges/coverage.json, read by
44
+ # a shields.io endpoint badge in the README) instead of depending on a
45
+ # third-party coverage service like Coveralls/Codecov.
46
+ - name: Update coverage badge
47
+ if: matrix.ruby == '4.0' && github.ref_name == github.event.repository.default_branch && github.event_name == 'push'
48
+ run: |
49
+ pct=$(ruby -rjson -e "r = JSON.parse(File.read('coverage/.last_run.json'))['result']; puts (r['covered_percent'] || r['line']).round(1)")
50
+ color=$(ruby -e "pct = $pct; puts(pct >= 90 ? 'brightgreen' : pct >= 75 ? 'yellow' : 'red')")
51
+ mkdir -p badges
52
+ printf '{"schemaVersion":1,"label":"coverage","message":"%s%%","color":"%s"}\n' "$pct" "$color" > badges/coverage.json
53
+ git config user.name "github-actions[bot]"
54
+ git config user.email "github-actions[bot]@users.noreply.github.com"
55
+ git add badges/coverage.json
56
+ git diff --staged --quiet || git commit -m "Update coverage badge [skip ci]"
57
+ git push
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ Gemfile.lock
2
+ *.log
3
+ tmp
4
+ *.pid
5
+ *.gem
6
+ .idea
7
+ .bundle
8
+ coverage
9
+ spec/dummy/db/development.sqlite3
10
+ spec/dummy/db/test.sqlite3
11
+ *.sqlite3-journal
12
+ *.sqlite3-shm
13
+ *.sqlite3-wal
data/.rspec CHANGED
@@ -1 +1 @@
1
- --color
1
+ --color
data/.rubocop.yml ADDED
@@ -0,0 +1,28 @@
1
+ inherit_from: .rubocop_todo.yml
2
+
3
+ plugins:
4
+ - rubocop-rails
5
+ - rubocop-rake
6
+ - rubocop-rspec
7
+
8
+ AllCops:
9
+ TargetRubyVersion: 3.2
10
+ DisplayCopNames: true
11
+ NewCops: enable
12
+ SuggestExtensions: false
13
+ Exclude:
14
+ - private_person.gemspec
15
+ - spec/dummy/db/schema.rb
16
+ - spec/dummy/db/migrate/*
17
+ - lib/generators/private_person/install/templates/**/*
18
+
19
+ Metrics/BlockLength:
20
+ Exclude:
21
+ - spec/*
22
+ - spec/*/*
23
+
24
+ # PrivatePerson::Permission is a gem-owned model shipped to consumers -
25
+ # it can't assume a host app's own ApplicationRecord exists.
26
+ Rails/ApplicationRecord:
27
+ Exclude:
28
+ - lib/**/*
data/.rubocop_todo.yml ADDED
@@ -0,0 +1,57 @@
1
+ # This configuration was generated by
2
+ # `rubocop --auto-gen-config --no-offense-counts --no-auto-gen-timestamp`
3
+ # using RuboCop version 1.90.0.
4
+ # The point is for the user to remove these configuration records
5
+ # one by one as the offenses are removed from the code base.
6
+ # Note that changes in the inspected code, or installation of new
7
+ # versions of RuboCop, may require this file to be generated again.
8
+
9
+ # Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros, UseSorbetSigs.
10
+ # NamePrefix: is_, has_, have_, does_
11
+ # ForbiddenPrefixes: is_, has_, have_, does_
12
+ # AllowedMethods: is_a?
13
+ # MethodDefinitionMacros: define_method, define_singleton_method
14
+ Naming/PredicatePrefix:
15
+ Exclude:
16
+ - 'lib/private_person/extensions/acts_as_permissible.rb'
17
+ - 'lib/private_person/extensions/acts_as_permitted.rb'
18
+
19
+ # Configuration parameters: Prefixes, AllowedPatterns.
20
+ # Prefixes: when, with, without
21
+ RSpec/ContextWording:
22
+ Exclude:
23
+ - 'spec/models/user_spec.rb'
24
+ - 'spec/support/permissions_support.rb'
25
+ - 'spec/support/permissor_support.rb'
26
+ - 'spec/support/users_support.rb'
27
+
28
+ RSpec/LetSetup:
29
+ Exclude:
30
+ - 'spec/support/permissions_support.rb'
31
+ - 'spec/support/permissor_support.rb'
32
+ - 'spec/support/users_support.rb'
33
+
34
+ # Configuration parameters: AllowSubject.
35
+ RSpec/MultipleMemoizedHelpers:
36
+ Max: 18
37
+
38
+ # Configuration parameters: EnforcedStyle, IgnoreSharedExamples.
39
+ # SupportedStyles: always, named_only
40
+ RSpec/NamedSubject:
41
+ Exclude:
42
+ - 'spec/models/permission_spec.rb'
43
+
44
+ # Configuration parameters: AllowedGroups.
45
+ RSpec/NestedGroups:
46
+ Max: 5
47
+
48
+ # Configuration parameters: CustomTransform, IgnoreMethods, IgnoreMetadata, InflectorPath, EnforcedInflector.
49
+ # SupportedInflectors: default, active_support
50
+ RSpec/SpecFilePathFormat:
51
+ Exclude:
52
+ - 'spec/models/permission_spec.rb'
53
+
54
+ # Configuration parameters: AllowedConstants.
55
+ # This gem doesn't use top-level documentation comments anywhere.
56
+ Style/Documentation:
57
+ Enabled: false
data/.simplecov ADDED
@@ -0,0 +1,5 @@
1
+ require 'simplecov'
2
+
3
+ SimpleCov.start do
4
+ add_filter '/spec/'
5
+ end
data/CHANGELOG.md ADDED
@@ -0,0 +1,57 @@
1
+ # Changelog
2
+
3
+ ## 1.0.0
4
+
5
+ **Breaking change.** From-the-ground-up modernization: Rails 4 support
6
+ is dropped in favor of Rails >= 7.1, < 9, and the packaging/tooling
7
+ stack is fully replaced. There is no data-model migration needed for
8
+ existing installs - the `permissions` table shape is unchanged (see
9
+ below) - but the Ruby/Rails floor bump and the two association fixes
10
+ below are real behavior changes to check against before upgrading.
11
+
12
+ ### Breaking
13
+
14
+ - **Ruby >= 3.2, Rails >= 7.1, < 9** required (was Rails >= 4.0, no
15
+ ceiling, developed against Rails 3/4-era conventions).
16
+ - **`user.permissibles` was broken and is now fixed.** The
17
+ `acts_as_permissor`-generated `has_many :permissibles, through:
18
+ :permissions` referenced the wrong association name (should have been
19
+ `:permissions_as_permissor`) and was missing `source_type` for its
20
+ polymorphic source - calling it raised outright on Rails 8's stricter
21
+ association validation. If your code already worked around this
22
+ (e.g. by never calling `.permissibles`), no change needed; if you
23
+ relied on it silently failing, it now actually returns the collection.
24
+ - **`wildcard_permit!`'s de-duplication is now fixed.** It previously
25
+ built its "does this already exist?" check with a malformed `.where`
26
+ call and had its guard commented out, so calling `wildcard_permit!`
27
+ twice with the same arguments always created a duplicate `Permission`
28
+ row. It now correctly creates at most one.
29
+ - **The generator's migration template is rewritten for Rails 8**
30
+ (`ActiveRecord::Migration[8.0]`, `t.references ..., polymorphic:
31
+ true`, `def change`) - the old template used a bare
32
+ `ActiveRecord::Migration` with no version bracket, which doesn't load
33
+ at all on Rails 5+. Column shape is otherwise unchanged: `permissor`
34
+ is required, `permissible` stays nullable (that's the wildcard/
35
+ type-level grant signal), `relationship_type` still defaults to
36
+ `'none'`.
37
+ - **`Permission.permissible_types`** no longer issues an invalid
38
+ `GROUP BY` query (worked on SQLite by accident, would have failed on
39
+ Postgres) and no longer raises when a permissor record has since been
40
+ deleted (it's skipped instead).
41
+ - **`Permission#by_relationship_type`**'s "match nothing" fallback
42
+ changed from the `where(0)` hack to `.none`.
43
+
44
+ ### Also changed
45
+
46
+ - Jeweler/Rakefile-based packaging replaced with a hand-written
47
+ gemspec (`s.files` via `git ls-files`); `jeweler` is no longer even a
48
+ runtime dependency of the built gem (it was, by mistake, in 0.5.0).
49
+ - factory_girl -> factory_bot, RSpec `should` syntax -> `expect`/
50
+ `is_expected`, shoulda-matchers bumped to 6.x.
51
+ - Added rubocop (rubocop-rails, rubocop-rspec) - none was configured
52
+ before.
53
+ - Travis CI -> GitHub Actions; Coveralls -> a self-hosted coverage
54
+ badge (same approach as message_train).
55
+ - README rewritten in Markdown; its `is_permitted?` example previously
56
+ passed a **class** (`Page`) where the real method always expects an
57
+ **instance** - fixed.
data/CLAUDE.md ADDED
@@ -0,0 +1,5 @@
1
+ # private_person
2
+
3
+ ## Client
4
+
5
+ Fiendish Labs, via GemVein (owns all gems, owned by Fiendish Labs). Fiendish Labs (Calendula and Martusjaav's household company). See `Office/projects/TYPES.md`'s Ownership section for the full taxonomy.
data/Gemfile CHANGED
@@ -1,10 +1,28 @@
1
- source 'http://rubygems.org'
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
2
4
  # Add dependencies required to use your gem here.
3
- # Example:
4
- # gem 'activesupport', '>= 2.3.5'
5
+ gem 'rails', '>= 7.1', '< 9'
6
+
7
+ # Add dependencies to develop your gem here.
8
+ # Include everything needed to run rake, tests, features, etc.
9
+ group :development do
10
+ gem 'rubocop', '~> 1.6', require: false
11
+ gem 'rubocop-rails', '~> 2.25', require: false
12
+ gem 'rubocop-rake', '~> 0.7', require: false
13
+ gem 'rubocop-rspec', '~> 3.0', require: false
14
+ end
5
15
 
6
- gem 'rails', '>= 4.0'
7
- gem 'activerecord', '>= 4.0'
8
- gem 'chalk_dust', group: :test, git: 'https://github.com/nerakdon/chalk_dust.git'
16
+ group :development, :test do
17
+ gem 'factory_bot_rails', '~> 6.4'
18
+ gem 'rspec-its', '>= 1', '< 2'
19
+ gem 'rspec-rails', '~> 7.0'
20
+ gem 'sqlite3', '~> 2.1'
21
+ end
9
22
 
10
- gemspec
23
+ group :test do
24
+ gem 'chalk_dust', git: 'https://github.com/krisleech/chalk_dust.git'
25
+ gem 'database_cleaner-active_record', '~> 2.1'
26
+ gem 'shoulda-matchers', '~> 6.0'
27
+ gem 'simplecov', '~> 0.22', require: false
28
+ end
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2013-2014 Gem Vein
1
+ Copyright (c) 2013-2015 Gem Vein
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md ADDED
@@ -0,0 +1,93 @@
1
+ # PrivatePerson
2
+
3
+ [![CI](https://github.com/gemvein/private_person/actions/workflows/ci.yml/badge.svg)](https://github.com/gemvein/private_person/actions/workflows/ci.yml)
4
+ [![Gem Version](https://img.shields.io/gem/v/private_person)](https://rubygems.org/gems/private_person)
5
+ [![Coverage](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/gemvein/private_person/HEAD/badges/coverage.json)](https://github.com/gemvein/private_person/actions/workflows/ci.yml)
6
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](http://opensource.org/licenses/MIT)
7
+
8
+ PrivatePerson is an ActiveRecord extension gem that lets a model be given
9
+ privacy settings over arbitrary models and polymorphic relations, putting
10
+ users' accounts in control of their own privacy policies.
11
+
12
+ ## Installation
13
+
14
+ Add PrivatePerson to your Gemfile:
15
+
16
+ ```ruby
17
+ gem 'private_person'
18
+ ```
19
+
20
+ Then run the install generator, which adds a migration for the
21
+ `permissions` table:
22
+
23
+ ```bash
24
+ rails g private_person:install
25
+ rails db:migrate
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ Set up your models. The "permissor" is whoever is granting/checking
31
+ access (typically a `User`); the "permissible" is whatever's being
32
+ protected:
33
+
34
+ ```ruby
35
+ # app/models/user.rb - using ChalkDust as the subscription model, but any
36
+ # gem or hand-rolled association works, as long as each method below
37
+ # returns the right collection of Users.
38
+ class User < ActiveRecord::Base
39
+ acts_as_permissor of: [:following_users, :user_followers],
40
+ class_name: 'User'
41
+
42
+ def follow(user)
43
+ ChalkDust.subscribe(self, to: user)
44
+ end
45
+
46
+ def following_users
47
+ ChalkDust.publishers_of(self)
48
+ end
49
+
50
+ def user_followers
51
+ ChalkDust.subscribers_of(self)
52
+ end
53
+ end
54
+
55
+ # app/models/page.rb
56
+ class Page < ActiveRecord::Base
57
+ acts_as_permissible by: :user
58
+ belongs_to :user
59
+ end
60
+ ```
61
+
62
+ Then, when you need to know whether someone's permitted to see a
63
+ specific record:
64
+
65
+ ```ruby
66
+ @user.is_permitted? friend_user, @page
67
+ ```
68
+
69
+ Grant or revoke access directly:
70
+
71
+ ```ruby
72
+ @user.permit! 'following_users', @page # this specific page
73
+ @user.wildcard_permit! 'public', 'Page' # every Page, by type
74
+ ```
75
+
76
+ ## Contributing to PrivatePerson
77
+
78
+ * Check out the latest main to make sure the feature hasn't been
79
+ implemented or the bug hasn't been fixed yet.
80
+ * Check out the issue tracker to make sure someone hasn't already
81
+ requested it and/or contributed it.
82
+ * Fork the project.
83
+ * Start a feature/bugfix branch.
84
+ * Commit and push until you are happy with your contribution.
85
+ * Make sure to add tests for it, so it doesn't break in a future version
86
+ unintentionally.
87
+ * Please try not to mess with the Rakefile, version, or history. If you
88
+ want your own version, or it's otherwise necessary, that's fine, but
89
+ please isolate it to its own commit so it can be cherry-picked around.
90
+
91
+ ## Copyright
92
+
93
+ Copyright (c) 2013-2026 Gem Vein. See LICENSE.txt for further details.
data/Rakefile CHANGED
@@ -1,39 +1,21 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  require 'rubygems'
4
4
  require 'bundler'
5
5
  begin
6
6
  Bundler.setup(:default, :development)
7
7
  rescue Bundler::BundlerError => e
8
- $stderr.puts e.message
9
- $stderr.puts "Run `bundle install` to install missing gems"
8
+ warn e.message
9
+ warn 'Run `bundle install` to install missing gems'
10
10
  exit e.status_code
11
11
  end
12
+ require 'bundler/gem_tasks'
12
13
  require 'rake'
13
14
 
14
- require 'jeweler'
15
- Jeweler::Tasks.new do |gem|
16
- # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
- gem.name = "private_person"
18
- gem.homepage = "http://www.gemvein.com/museum/cases/private_person"
19
- gem.license = "MIT"
20
- gem.summary = %Q{Private person puts your users in control of their own privacy policies.}
21
- gem.description = %Q{Private person is an active record extension gem that allows a model to be given privacy settings over arbitrary models and polymorphic relations, putting users' accounts in control of their own privacy policies.}
22
- gem.email = "karen.e.lundgren@gmail.com"
23
- gem.authors = ["Karen Lundgren"]
24
- # dependencies defined in Gemfile
25
- end
26
- Jeweler::RubygemsDotOrgTasks.new
27
-
28
15
  require 'rspec/core'
29
16
  require 'rspec/core/rake_task'
30
17
  RSpec::Core::RakeTask.new(:spec) do |spec|
31
18
  spec.pattern = FileList['spec/**/*_spec.rb']
32
19
  end
33
20
 
34
- RSpec::Core::RakeTask.new(:rcov) do |spec|
35
- spec.pattern = 'spec/**/*_spec.rb'
36
- spec.rcov = false
37
- end
38
-
39
- task :default => :spec
21
+ task default: :spec
@@ -1,31 +1,33 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PrivatePerson
2
4
  class InstallGenerator < Rails::Generators::Base
3
- source_root File.expand_path("../templates", __FILE__)
4
- require File.expand_path('../../utils', __FILE__)
5
+ source_root File.expand_path('templates', __dir__)
6
+ require File.expand_path('../utils', __dir__)
5
7
  include Generators::Utils
6
8
  include Rails::Generators::Migration
7
-
9
+
8
10
  def hello
9
- output "With PrivatePerson, you can put your users in control of their own privacy policies.", :magenta
11
+ output 'With PrivatePerson, you can put your users in control of their own privacy policies.', :magenta
10
12
  end
11
13
 
12
14
  def add_migrations
13
- unless ActiveRecord::Base.connection.table_exists? 'permissions'
14
- migration_template 'migrate/create_permissions_table.rb', 'db/migrate/create_permissions_table.rb' rescue output $!.message
15
- end
15
+ return if ActiveRecord::Base.connection.table_exists? 'permissions'
16
+
17
+ migration_template 'migrate/create_permissions_table.rb',
18
+ 'db/migrate/create_permissions_table.rb'
19
+ rescue StandardError => e
20
+ output e.message
16
21
  end
17
-
22
+
23
+ # Rails::Generators::Migration (included above) declares this
24
+ # interface method but only raises NotImplementedError - every
25
+ # generator that ships a migration must supply its own. This mirrors
26
+ # ActiveRecord::Generators::Migration's own implementation, which
27
+ # can't be included directly here without also requiring
28
+ # rails/generators/active_record.rb (not autoloaded by default).
18
29
  def self.next_migration_number(dirname)
19
- if ActiveRecord::Base.timestamped_migrations
20
- unless @prev_migration_nr
21
- @prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
22
- else
23
- @prev_migration_nr += 1
24
- end
25
- @prev_migration_nr.to_s
26
- else
27
- "%.3d" % (current_migration_number(dirname) + 1)
28
- end
30
+ ActiveRecord::Migration.next_migration_number(current_migration_number(dirname) + 1)
29
31
  end
30
32
  end
31
- end
33
+ end
@@ -1,18 +1,11 @@
1
- class CreatePermissionsTable < ActiveRecord::Migration
2
- def self.up
1
+ class CreatePermissionsTable < ActiveRecord::Migration[8.0]
2
+ def change
3
3
  create_table :permissions do |t|
4
- t.string :permissor_type
5
- t.integer :permissor_id
6
- t.string :permissible_type
7
- t.integer :permissible_id
8
- t.string :relationship_type, :default => 'none'
4
+ t.references :permissor, polymorphic: true, null: false
5
+ t.references :permissible, polymorphic: true, null: true
6
+ t.string :relationship_type, default: 'none', null: false
7
+
9
8
  t.timestamps
10
9
  end
11
-
12
- add_index :permissions, [:permissor_type, :permissor_id]
13
- add_index :permissions, [:permissible_type, :permissible_id]
14
- end
15
- def self.down
16
- drop_table :permissions
17
10
  end
18
- end
11
+ end
@@ -1,16 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PrivatePerson
2
4
  module Generators
3
5
  module Utils
4
6
  def output(output, color = :green)
5
7
  say(" - #{output}", color)
6
8
  end
7
-
8
- def ask_for(wording, default_value = nil, override_if_present_value = nil)
9
- override_if_present_value.present? ?
10
- display("Using [#{override_if_present_value}] for question '#{wording}'") && override_if_present_value :
11
- ask(" ? #{wording} Press <enter> for [#{default_value}] >", :yellow).presence || default_value
12
- end
13
9
  end
14
10
  end
15
11
  end
16
-
@@ -1,20 +1,21 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PrivatePerson
2
4
  module ActsAsPermissible
3
-
4
5
  extend ActiveSupport::Concern
5
6
 
6
7
  module ClassMethods
7
8
  def acts_as_permissible(params = {})
8
- if params[:by].nil?
9
- raise 'Called acts_as_permissible, but without a :by parameter.'
10
- end
9
+ raise 'Called acts_as_permissible, but without a :by parameter.' if params[:by].nil?
10
+
11
11
  class_attribute :by
12
12
  self.by = params[:by]
13
13
 
14
- has_many :permissions, :as => :permissible, :class_name => 'PrivatePerson::Permission'
15
- has_many :permissors, :through => :permissions, :as => :permissible
14
+ has_many :permissions, as: :permissible, class_name: 'PrivatePerson::Permission'
15
+ has_many :permissors, through: :permissions, source: :permissor,
16
+ source_type: by.to_s.camelize
16
17
 
17
- send :include, InstanceMethods
18
+ include InstanceMethods
18
19
  end
19
20
  end
20
21
 
@@ -24,4 +25,4 @@ module PrivatePerson
24
25
  end
25
26
  end
26
27
  end
27
- end
28
+ end
@@ -1,58 +1,55 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PrivatePerson
2
4
  module ActsAsPermissor
3
-
4
5
  extend ActiveSupport::Concern
5
6
 
6
7
  module ClassMethods
7
8
  def acts_as_permissor(params = {})
8
- if params[:of].nil?
9
- raise 'Called acts_as_permissor, but without an :of parameter.'
10
- end
9
+ raise 'Called acts_as_permissor, but without an :of parameter.' if params[:of].nil?
10
+
11
11
  class_attribute :of
12
12
  self.of = params[:of]
13
13
  class_name = params[:class_name] || params[:of].to_s.classify
14
14
  class_name.constantize.acts_as_permitted
15
15
 
16
- has_many :permissions_as_permissor, :as => :permissor, :class_name => 'PrivatePerson::Permission'
17
- has_many :permissibles, :through => :permissions, :as => :permissor
18
-
19
- send :include, InstanceMethods
16
+ has_many :permissions_as_permissor, as: :permissor, class_name: 'PrivatePerson::Permission'
17
+ has_many :permissibles, through: :permissions_as_permissor, source: :permissible,
18
+ source_type: class_name
19
+
20
+ include InstanceMethods
20
21
  end
21
22
  end
22
23
 
23
24
  module InstanceMethods
24
25
  def permit!(whom, what)
25
- existing = self.permissions_as_permissor.by_relationship_type(whom).by_permissible(what)
26
+ existing = permissions_as_permissor.by_relationship_type(whom).by_permissible(what)
26
27
 
27
- if existing.empty?
28
- self.permissions_as_permissor.create!(permission_params(whom, what))
29
- end
30
- self.permissions_as_permissor.reload
28
+ permissions_as_permissor.create!(permission_params(whom, what)) if existing.empty?
29
+ permissions_as_permissor.reload
31
30
  end
32
31
 
33
32
  def wildcard_permit!(whom, what)
34
- existing = self.permissions_as_permissor.by_relationship_type(whom).where(:permissible_type, what)
33
+ existing = permissions_as_permissor.by_relationship_type(whom).where(permissible_type: what)
35
34
 
36
- # if existing.empty?
37
- self.permissions_as_permissor.create!(wildcard_permission_params(whom, what))
38
- # end
39
- self.permissions_as_permissor.reload
35
+ permissions_as_permissor.create!(wildcard_permission_params(whom, what)) if existing.empty?
36
+ permissions_as_permissor.reload
40
37
  end
41
38
 
42
39
  def permission_params(whom, what)
43
- ::ActionController::Parameters.new({
44
- :relationship_type => whom,
45
- :permissible_type => what.class.name,
46
- :permissible_id => what.id
47
- }).permit!
40
+ {
41
+ relationship_type: whom,
42
+ permissible_type: what.class.name,
43
+ permissible_id: what.id
44
+ }
48
45
  end
49
46
 
50
47
  def wildcard_permission_params(whom, what)
51
- ::ActionController::Parameters.new({
52
- :relationship_type => whom,
53
- :permissible_type => what
54
- }).permit!
48
+ {
49
+ relationship_type: whom,
50
+ permissible_type: what
51
+ }
55
52
  end
56
53
  end
57
54
  end
58
- end
55
+ end