audiences 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 301017a77754bc9639d80ae7cf2a5260c1a6811e9bec5c49daefaca3b9833220
4
+ data.tar.gz: bd65ad4e4baf6577420716c58b75921700cd866d43514cf7c18978d564b0d5e7
5
+ SHA512:
6
+ metadata.gz: 0af804e8e6e477a2248b80339721897e3dd48ba27aa34f3524dbef8e5fd0cf09de9feaee0093fa2208030b7a194385e2313157a20f64cc3b536e719ac35d1b5d
7
+ data.tar.gz: '08b631ec00c43818f1537ee222df54e196df0f6cb918e6cd45eb23c552a70b9d953a3a25c8774bf3d842360be406cdee4d9ffd89e54d33bd0760d8182348b637'
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env rake
2
+
3
+ # frozen_string_literal: true
4
+
5
+ require "bundler/setup"
6
+ require "bundler/gem_tasks"
7
+
8
+ require "rspec/core/rake_task"
9
+ RSpec::Core::RakeTask.new(spec: %w[app:db:drop app:db:prepare])
10
+
11
+ require "rubocop/rake_task"
12
+ RuboCop::RakeTask.new(:rubocop)
13
+
14
+ APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
15
+ load "rails/tasks/engine.rake"
16
+ load "rails/tasks/statistics.rake"
17
+
18
+ task default: %i[rubocop spec]
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Audiences
4
+ class ApplicationController < ActionController::API
5
+ end
6
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Audiences
4
+ class ContextsController < ApplicationController
5
+ def show
6
+ render json: current_context.as_json(only: %w[match_all], methods: %w[key criteria])
7
+ end
8
+
9
+ private
10
+
11
+ def current_context
12
+ @current_context ||= Audiences.load(params[:key])
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "audiences/scim_proxy"
4
+
5
+ module Audiences
6
+ class ScimProxyController < ApplicationController
7
+ def get
8
+ status, body = ScimProxy.get(params[:scim_path], scim_params)
9
+
10
+ render body: body, status: status, content_type: "application/json"
11
+ end
12
+
13
+ private
14
+
15
+ def scim_params
16
+ params.except(:scim_path, :controller, :action).permit!.to_h
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Audiences
4
+ class ApplicationJob < ActiveJob::Base
5
+ end
6
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Audiences
4
+ # @private
5
+ class ApplicationRecord < ActiveRecord::Base
6
+ self.abstract_class = true
7
+ end
8
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Audiences
4
+ class Context < ApplicationRecord
5
+ belongs_to :owner, polymorphic: true
6
+
7
+ def key
8
+ Audiences.sign(owner)
9
+ end
10
+
11
+ def criteria
12
+ []
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Audiences</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <%= stylesheet_link_tag "audiences/application", media: "all" %>
9
+ </head>
10
+ <body>
11
+
12
+ <%= yield %>
13
+
14
+ </body>
15
+ </html>
data/config/routes.rb ADDED
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ Audiences::Engine.routes.draw do
4
+ get "/scim(/*scim_path)" => "scim_proxy#get", as: :scim_proxy
5
+ get "/:key" => "contexts#show", as: :signed_context
6
+ end
7
+
8
+ Rails.application.routes.draw do
9
+ mount Audiences::Engine, at: "/audiences", as: :audiences
10
+
11
+ direct :audience_context do |owner, options|
12
+ audiences.route_for(:signed_context, key: Audiences.sign(owner), **options)
13
+ end
14
+
15
+ direct :audience_scim_proxy do |options|
16
+ audiences.route_for(:scim_proxy, **options)
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ class CreateAudiencesContexts < ActiveRecord::Migration[6.0]
4
+ def change
5
+ create_table :audiences_contexts do |t|
6
+ t.references :owner, polymorphic: true, null: false, index: { unique: true }
7
+ t.boolean :match_all, default: false, null: false
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+ end
data/docs/CHANGELOG.md ADDED
File without changes
data/docs/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # Audiences
2
+
3
+ "Audiences" is a SCIM-integrated notifier for real-time Rails actions based on group changes.
4
+
5
+ ## Usage
6
+
7
+ ### Creating/Managing audiences
8
+
9
+ An audience is tied to an owning model withing your application. For the rest of this document we're going to assume a model Team. To create audiences for a team, using `audiences-react`, you'll render an audiences editor for your model.
10
+
11
+ That can be done with a unobstrusive JS renderer like react-rails, or a custom one as in [our dummy app](../audiences/spec/dummy/app/frontend/entrypoints/application.js). The editor will need two arguments:
12
+
13
+ - The context URI: `audience_context_url(owner)` helper
14
+ - The SCIM endpoint: `audience_scim_proxy_url` helper if using the [proxy](#configuring-the-scim-proxy), or the SCIM endpoint.
15
+
16
+ ### Listening to audience changes
17
+
18
+ **TBD**
19
+
20
+ ### Configuring the SCIM proxy
21
+
22
+ The Audience::ScimProxy should point to the real SCIM endpoint. The proxy allows you to configure the endpoint and the credentials/headers:
23
+
24
+ I.e.:
25
+
26
+ ```ruby
27
+ # frozen_string_literal: true
28
+
29
+ require "audiences/scim_proxy"
30
+
31
+ Audiences::ScimProxy.config = {
32
+ uri: "http://super-secret-scim.com/scim/v2/",
33
+ headers: {
34
+ "Authorization": "Beaer very-secret"
35
+ }
36
+ debug: $stdout,
37
+ }
38
+ ```
39
+
40
+ ## Installation
41
+
42
+ Add this line to your application's Gemfile:
43
+
44
+ ```ruby
45
+ gem "audiences"
46
+ ```
47
+
48
+ And then execute:
49
+
50
+ ```bash
51
+ $ bundle
52
+ ```
53
+
54
+ Or install it yourself as:
55
+
56
+ ```bash
57
+ $ gem install audiences
58
+ ```
59
+
60
+ ## Contributing
61
+
62
+ See [development guide](../../docs/development.md).
63
+
64
+ ## License
65
+
66
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "audiences"
4
+
5
+ module Audiences
6
+ # Audiences Engine
7
+ #
8
+ # i.e.: `mount Audiences::Engine`
9
+ #
10
+ class Engine < ::Rails::Engine
11
+ isolate_namespace Audiences
12
+ end
13
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "net/http"
4
+ require "uri"
5
+
6
+ module Audiences
7
+ module ScimProxy
8
+ mattr_accessor :config do
9
+ {}
10
+ end
11
+
12
+ module_function
13
+
14
+ def get(path, query)
15
+ response = perform_request(path: path, method: :Get, query: query)
16
+
17
+ [response.code, response.body]
18
+ end
19
+
20
+ private_class_method def perform_request(method:, path:, query: {})
21
+ uri = URI.join(config[:uri], path)
22
+ uri.query = URI.encode_www_form(query)
23
+ request = ::Net::HTTP.const_get(method).new(uri, config[:headers])
24
+
25
+ http = ::Net::HTTP.new(uri.host, uri.port)
26
+ http.use_ssl = uri.scheme == "https"
27
+
28
+ http.request(request)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Audiences
4
+ VERSION = "0.1.0"
5
+ end
data/lib/audiences.rb ADDED
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "audiences/version"
4
+
5
+ # Audiences system
6
+ # Audiences pushes notifications to your rails app when a
7
+ # SCIM backend updates a user, notifying matching audiences.
8
+ #
9
+ module Audiences
10
+ GID_RESOURCE = "audiences"
11
+
12
+ module_function
13
+
14
+ # Provides a key to load an audience context for the given owner.
15
+ # An owner should implment GlobalID::Identification.
16
+ #
17
+ # @param owner [GlobalID::Identification] an owning model
18
+ # @return [String] context key
19
+ #
20
+ def sign(owner)
21
+ owner.to_sgid(for: GID_RESOURCE)
22
+ end
23
+
24
+ # Loads a context for the given context key
25
+ #
26
+ # @param token [String] a signed token (see #sign)
27
+ # @return Audience::Context
28
+ #
29
+ def load(key)
30
+ owner = GlobalID::Locator.locate_signed(key, for: GID_RESOURCE)
31
+ ::Audiences::Context.where(owner: owner).first_or_create!.tap(&:readonly!)
32
+ end
33
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+ # desc "Explaining what the task does"
3
+ # task :audiences do
4
+ # # Task goes here
5
+ # end
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: audiences
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Carlos Palhares
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-08-16 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: '6.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '6.0'
27
+ description: Audiences notify the Rails app when a SCIM backend updates a user affecting
28
+ matching audiences
29
+ email:
30
+ - carlos.palhares@powerhrg.com
31
+ executables: []
32
+ extensions: []
33
+ extra_rdoc_files: []
34
+ files:
35
+ - Rakefile
36
+ - app/controllers/audiences/application_controller.rb
37
+ - app/controllers/audiences/contexts_controller.rb
38
+ - app/controllers/audiences/scim_proxy_controller.rb
39
+ - app/jobs/audiences/application_job.rb
40
+ - app/models/audiences/application_record.rb
41
+ - app/models/audiences/context.rb
42
+ - app/views/layouts/audiences/application.html.erb
43
+ - config/routes.rb
44
+ - db/migrate/20230725194934_create_audiences_contexts.rb
45
+ - docs/CHANGELOG.md
46
+ - docs/README.md
47
+ - lib/audiences.rb
48
+ - lib/audiences/engine.rb
49
+ - lib/audiences/scim_proxy.rb
50
+ - lib/audiences/version.rb
51
+ - lib/tasks/audiences_tasks.rake
52
+ homepage: https://github.com/powerhome/power-tools
53
+ licenses:
54
+ - MIT
55
+ metadata:
56
+ homepage_uri: https://github.com/powerhome/power-tools
57
+ source_code_uri: https://github.com/powerhome/power-tools
58
+ changelog_uri: https://github.com/powerhome/power-tools/blob/main/packages/audiences/docs/CHANGELOG.md
59
+ rubygems_mfa_required: 'true'
60
+ post_install_message:
61
+ rdoc_options: []
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '2.7'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ requirements: []
75
+ rubygems_version: 3.4.10
76
+ signing_key:
77
+ specification_version: 4
78
+ summary: Audiences system
79
+ test_files: []