Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature] Turbo Drive and Sessions in iOS #1542

Merged
merged 12 commits into from
Apr 29, 2023
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.development
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ REDIS_URL=redis://solutions_redis:6379/12
APP_HOST=localhost
RECAPTCHA_SITE_KEY=foocvi0PSRc_AyhjP7jcN
RECAPTCHA_SECRET_KEY=bar8saabKym-6u5KGh
RACK_TIMEOUT_SERVICE_TIMEOUT=500
VIOLET_SERVICE_TIMEOUT=500
2 changes: 1 addition & 1 deletion app/assets/javascripts/comfy/admin/cms/custom.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

//= require select2

let subdomain = /:\/\/([^\/]+)/.exec(window.location.href)[1].split('.')[0]
var subdomain = /:\/\/([^\/]+)/.exec(window.location.href)[1].split('.')[0]
document.title = `${subdomain} Admin`

// when html body is clicked collapse bootstrap nav expansion
Expand Down
38 changes: 2 additions & 36 deletions app/controllers/concerns/twofactor_authenticable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,41 +23,11 @@ def redirect_with_js(url)
def resend_otp
user = find_user
prompt_for_otp_two_factor(user)
render 'users/sessions/two_factor'
redirect_back fallback_location: root_path, notice: t('devise.otp.sent_to_email')
end

include ApplicationHelper
def authenticate_with_otp_two_factor
user = self.resource = find_user
if session[:otp_user_id]
authenticate_user_with_otp_two_factor(user)
elsif user&.valid_password?(user_params[:password])
if user&.current_sign_in_ip != request&.remote_ip
prompt_for_otp_two_factor(user)
render 'users/sessions/two_factor'
else
sign_in(user)
session.delete(:otp_user_id)
end
end
end

def authenticate_user_with_otp_two_factor(user)
if valid_otp_attempt?(user)
session.delete(:otp_user_id)
remember_me(user) if user_params[:remember_me] == '1'
user.save!
sign_in(user, event: :authentication)
else
if params[:user][:otp_attempt].present?
flash.now[:alert] = 'Invalid two-factor code.'
else
flash.now[:alert] = 'OTP Required.'
end
render 'users/sessions/two_factor'
end
end


def user_params
params.require(:user).permit(:email, :password, :remember_me, :otp_attempt)
end
Expand All @@ -70,10 +40,6 @@ def find_user
end
end

def otp_two_factor_enabled?
find_user&.otp_required_for_login && enable_2fa?
end

def generate_and_prompt_for_otp_two_factor(user)
@user = user
@user.generate_two_factor_secret_if_missing!
Expand Down
25 changes: 25 additions & 0 deletions app/controllers/users/otp/sessions_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
class Users::Otp::SessionsController < DeviseController
prepend_before_action :require_no_authentication, only: [:new, :create]

def new
unless User.exists?(session[:otp_user_id])
session[:otp_user_id] = nil
redirect_to new_user_session_path
else
render 'users/otp/sessions/new'
end
end

def create
resource = warden.authenticate(:otp_attempt_authenticatable, scope: resource_name)

if resource
set_flash_message!(:notice, :signed_in)
sign_in(resource_name, resource)
respond_with resource, location: after_sign_in_path_for(resource)
else
flash[:danger]= t("devise.otp.invalid")
redirect_to users_sign_in_otp_path
end
end
end
38 changes: 26 additions & 12 deletions app/controllers/users/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,34 @@
class Users::SessionsController < Devise::SessionsController
# before_action :configure_sign_in_params, only: [:create]

include TwofactorAuthenticable

prepend_before_action :authenticate_with_otp_two_factor,
if: -> { action_name == 'create' && otp_two_factor_enabled? }

protect_from_forgery with: :exception, prepend: true, except: :destroy

# GET /resource/sign_in
def new
session.delete(:otp_user_id)
super
end

# POST /resource/sign_in
# def create
# def new
# # session.delete(:otp_user_id)
# super
# end

def create
request.env['devise.skip_trackable'] = true
self.resource = warden.authenticate!(:database_authenticatable, auth_options)

