fera-apps-rails 0.1.4
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 +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +32 -0
- data/app/helpers/fera/apps/views_helper.rb +27 -0
- data/app/views/fera/apps/_flash_messages.html.erb +14 -0
- data/app/views/fera/apps/layout/_content.html.erb +7 -0
- data/app/views/fera/apps/layout/_footer.html.erb +16 -0
- data/app/views/fera/apps/layout/_header.html.erb +7 -0
- data/config/initializers/app.rb +5 -0
- data/config/initializers/omniauth.rb +12 -0
- data/config/routes.rb +16 -0
- data/lib/fera/apps/concerns/controllers/auth.rb +132 -0
- data/lib/fera/apps/concerns/controllers/base.rb +34 -0
- data/lib/fera/apps/concerns/controllers/hooks.rb +51 -0
- data/lib/fera/apps/concerns/models/store.rb +96 -0
- data/lib/fera/apps/rails/engine.rb +10 -0
- data/lib/fera/apps/rails/railtie.rb +11 -0
- data/lib/fera/apps/rails/version.rb +7 -0
- data/lib/fera/apps/rails.rb +15 -0
- data/lib/fera/apps.rb +6 -0
- data/lib/fera.rb +4 -0
- metadata +249 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: f29b7ea4df02e2e3663e032927c7fabed959ea47cec5e68cd09e1a663d34c169
|
|
4
|
+
data.tar.gz: 83e5c24a7deecb92f6511b8238e5f0386eb0d8591ba97f3b28a748a95e5ae3f9
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 35d734517ec2e590481a9ac394f40bfe84db487322d9956bd443b138dbea6d3b5f646fcc03041e97d55db591ed77acb7ef225100188f377327c5226a407f1cc5
|
|
7
|
+
data.tar.gz: e122187d2954a746e4d4bba7a98832bb32d533877afb9ee3dfffc8fc5e34521218a8f32d1109671686549f0cc2ee6bad226930b85335b66a7e3ce47f84bba0e8
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Jay El-Kaake
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
[](https://github.com/feracommerce/fera-api-ruby/actions/workflows/checks.yml)
|
|
2
|
+
[](https://github.com/feracommerce/fera-api-ruby/actions/workflows/tests.yml)
|
|
3
|
+
|
|
4
|
+
# Fera Rails App Gem
|
|
5
|
+
|
|
6
|
+
This gem includes some standard functionality and design patterns for Fera apps. It makes it easier to develop
|
|
7
|
+
a Fera app that looks and feels consistent with Fera's other UIs.
|
|
8
|
+
|
|
9
|
+
# Installation
|
|
10
|
+
The best way to use this app is to checkout the [Fera Rails App Template](https://github.com/feracommerce/fera-apps-rails-template).
|
|
11
|
+
|
|
12
|
+
# Contributing
|
|
13
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/feracommerce/fera-apps-rails
|
|
14
|
+
|
|
15
|
+
To contribute to the repository:
|
|
16
|
+
|
|
17
|
+
### Starting a contribution
|
|
18
|
+
1. Fork the repository.
|
|
19
|
+
2. Clone the forked repository locally.
|
|
20
|
+
3. Create a branch descriptive of your work. For example "my_new_feature_xyz".
|
|
21
|
+
|
|
22
|
+
### Submitting your contribution.
|
|
23
|
+
1. Run `./bin/check_code` and fix any issues.
|
|
24
|
+
1. You can use `./bin/check_code -a` to auto-fix issues safely.
|
|
25
|
+
2. You can use `./bin/add_to_dictionary` to add words to the spelling checker dictionary.
|
|
26
|
+
1. When you're done work, push up that branch to **your own forked repository** (not the main one).
|
|
27
|
+
1. Visit https://github.com/feracommerce/fera-apps-rails and you'll see an option to create a pull request from your forked branch to the master.
|
|
28
|
+
1. Create a pull request by filling out the pull request template.
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# License
|
|
32
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Fera
|
|
2
|
+
module Apps
|
|
3
|
+
module ViewsHelper
|
|
4
|
+
def last_deployed_at
|
|
5
|
+
@last_deployed_at ||= File.exist?("tmp/pids") ? File.mtime("tmp/pids") : Time.now.utc
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def render_fera_app_footer
|
|
9
|
+
render(partial: "fera/apps/layout/footer")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def render_fera_app_header
|
|
13
|
+
render(partial: "fera/apps/layout/header")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def render_fera_app_flash_messages
|
|
17
|
+
render(partial: "fera/apps/flash_messages")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def render_fera_app_layout(&block)
|
|
21
|
+
render(layout: "fera/apps/layout/content") do
|
|
22
|
+
capture(&block)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<div class="fera-app-flashMessages">
|
|
2
|
+
<% if notice %>
|
|
3
|
+
<div class="alert alert-success alert-dismissible fade show" role="alert">
|
|
4
|
+
<%= notice %>
|
|
5
|
+
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
6
|
+
</div>
|
|
7
|
+
<% end %>
|
|
8
|
+
<% if alert %>
|
|
9
|
+
<div class="alert alert-danger alert-dismissible fade show" role="alert">
|
|
10
|
+
<%= alert %>
|
|
11
|
+
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
|
12
|
+
</div>
|
|
13
|
+
<% end %>
|
|
14
|
+
</div>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<footer class="fera-app-footer">
|
|
2
|
+
<div class="bottomAppNav">
|
|
3
|
+
<a href="<%= ENV['FERA_APP_URL'].chomp('/') %>/integrations/apps/<%= ENV['APP_CODE'] %>"
|
|
4
|
+
class="btn btn-sm btn-secondary">
|
|
5
|
+
<i class="bi bi-arrow-left me-2"></i> Back to Fera
|
|
6
|
+
</a>
|
|
7
|
+
</div>
|
|
8
|
+
<div class="copyrightAndLinks">
|
|
9
|
+
<!-- Last deploy: <%= last_deployed_at %> -->
|
|
10
|
+
<a href="https://www.fera.ai">Fera™️</a> © <%= Time.now.year %>
|
|
11
|
+
| <a href="https://www.fera.ai/privacy-policy" target="_blank">Privacy Policy</a>
|
|
12
|
+
| <a href="https://www.fera.ai/terms-of-service" target="_blank">Terms of Service</a>
|
|
13
|
+
| <a href="https://help.fera.ai" target="_blank">Support</a>
|
|
14
|
+
| <a href="https://app.fera.ai" target="_blank">Fera Dashboard</a>
|
|
15
|
+
</div>
|
|
16
|
+
</footer>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<header class="fera-app-header">
|
|
2
|
+
<div class="header-image">
|
|
3
|
+
<img src="https://uploads.fera.ai/brand/fera_app_blank_header.svg" class="background-image" alt="Fera icon">
|
|
4
|
+
<span class="app-icon-container"><%= image_tag("icon.png", class: "app-icon", alt: "#{ ENV['APP_NAME'] } icon") %></span>
|
|
5
|
+
</div>
|
|
6
|
+
<h1 class="header-title"><%= ENV.fetch("APP_TITLE", "Fera #{ ENV['APP_NAME'] } App") %></h1>
|
|
7
|
+
</header>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# This is to interact with the Fera APP globally
|
|
2
|
+
$fera_app = Fera::App.new(ENV.fetch("FERA_CLIENT_ID", nil), ENV.fetch("FERA_CLIENT_SECRET", nil),
|
|
3
|
+
app_url: ENV.fetch("FERA_APP_URL", nil),
|
|
4
|
+
api_url: ENV.fetch("FERA_API_URL", nil),
|
|
5
|
+
debug_mode: ::Rails.env.development?)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require 'omniauth-fera'
|
|
2
|
+
|
|
3
|
+
OmniAuth.config.allowed_request_methods = [:get, :post]
|
|
4
|
+
|
|
5
|
+
::Rails.application.config.middleware.use OmniAuth::Builder do
|
|
6
|
+
provider :fera,
|
|
7
|
+
ENV.fetch('FERA_CLIENT_ID', nil),
|
|
8
|
+
ENV.fetch('FERA_CLIENT_SECRET', nil),
|
|
9
|
+
callback_url: ENV.fetch('FERA_REDIRECT_URI', nil),
|
|
10
|
+
scope: ENV.fetch('FERA_CLIENT_SCOPES', "read write"),
|
|
11
|
+
client_options: { site: ENV["FERA_APP_URL"].presence || ENV["FERA_PROVIDER_URL"].presence || "https://app.fera.ai" }
|
|
12
|
+
end
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
::Rails.application.routes.draw do
|
|
2
|
+
# This route is what the omniauth2 gem uses
|
|
3
|
+
get "auth/fera/callback" => "fera/auth#callback"
|
|
4
|
+
|
|
5
|
+
namespace :fera do
|
|
6
|
+
get "auth" => redirect(path: "/auth/fera") # @alias since omniauth gem path is not consistent with our pattern here
|
|
7
|
+
get "auth/check" => "auth#check"
|
|
8
|
+
get "auth/disconnect" => "auth#disconnect"
|
|
9
|
+
get "auth/load" => "auth#load"
|
|
10
|
+
get "auth/success" => "auth#success"
|
|
11
|
+
get "auth/test" => "auth#test"
|
|
12
|
+
|
|
13
|
+
# All apps should have an uninstall hook to cleanup data if app is uninstalled from Fera's side
|
|
14
|
+
post "hooks/app_uninstall" => "hooks#app_uninstall"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
module Fera
|
|
2
|
+
module Apps
|
|
3
|
+
module Controllers
|
|
4
|
+
module Auth
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
before_action :load_store_from_jwt!, only: [:load, :test, :check]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
##
|
|
12
|
+
# GET /auth/fera/callback
|
|
13
|
+
def callback
|
|
14
|
+
if @store.try(:fera_id) != params[:store_id]
|
|
15
|
+
@store = ::Store.find_or_initialize_by(fera_id: params[:store_id]) # Fera::Store also exists so make sure to include `::` prefix to reference right class
|
|
16
|
+
end
|
|
17
|
+
@store.install_fera!(request)
|
|
18
|
+
|
|
19
|
+
set_current_store(@store)
|
|
20
|
+
|
|
21
|
+
after_fera_callback
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
##
|
|
25
|
+
# You should override this in your own controller.
|
|
26
|
+
def after_fera_callback
|
|
27
|
+
::Rails.logger.warn("#after_fera_callback not implemented in your controller, so the default action was to redirect to the root_path")
|
|
28
|
+
redirect_to root_path
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# Override this to send them someone else
|
|
33
|
+
# @GET /fera/auth/load
|
|
34
|
+
def load
|
|
35
|
+
redirect_to root_path
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
##
|
|
39
|
+
# @GET /fera/auth/disconnect
|
|
40
|
+
def disconnect
|
|
41
|
+
if @store.present?
|
|
42
|
+
@store.destroy!
|
|
43
|
+
redirect_to root_path, notice: "Disconnected app from Fera successfully."
|
|
44
|
+
else
|
|
45
|
+
redirect_to root_path, flash: { error: "Not connected to Fera, so disconnecting did nothing." }
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
##
|
|
50
|
+
# @GET /fera/auth/test
|
|
51
|
+
def test
|
|
52
|
+
respond_to do |format|
|
|
53
|
+
format.json { render json: status_result, status: status_result[:status] }
|
|
54
|
+
format.html do
|
|
55
|
+
redirect_to fera_app_relay_url(status_result[:status], status_result[:message])
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
##
|
|
61
|
+
# GET /fera/auth/success
|
|
62
|
+
def success
|
|
63
|
+
redirect_to fera_app_relay_url(fera_app_connect_success_msg)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
##
|
|
67
|
+
# GET /fera/auth/check
|
|
68
|
+
# GET /fera/auth/check.json
|
|
69
|
+
def check
|
|
70
|
+
respond_to do |format|
|
|
71
|
+
format.json { render json: status_result, status: status_result[:status] }
|
|
72
|
+
format.html do
|
|
73
|
+
redirect_to root_path, (status_result[:status] == :connected ? :notice : :alert) => status_result[:message], status: status_result[:status]
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private
|
|
79
|
+
|
|
80
|
+
def status_result
|
|
81
|
+
@status_result ||= generate_status_response || { status: :ok, message: "Everything appears to be operational!" }
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
##
|
|
85
|
+
# Override this to set a custom message
|
|
86
|
+
def fera_app_connect_success_msg
|
|
87
|
+
"Connected #{ ENV.fetch('APP_NAME', 'app') } to Fera successfully!"
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
##
|
|
91
|
+
# Returns nil if everything is OK.
|
|
92
|
+
# Otherwise returns the status code and error message.
|
|
93
|
+
#
|
|
94
|
+
# @return [Hash, NilClass] with two keys: :status and :message. Status should be a symbol that matches the strings at HTTP_STATUS_CODES
|
|
95
|
+
def generate_status_response
|
|
96
|
+
if @store.blank?
|
|
97
|
+
{ status: :not_found, message: "App not installed." }
|
|
98
|
+
elsif !@store.connected_to_fera?
|
|
99
|
+
{ status: :not_authorized, message: "Fera app not installed." }
|
|
100
|
+
elsif !@store.check_fera_connection
|
|
101
|
+
{ status: :server_error, message: "Fera connection lost. Please re-install the Fera app." }
|
|
102
|
+
else
|
|
103
|
+
nil # Everything is OK
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def load_store_from_jwt!
|
|
108
|
+
data = $fera_app.decode_jwt(params[:jwt])
|
|
109
|
+
|
|
110
|
+
if data.blank?
|
|
111
|
+
message = "Something went wrong. Try refreshing the page and connecting your Fera account."
|
|
112
|
+
respond_to do |format|
|
|
113
|
+
format.json { render json: { message: message }, status: :unauthorized }
|
|
114
|
+
format.html { redirect_to root_path, alert: message }
|
|
115
|
+
end
|
|
116
|
+
else
|
|
117
|
+
@store = ::Store.find_by(fera_id: data[:store_id]) # Fera::Store also exists so make sure to include `::` prefix to reference right class
|
|
118
|
+
set_current_store(@store)
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
##
|
|
123
|
+
# @param message [String] Message to display to the user in Fera app
|
|
124
|
+
# @param status [Symbol, Integer] Status, from Rack::Utils::HTTP_STATUS_CODES. Default: :ok, which is 200 and success
|
|
125
|
+
def fera_app_relay_url(message, status: :ok)
|
|
126
|
+
url = "#{ ENV.fetch('FERA_APP_URL', 'https://app.fera.ai').chomp('/') }/integrations/apps/#{ ENV.fetch('APP_CODE', nil) }/relay"
|
|
127
|
+
"#{ url }?jwt=#{ $fera_app.encode_jwt(store_id: @store.fera_id, message: message, exp: 1.hour.from_now.to_i, status: status) }"
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Fera
|
|
2
|
+
module Apps
|
|
3
|
+
module Controllers
|
|
4
|
+
module Base
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
before_action :store
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def load_store
|
|
14
|
+
if session[:store_id].present?
|
|
15
|
+
::Store.find(session[:store_id])
|
|
16
|
+
else
|
|
17
|
+
nil
|
|
18
|
+
end
|
|
19
|
+
rescue ActiveRecord::RecordNotFound
|
|
20
|
+
nil
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def store
|
|
24
|
+
@store ||= load_store
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def set_current_store(store) # rubocop:disable Naming/AccessorMethodName
|
|
28
|
+
session[:store_id] = store.id
|
|
29
|
+
@store = store
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module Fera
|
|
2
|
+
module Apps
|
|
3
|
+
module Controllers
|
|
4
|
+
module Hooks
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
# Since these are webhooks we will validate the signatures using JWT as per Fera docs, so we don't need Rails to do it's
|
|
9
|
+
# default security token checks upon POST requests.
|
|
10
|
+
skip_forgery_protection
|
|
11
|
+
|
|
12
|
+
before_action :load_store_from_token
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
##
|
|
16
|
+
# POST /fera/hooks/app_uninstall
|
|
17
|
+
# All apps should have an uninstall hook to cleanup data if app is uninstalled from Fera's side
|
|
18
|
+
def app_uninstall
|
|
19
|
+
@store.destroy!
|
|
20
|
+
|
|
21
|
+
::Rails.logger.info("Deleted store #{ @store.id } triggered by Fera uninstall webhook.")
|
|
22
|
+
|
|
23
|
+
head :ok
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# ##
|
|
27
|
+
# # This is just here as an example
|
|
28
|
+
# # POST /fera/hooks/review_create
|
|
29
|
+
# def review_create
|
|
30
|
+
# ::Rails.logger.info("Received review_create webhook from Fera for store ##{ @store.id } and review ##{ params[:id] }.")
|
|
31
|
+
#
|
|
32
|
+
# # You'll get a post here with the review data as well as the review id if you want to grab a fresh copy.
|
|
33
|
+
# # If you want a fresh review copy you do this:
|
|
34
|
+
# # @store.fera_api do
|
|
35
|
+
# # review = Fera::Review.find(params[:id])
|
|
36
|
+
# # puts "Wow, that's a sweet new #{ review.stars } review from #{ review.customer.display_name }: #{ review.body }"
|
|
37
|
+
# # end
|
|
38
|
+
#
|
|
39
|
+
# head :ok
|
|
40
|
+
# end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def load_store_from_token
|
|
45
|
+
@token_data = $fera_app.decode_jwt(params[:jwt])
|
|
46
|
+
@store = ::Store.find_by(fera_id: @token_data[:store_id]) # Fera::Store also exists so make sure to include `::` prefix to reference right class
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
module Fera
|
|
2
|
+
module Apps
|
|
3
|
+
module Models
|
|
4
|
+
module Store
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
define_model_callbacks :install_fera
|
|
9
|
+
define_model_callbacks :uninstall_fera
|
|
10
|
+
|
|
11
|
+
scope :with_fera_id, -> (fera_id) { where(fera_id: fera_id) }
|
|
12
|
+
|
|
13
|
+
before_destroy :revoke_fera_token!, if: -> { fera_auth_token.present? }
|
|
14
|
+
|
|
15
|
+
validates_uniqueness_of :fera_id, if: :connected_to_fera?
|
|
16
|
+
validates :fera_domain, presence: true, if: :connected_to_fera?
|
|
17
|
+
validates :fera_domain, format: { with: /\A[a-z0-9][a-z0-9.-]+[a-z]\z/i, message: "can only contain letters, numbers, . or -" }, if: :connected_to_fera?
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def install_fera!(request)
|
|
21
|
+
run_callbacks(:install_fera) do
|
|
22
|
+
auth_data = request.env['omniauth.auth']['credentials']
|
|
23
|
+
|
|
24
|
+
self.fera_auth_token = auth_data['token']
|
|
25
|
+
self.fera_domain = request.params[:store_domain]
|
|
26
|
+
|
|
27
|
+
save!
|
|
28
|
+
|
|
29
|
+
fera_api do
|
|
30
|
+
install_fera_webhooks!
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def connected_to_fera?
|
|
36
|
+
fera_auth_token.present?
|
|
37
|
+
end
|
|
38
|
+
alias_method :fera_connected?, :connected_to_fera?
|
|
39
|
+
|
|
40
|
+
def check_fera_connection
|
|
41
|
+
return false unless connected_to_fera?
|
|
42
|
+
|
|
43
|
+
fera_api do
|
|
44
|
+
::Fera::Store.current
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
true
|
|
48
|
+
rescue ActiveResource::ConnectionError
|
|
49
|
+
false
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def disconnect_fera!
|
|
53
|
+
revoke_fera_token! if connected_to_fera?
|
|
54
|
+
|
|
55
|
+
remove_fera_attributes!
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def install_fera_webhooks!
|
|
59
|
+
# Here is some example code you can use to install webhooks:
|
|
60
|
+
#
|
|
61
|
+
# hook = Fera::Webhook.where(event_name: :review_create).try(:first)
|
|
62
|
+
# hook ||= Fera::Webhook.new(event_name: :review_create)
|
|
63
|
+
# hook.is_enabled = true
|
|
64
|
+
# hook.url = "#{ ENV.fetch('BASE_APP_URL', nil) }/fera/hooks/review_create"
|
|
65
|
+
# hook.save!
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def revoke_fera_token!
|
|
71
|
+
return unless fera_auth_token.present?
|
|
72
|
+
|
|
73
|
+
$fera_app.revoke_token!(fera_auth_token)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def remove_fera_attributes!
|
|
77
|
+
update(
|
|
78
|
+
fera_id: nil,
|
|
79
|
+
fera_auth_token: nil,
|
|
80
|
+
fera_domain: nil
|
|
81
|
+
)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
##
|
|
85
|
+
# Run Fera::API methods in the scope of the current store.
|
|
86
|
+
# fera_api { ::Fera::Store.current }
|
|
87
|
+
# @return [Object] Result of block provided
|
|
88
|
+
def fera_api(&block)
|
|
89
|
+
Fera::API.configure(fera_auth_token,
|
|
90
|
+
api_url: ENV.fetch("FERA_API_URL", nil),
|
|
91
|
+
&block)
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'active_support'
|
|
2
|
+
require 'active_support/concern'
|
|
3
|
+
require_relative "concerns/controllers/base"
|
|
4
|
+
require_relative "concerns/controllers/auth"
|
|
5
|
+
require_relative "concerns/controllers/hooks"
|
|
6
|
+
require_relative "concerns/models/store"
|
|
7
|
+
require_relative "./rails/railtie"
|
|
8
|
+
require_relative "./rails/engine"
|
|
9
|
+
|
|
10
|
+
module Fera
|
|
11
|
+
module Apps
|
|
12
|
+
module Rails
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
data/lib/fera/apps.rb
ADDED
data/lib/fera.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: fera-apps-rails
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.4
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Fera Commerce Inc
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2022-08-25 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: actionview
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '6.1'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '6.1'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: activesupport
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '6.1'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '6.1'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: fera-api
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :runtime
|
|
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: omniauth-fera
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :runtime
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: omniauth-oauth2
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '1.3'
|
|
76
|
+
type: :runtime
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '1.3'
|
|
83
|
+
- !ruby/object:Gem::Dependency
|
|
84
|
+
name: rails
|
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ">="
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '6.1'
|
|
90
|
+
type: :runtime
|
|
91
|
+
prerelease: false
|
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
93
|
+
requirements:
|
|
94
|
+
- - ">="
|
|
95
|
+
- !ruby/object:Gem::Version
|
|
96
|
+
version: '6.1'
|
|
97
|
+
- !ruby/object:Gem::Dependency
|
|
98
|
+
name: railties
|
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
|
100
|
+
requirements:
|
|
101
|
+
- - ">="
|
|
102
|
+
- !ruby/object:Gem::Version
|
|
103
|
+
version: '6.1'
|
|
104
|
+
type: :runtime
|
|
105
|
+
prerelease: false
|
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
107
|
+
requirements:
|
|
108
|
+
- - ">="
|
|
109
|
+
- !ruby/object:Gem::Version
|
|
110
|
+
version: '6.1'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: pry
|
|
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: pry-byebug
|
|
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
|
+
- !ruby/object:Gem::Dependency
|
|
140
|
+
name: pry-stack_explorer
|
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
|
142
|
+
requirements:
|
|
143
|
+
- - ">="
|
|
144
|
+
- !ruby/object:Gem::Version
|
|
145
|
+
version: '0'
|
|
146
|
+
type: :development
|
|
147
|
+
prerelease: false
|
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
149
|
+
requirements:
|
|
150
|
+
- - ">="
|
|
151
|
+
- !ruby/object:Gem::Version
|
|
152
|
+
version: '0'
|
|
153
|
+
- !ruby/object:Gem::Dependency
|
|
154
|
+
name: rspec
|
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
|
156
|
+
requirements:
|
|
157
|
+
- - ">="
|
|
158
|
+
- !ruby/object:Gem::Version
|
|
159
|
+
version: '3.0'
|
|
160
|
+
type: :development
|
|
161
|
+
prerelease: false
|
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
163
|
+
requirements:
|
|
164
|
+
- - ">="
|
|
165
|
+
- !ruby/object:Gem::Version
|
|
166
|
+
version: '3.0'
|
|
167
|
+
- !ruby/object:Gem::Dependency
|
|
168
|
+
name: to_bool
|
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
|
170
|
+
requirements:
|
|
171
|
+
- - "~>"
|
|
172
|
+
- !ruby/object:Gem::Version
|
|
173
|
+
version: '2.0'
|
|
174
|
+
type: :development
|
|
175
|
+
prerelease: false
|
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
177
|
+
requirements:
|
|
178
|
+
- - "~>"
|
|
179
|
+
- !ruby/object:Gem::Version
|
|
180
|
+
version: '2.0'
|
|
181
|
+
- !ruby/object:Gem::Dependency
|
|
182
|
+
name: webmock
|
|
183
|
+
requirement: !ruby/object:Gem::Requirement
|
|
184
|
+
requirements:
|
|
185
|
+
- - ">="
|
|
186
|
+
- !ruby/object:Gem::Version
|
|
187
|
+
version: '3.0'
|
|
188
|
+
type: :development
|
|
189
|
+
prerelease: false
|
|
190
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
191
|
+
requirements:
|
|
192
|
+
- - ">="
|
|
193
|
+
- !ruby/object:Gem::Version
|
|
194
|
+
version: '3.0'
|
|
195
|
+
description: Checkout the Fera Rails App github repo to get started with a beautiful
|
|
196
|
+
Fera App integration.
|
|
197
|
+
email:
|
|
198
|
+
- developers@fera.ai
|
|
199
|
+
executables: []
|
|
200
|
+
extensions: []
|
|
201
|
+
extra_rdoc_files: []
|
|
202
|
+
files:
|
|
203
|
+
- LICENSE.txt
|
|
204
|
+
- README.md
|
|
205
|
+
- app/helpers/fera/apps/views_helper.rb
|
|
206
|
+
- app/views/fera/apps/_flash_messages.html.erb
|
|
207
|
+
- app/views/fera/apps/layout/_content.html.erb
|
|
208
|
+
- app/views/fera/apps/layout/_footer.html.erb
|
|
209
|
+
- app/views/fera/apps/layout/_header.html.erb
|
|
210
|
+
- config/initializers/app.rb
|
|
211
|
+
- config/initializers/omniauth.rb
|
|
212
|
+
- config/routes.rb
|
|
213
|
+
- lib/fera.rb
|
|
214
|
+
- lib/fera/apps.rb
|
|
215
|
+
- lib/fera/apps/concerns/controllers/auth.rb
|
|
216
|
+
- lib/fera/apps/concerns/controllers/base.rb
|
|
217
|
+
- lib/fera/apps/concerns/controllers/hooks.rb
|
|
218
|
+
- lib/fera/apps/concerns/models/store.rb
|
|
219
|
+
- lib/fera/apps/rails.rb
|
|
220
|
+
- lib/fera/apps/rails/engine.rb
|
|
221
|
+
- lib/fera/apps/rails/railtie.rb
|
|
222
|
+
- lib/fera/apps/rails/version.rb
|
|
223
|
+
homepage: https://developers.fera.ai
|
|
224
|
+
licenses:
|
|
225
|
+
- MIT
|
|
226
|
+
metadata:
|
|
227
|
+
homepage_uri: https://developers.fera.ai
|
|
228
|
+
rubygems_mfa_required: 'true'
|
|
229
|
+
post_install_message:
|
|
230
|
+
rdoc_options: []
|
|
231
|
+
require_paths:
|
|
232
|
+
- lib
|
|
233
|
+
- app
|
|
234
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
235
|
+
requirements:
|
|
236
|
+
- - ">="
|
|
237
|
+
- !ruby/object:Gem::Version
|
|
238
|
+
version: '2.7'
|
|
239
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
240
|
+
requirements:
|
|
241
|
+
- - ">="
|
|
242
|
+
- !ruby/object:Gem::Version
|
|
243
|
+
version: '0'
|
|
244
|
+
requirements: []
|
|
245
|
+
rubygems_version: 3.1.6
|
|
246
|
+
signing_key:
|
|
247
|
+
specification_version: 4
|
|
248
|
+
summary: Fera Rails App Gem
|
|
249
|
+
test_files: []
|