if prompt_for_otp?(resource)
sign_out(resource)
UserMailer.send_otp(resource).deliver_later
session[:otp_user_id] = resource.id
redirect_to users_sign_in_otp_path
else
request.env['devise.skip_trackable'] = false
resource.update_tracked_fields!(request)
set_flash_message!(:notice, :signed_in)
sign_in(resource_name, resource)

redirect_to after_sign_in_path_for(resource), status: :see_other
end
end


# DELETE /resource/sign_out
# def destroy
# super
Expand All @@ -38,4 +48,8 @@ def new
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_in, keys: [:otp_attempt])
end

def prompt_for_otp?(resource)
Subdomain.current.enable_2fa && resource.otp_required_for_login && resource.current_sign_in_ip != request.remote_ip
end
end
39 changes: 39 additions & 0 deletions app/javascript/packs/comfy/admin/cms.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,43 @@ window.addEventListener('DOMContentLoaded', (event) => {
})
})

$(document).on("turbo:load", () => {
$('[data-violet-jsoneditor]').each(function() {
const editor = new JSONEditor(this, {
onChange: () => { setFields(this, editor.get()) },
mode: `${this.dataset.mode || 'tree'}`
})

// set json
const initialJson = {
"Array": [1, 2, 3],
"Boolean": true,
"Null": null,
"Number": 123,
"Object": {"a": "b", "c": "d"},
"String": "Hello World"
}

editor.set(initialJson)
let existingValue = $(`#${this.dataset.target}`).val()

if (existingValue) {
let json = JSON.parse(existingValue)
$(`#${this.dataset.target}`).val(existingValue)
editor.set(json)
} else {
setFields(this, editor.get())
}
// get json
const updatedJson = editor.get()
})
});

function setFields(container, content) {
$(`#${container.dataset.target}`).val(JSON.stringify(content))
}


function initializeSortable(containerId) {
var el = document.getElementById(containerId);
Sortable.create(el, {
Expand All @@ -34,5 +71,7 @@ function resetIndex(containerId) {
});
}



require("../../common")
require("../../turbo")
6 changes: 6 additions & 0 deletions app/javascript/packs/turbo.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,10 @@ $(document).on("turbo:load", () => {

$(document).on("turbo:before-cache", () => {
$(".g-recaptcha").each(function () { this.innerHTML = "" });
});

$(document).on("turbo:frame-missing", (event) => {
const { detail: { response, visit } } = event;
event.preventDefault();
visit(response.url);
});
6 changes: 3 additions & 3 deletions app/views/comfy/admin/api_namespaces/_editor.haml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
- read_only = false if local_assigns[:read_only].nil?
- mode = local_assigns[:read_only].nil? ? 'tree' : 'view'
- non_primitive_properties = api_resource.persisted? ? api_resource.non_primitive_properties : api_resource.api_namespace.non_primitive_properties
#jsoneditor
#jsoneditor{data: { violet_jsoneditor: true, mode: "#{mode}", target: 'api_resource_properties' } }
= hidden_field_tag :api_namespace_properties, api_resource.api_namespace.properties.to_json
= hidden_field_tag "api_resource[properties]", api_resource.properties&.to_json
- unless read_only
- if mode == 'tree'
- non_primitive_properties.each_with_index do |property, index|
= fields_for "api_resource[non_primitive_properties_attributes][#{index}]", property do |ff|
.form-group{class: "#{'disable-trix-file-attachment' unless ff.object.allow_attachments}"}
Expand Down
5 changes: 1 addition & 4 deletions app/views/comfy/admin/api_namespaces/_form.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
.field
= f.label :version
= f.number_field :version
#jsoneditor
#jsoneditor{data: { violet_jsoneditor: true, target: 'api_namespace_properties' }}
= hidden_field_tag "api_namespace[properties]", @api_namespace.properties&.to_json

.non-primitve-properties.mb-4
Expand All @@ -38,9 +38,6 @@
.actions
= f.submit 'Save'


= render 'init_editor', {read_only: false}

:javascript
function manageEvent(index) {
var fieldType = $("#field_type_field_" + index).val();
Expand Down
6 changes: 2 additions & 4 deletions app/views/comfy/admin/api_namespaces/show.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,5 @@
= @api_namespace.version
%p
%b Properties:
#jsoneditor
= hidden_field_tag :api_namespace_properties, @api_namespace.properties&.to_json

= render 'init_editor', {read_only: true}
#jsoneditor{data: { violet_jsoneditor: true, mode: 'view', target: 'api_namespace_properties' }}
= hidden_field_tag :api_namespace_properties, @api_namespace.properties&.to_json
1 change: 0 additions & 1 deletion app/views/comfy/admin/api_resources/_form.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,4 @@
= render 'comfy/admin/api_namespaces/editor', {api_resource: @api_resource, form_properties: form_properties, is_edit: is_edit}
.actions
= f.submit 'Save', data: {disable_with: false}
= render 'comfy/admin/api_namespaces/init_editor', {read_only: false}
= render 'comfy/admin/api_namespaces/richtext_form_validations'
1 change: 0 additions & 1 deletion app/views/comfy/admin/api_resources/show.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
%b Resource Id:
= @api_resource.id
= render 'comfy/admin/api_namespaces/editor', {api_resource: @api_resource, form_properties: @api_resource.api_namespace&.api_form&.properties&.symbolize_keys, read_only: true}
= render 'comfy/admin/api_namespaces/init_editor', {read_only: true}

- user = @api_resource.tracked_user
- if user
Expand Down
2 changes: 1 addition & 1 deletion app/views/comfy/admin/cms/partials/_navigation_inner.haml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
%li{class: 'nav-item'}
%li{class: 'nav-item', data: { turbo: 'true'}}
= active_link_to "Users", admin_users_path, class: 'nav-link'
= active_link_to "Email", mailbox_path, class: 'nav-link'
= active_link_to "API", api_namespaces_path, class: 'nav-link'
Expand Down
2 changes: 1 addition & 1 deletion app/views/comfy/admin/external_api_clients/_form.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
%a{href: "https://github.com/restarone/violet_rails/blob/141e942461e016991b18697211d2f44e4569cb4e/test/fixtures/external_api_clients.yml#L35", target: '_blank'} External API Connection Model definition
= f.text_area :model_definition, data: {'cms-cm-mode' => 'javascript'}

#jsoneditor
#jsoneditor{data: { violet_jsoneditor: true, target: 'external_api_client_metadata' }}
= hidden_field_tag "external_api_client[metadata]", @external_api_client.metadata&.to_json

.actions
Expand Down
4 changes: 1 addition & 3 deletions app/views/comfy/admin/external_api_clients/show.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,5 @@
= link_to "Clear Errors", clear_errors_api_namespace_external_api_client_path(api_namespace_id: @api_namespace.id, id: @external_api_client.id), data: {confirm:"Are you sure? Please note down the error message and error state before clearing"}
%p
%b Metadata:
#jsoneditor
#jsoneditor{data: { violet_jsoneditor: true, mode: 'view', target: 'api_namespace_properties' }}
= hidden_field_tag :api_namespace_properties, @external_api_client.metadata&.to_json

= render 'comfy/admin/api_namespaces/init_editor', {read_only: true}
2 changes: 1 addition & 1 deletion app/views/layouts/comfy/admin/cms/_body.html.haml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
%body#comfy{class: "c-#{params[:controller].parameterize} a-#{params[:action].parameterize}", 'data-turbo': 'false'}
.container-fluid
.row
#cms-left.col-lg-2.bg-dark
#cms-left.col-lg-2.bg-dark{data: {turbo: 'true'}}
= render "layouts/comfy/admin/cms/left"
#cms-main{class: "col-lg-#{controller_name == 'dashboard' ? '10 ml-auto' : '8 m-auto'}"}
= render "layouts/comfy/admin/cms/flash"
Expand Down
3 changes: 2 additions & 1 deletion app/views/layouts/devise.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@


%body
= render partial: 'shared/flash'
= turbo_frame_tag 'turbo-flash' do
= render partial: 'shared/flash'
= cms_snippet_render('navbar').html_safe unless mobile?
.d-flex.flex-column.justify-content-center.align-items-center
.my-5
Expand Down
10 changes: 3 additions & 7 deletions app/views/shared/_flash_content.haml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
- show_custom_snippet = strip_tags(value.to_s) != value.to_s
- unless key == 'file_url'
- alert_class = key == 'notice' ? 'alert-success' : 'alert-danger'
%div{class: "toast alert #{!show_custom_snippet ? alert_class : ''} p-0", role: "alert", "aria-live": "assertive", "aria-atomic": "true"}
%div{class: "toast alert show #{!show_custom_snippet ? alert_class : ''} p-0", role: "alert"}
%div{class: "d-flex justify-content-between"}
%div{class: "toast-body"}
- if show_custom_snippet
Expand All @@ -15,10 +15,6 @@
- else
%strong
= value
%button{class: "btn-close btn-close-danger toast-close-btn mr-2 bg-transparent border-0", type: "button", "data-dismiss": "toast", "aria-label": "Close"}
%button{class: "btn-close btn-close-danger toast-close-btn mr-2 bg-transparent border-0", type: "button", "data-dismiss": "toast", "aria-label": "Close", onclick: "$(this).closest('.toast').toast('hide')"}
%span{"aria-hidden" => "true"}
%i.fa.fa-times
%script
$('.flash-container .alert').toast({ autohide: false});
$(".flash-container .alert").toast('show');
$('.flash-container .alert .btn-close').on('click', function() { $(this).closest('.toast').toast('hide') });
%i.fa.fa-times
2 changes: 1 addition & 1 deletion app/views/users/confirmations/new.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@
= f.email_field :email, autofocus: true, autocomplete: "email", value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email), class: 'form-control'
.form-group
= f.submit "Resend confirmation instructions", class: 'btn btn-secondary btn-block'
= render "devise/shared/links"
= render "users/shared/links"
12 changes: 12 additions & 0 deletions app/views/users/otp/sessions/new.html.haml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.card.shadow-lg.p-5.bg-white.rounded
.text-center
%h3.font-weight-bold
2 Factor Authentication
.form-group.mt-3
= form_with(url: users_sign_in_otp_path, scope: :user, method: :post, data: { turbo: 'true', turbo_action: 'advance' }) do |f|
.form-group
= f.text_field :otp_attempt, autofocus: true, class: 'form-control', placeholder: 'OTP'
.form-group
= f.submit "Verify", class: 'btn btn-primary btn-block'

= button_to 'Resend OTP' ,resend_otp_path ,method: :get, remote: true, class: 'btn btn-link p-0',id: 'resend-otp-btn'
2 changes: 1 addition & 1 deletion app/views/users/passwords/new.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@
= f.email_field :email, autofocus: true, autocomplete: "email", class: 'form-control'
.form-group
= f.submit "Send me reset password instructions", class: 'btn btn-primary btn-block'
= render "devise/shared/links"
= render "users/shared/links"
2 changes: 1 addition & 1 deletion app/views/users/registrations/new.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,4 @@
= f.password_field :password_confirmation, autocomplete: "new-password", class: 'form-control'
.form-group
= f.submit "Sign up", class: 'btn btn-primary btn-block'
= render "devise/shared/links"
= render "users/shared/links"
4 changes: 2 additions & 2 deletions app/views/users/sessions/new.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
.text-center
%h3.font-weight-bold Log In
.form-group
= form_for(resource, as: resource_name, url: session_path(resource_name), data: { turbo: false}) do |f|
= form_for(resource, as: resource_name, url: session_path(resource_name), data: { turbo: true, turbo_action: 'advance'}) do |f|
.form-group
= f.label :email
%br/
Expand All @@ -18,4 +18,4 @@
= f.label :remember_me
.form-group
= f.submit "Log in", class: 'btn btn-primary btn-block'
= render "devise/shared/links"
= render "users/shared/links"
Loading