2016-02-12 23:52:43 +08:00
|
|
|
class Users::RegistrationsController < Devise::RegistrationsController
|
2022-12-21 18:59:25 +08:00
|
|
|
include ::ApplicationHelper
|
|
|
|
|
2016-11-22 21:57:41 +08:00
|
|
|
prepend_before_action :check_captcha, only: [:create]
|
2018-02-26 18:05:05 +08:00
|
|
|
before_action :registration_enabled?,
|
|
|
|
only: %i(new create new_with_provider create_with_provider)
|
|
|
|
before_action :sign_up_with_provider_enabled?,
|
|
|
|
only: %i(new_with_provider create_with_provider)
|
2018-04-06 23:16:04 +08:00
|
|
|
layout :layout
|
2016-02-12 23:52:43 +08:00
|
|
|
|
|
|
|
def avatar
|
2016-07-21 19:11:15 +08:00
|
|
|
user = User.find_by_id(params[:id]) || current_user
|
2019-07-05 22:56:05 +08:00
|
|
|
style = params[:style] || :icon_small
|
|
|
|
redirect_to user.avatar_url(style)
|
2016-02-12 23:52:43 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def update_resource(resource, params)
|
2016-07-21 19:11:15 +08:00
|
|
|
@user_avatar_url = avatar_path(current_user, :thumb)
|
2016-02-12 23:52:43 +08:00
|
|
|
|
|
|
|
if params.include? :change_password
|
|
|
|
# Special handling if changing password
|
|
|
|
params.delete(:change_password)
|
2019-07-05 22:56:05 +08:00
|
|
|
if resource.valid_password?(params[:current_password]) &&
|
|
|
|
params.include?(:password) &&
|
|
|
|
params.include?(:password_confirmation) &&
|
|
|
|
params[:password].blank?
|
2016-02-12 23:52:43 +08:00
|
|
|
# If new password is blank and we're in process of changing
|
|
|
|
# password, add error to the resource and return false
|
|
|
|
resource.errors.add(:password, :blank)
|
|
|
|
false
|
|
|
|
else
|
|
|
|
resource.update_with_password(params)
|
|
|
|
end
|
|
|
|
elsif params.include? :change_avatar
|
|
|
|
params.delete(:change_avatar)
|
2019-07-30 19:31:22 +08:00
|
|
|
if !params.include?(:avatar) || (params[:avatar].length > Constants::AVATAR_MAX_SIZE_MB.megabytes * 2)
|
2016-02-12 23:52:43 +08:00
|
|
|
resource.errors.add(:avatar, :blank)
|
|
|
|
false
|
|
|
|
else
|
2019-07-05 22:56:05 +08:00
|
|
|
temp_file = Tempfile.new('avatar', Rails.root.join('tmp'))
|
|
|
|
begin
|
2019-10-02 15:52:37 +08:00
|
|
|
check_extension = params[:avatar].split(';')[0].split('/')[1]
|
2019-07-05 22:56:05 +08:00
|
|
|
temp_file.binmode
|
2019-10-02 15:52:37 +08:00
|
|
|
temp_file.write(Base64.decode64(params[:avatar].split(',')[1]))
|
2019-07-05 22:56:05 +08:00
|
|
|
temp_file.rewind
|
2019-10-02 15:52:37 +08:00
|
|
|
resource.avatar.attach(io: temp_file, filename: "avatar.#{check_extension}")
|
2019-07-05 22:56:05 +08:00
|
|
|
ensure
|
|
|
|
temp_file.close
|
|
|
|
temp_file.unlink
|
|
|
|
end
|
|
|
|
params.delete(:avatar)
|
2016-02-12 23:52:43 +08:00
|
|
|
resource.update_without_password(params)
|
|
|
|
end
|
2019-07-05 22:56:05 +08:00
|
|
|
elsif params.include?(:email) || params.include?(:password)
|
2016-02-12 23:52:43 +08:00
|
|
|
# For changing email or password, validate current_password
|
|
|
|
resource.update_with_password(params)
|
|
|
|
else
|
|
|
|
# For changing some attributes, no current_password validation
|
|
|
|
# is required
|
|
|
|
resource.update_without_password(params)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# Override default registrations_controller.rb implementation
|
|
|
|
# to support JSON
|
|
|
|
def update
|
|
|
|
change_password = account_update_params.include? :change_password
|
|
|
|
respond_to do |format|
|
|
|
|
self.resource = resource_class.to_adapter.get!(send(:"current_#{resource_name}").to_key)
|
|
|
|
prev_unconfirmed_email = resource.unconfirmed_email if resource.respond_to?(:unconfirmed_email)
|
|
|
|
|
|
|
|
resource_updated = update_resource(resource, account_update_params)
|
2016-09-21 21:54:12 +08:00
|
|
|
|
2016-02-12 23:52:43 +08:00
|
|
|
yield resource if block_given?
|
|
|
|
if resource_updated
|
|
|
|
# Set "needs confirmation" flash if neccesary
|
2019-10-02 19:22:07 +08:00
|
|
|
if is_flashing_format? || account_update_params['change_avatar']
|
2016-02-12 23:52:43 +08:00
|
|
|
flash_key = update_needs_confirmation?(resource, prev_unconfirmed_email) ?
|
|
|
|
:update_needs_confirmation : :updated
|
|
|
|
set_flash_message :notice, flash_key
|
|
|
|
end
|
|
|
|
|
|
|
|
# Set "password successfully updated" flash if neccesary
|
|
|
|
if change_password
|
|
|
|
set_flash_message :notice, :password_changed
|
|
|
|
end
|
|
|
|
|
|
|
|
format.html {
|
|
|
|
sign_in resource_name, resource, bypass: true
|
|
|
|
respond_with resource, location: edit_user_registration_path
|
|
|
|
}
|
|
|
|
format.json {
|
|
|
|
flash.keep
|
|
|
|
sign_in resource_name, resource, bypass: true
|
2016-08-05 23:00:29 +08:00
|
|
|
render json: {}
|
2016-02-12 23:52:43 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
clean_up_passwords resource
|
|
|
|
format.html {
|
|
|
|
respond_with resource, location: edit_user_registration_path
|
|
|
|
}
|
|
|
|
format.json {
|
2016-08-18 02:49:20 +08:00
|
|
|
render json: resource.errors, status: :bad_request
|
2016-02-12 23:52:43 +08:00
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-02-26 18:05:05 +08:00
|
|
|
def new; end
|
2017-01-30 22:04:02 +08:00
|
|
|
|
2016-02-12 23:52:43 +08:00
|
|
|
def create
|
2016-11-25 16:56:07 +08:00
|
|
|
build_resource(sign_up_params)
|
|
|
|
valid_resource = resource.valid?
|
2017-10-25 21:29:04 +08:00
|
|
|
# ugly checking if new team on sign up is enabled :(
|
|
|
|
if Rails.configuration.x.new_team_on_signup
|
|
|
|
# Create new team for the new user
|
|
|
|
@team = Team.new
|
|
|
|
@team.name = params[:team][:name]
|
|
|
|
valid_team = @team.valid?
|
|
|
|
|
|
|
|
if valid_team && valid_resource
|
|
|
|
# this must be called after @team variable is defined. Otherwise this
|
|
|
|
# variable won't be accessable in view.
|
|
|
|
super do |resource|
|
|
|
|
# Set the confirmed_at == created_at IF not using email confirmations
|
|
|
|
unless Rails.configuration.x.enable_email_confirmations
|
|
|
|
resource.update(confirmed_at: resource.created_at)
|
|
|
|
end
|
2016-02-12 23:52:43 +08:00
|
|
|
|
2017-10-25 21:29:04 +08:00
|
|
|
if resource.valid? && resource.persisted?
|
|
|
|
@team.created_by = resource # set created_by for oraganization
|
|
|
|
@team.save
|
2016-02-12 23:52:43 +08:00
|
|
|
|
2017-10-25 21:29:04 +08:00
|
|
|
# set current team to new user
|
|
|
|
resource.current_team_id = @team.id
|
|
|
|
resource.save
|
|
|
|
end
|
2016-02-12 23:52:43 +08:00
|
|
|
end
|
2017-10-25 21:29:04 +08:00
|
|
|
else
|
|
|
|
render :new
|
2016-02-12 23:52:43 +08:00
|
|
|
end
|
2017-10-26 16:42:18 +08:00
|
|
|
elsif valid_resource
|
|
|
|
super do |resource|
|
|
|
|
# Set the confirmed_at == created_at IF not using email confirmations
|
|
|
|
unless Rails.configuration.x.enable_email_confirmations
|
|
|
|
resource.update(confirmed_at: resource.created_at)
|
|
|
|
resource.save
|
2017-10-25 21:29:04 +08:00
|
|
|
end
|
|
|
|
end
|
2017-10-26 16:42:18 +08:00
|
|
|
else
|
|
|
|
render :new
|
2016-02-12 23:52:43 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-03-12 20:02:44 +08:00
|
|
|
def new_with_provider
|
|
|
|
return render_403 unless current_user
|
|
|
|
return render_403 unless Rails.configuration.x.new_team_on_signup
|
|
|
|
|
|
|
|
@team = Team.new
|
|
|
|
render layout: 'sign_in_halt'
|
|
|
|
end
|
2018-02-26 18:05:05 +08:00
|
|
|
|
|
|
|
def create_with_provider
|
2024-03-12 20:02:44 +08:00
|
|
|
return render_403 unless current_user
|
|
|
|
return render_403 unless Rails.configuration.x.new_team_on_signup
|
|
|
|
|
2018-02-26 18:05:05 +08:00
|
|
|
# Create new team for the new user
|
|
|
|
@team = Team.new(team_provider_params)
|
2024-03-12 20:02:44 +08:00
|
|
|
@team.created_by = current_user # set created_by for the team
|
2018-02-26 18:05:05 +08:00
|
|
|
|
2024-03-12 20:02:44 +08:00
|
|
|
if @team.save
|
2018-02-26 18:05:05 +08:00
|
|
|
# set current team to new user
|
2024-03-12 20:02:44 +08:00
|
|
|
current_user.update(current_team_id: @team.id)
|
|
|
|
redirect_to root_path
|
2018-02-26 18:05:05 +08:00
|
|
|
else
|
2024-03-12 20:02:44 +08:00
|
|
|
render :new_with_provider, layout: 'sign_in_halt'
|
2018-02-26 18:05:05 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-03-21 23:44:24 +08:00
|
|
|
def edit
|
|
|
|
@connected_devices = ConnectedDevice.for_user(current_user)
|
2023-03-31 16:01:58 +08:00
|
|
|
@user_statistics = current_user.statistics
|
2023-03-21 23:44:24 +08:00
|
|
|
super
|
|
|
|
end
|
|
|
|
|
2020-07-01 17:07:33 +08:00
|
|
|
def two_factor_enable
|
2022-12-21 18:59:25 +08:00
|
|
|
user = current_user || User.find_by(id: session[:otp_user_id])
|
|
|
|
if user.valid_otp?(params[:submit_code])
|
|
|
|
recovery_codes = user.enable_2fa!
|
|
|
|
sign_in(user) unless current_user
|
2020-07-09 23:01:00 +08:00
|
|
|
render json: { recovery_codes: recovery_codes }
|
2020-07-01 17:07:33 +08:00
|
|
|
else
|
|
|
|
render json: { error: t('users.registrations.edit.2fa_errors.wrong_submit_code') }, status: :unprocessable_entity
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def two_factor_disable
|
|
|
|
if current_user.valid_password?(params[:password])
|
2020-07-01 21:44:52 +08:00
|
|
|
current_user.disable_2fa!
|
2020-07-01 17:07:33 +08:00
|
|
|
redirect_to edit_user_registration_path
|
|
|
|
else
|
|
|
|
render json: { error: t('users.registrations.edit.2fa_errors.wrong_password') }, status: :forbidden
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def two_factor_qr_code
|
2022-12-21 18:59:25 +08:00
|
|
|
render json: { qr_code: create_2fa_qr_code(current_user) }
|
2020-07-01 17:07:33 +08:00
|
|
|
end
|
|
|
|
|
2022-07-12 22:45:07 +08:00
|
|
|
def regenerate_api_key
|
2024-09-20 21:33:16 +08:00
|
|
|
token = current_user.regenerate_api_key!
|
2022-07-12 22:45:07 +08:00
|
|
|
|
2024-06-03 19:47:00 +08:00
|
|
|
redirect_to(edit_user_registration_path(anchor: 'api-key'),
|
|
|
|
flash: {
|
2024-09-20 21:33:16 +08:00
|
|
|
success: t('users.registrations.edit.api_key.generated'),
|
|
|
|
token: token
|
2024-06-03 19:47:00 +08:00
|
|
|
})
|
2022-07-12 22:45:07 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def revoke_api_key
|
|
|
|
current_user.revoke_api_key!
|
|
|
|
|
2024-06-03 19:47:00 +08:00
|
|
|
redirect_to(edit_user_registration_path(anchor: 'api-key'),
|
|
|
|
flash: {
|
|
|
|
success: t('users.registrations.edit.api_key.revoked')
|
|
|
|
})
|
2022-07-12 22:45:07 +08:00
|
|
|
end
|
|
|
|
|
2016-02-12 23:52:43 +08:00
|
|
|
protected
|
|
|
|
|
|
|
|
# Called upon creating User (before .save). Permits parameters and extracts
|
|
|
|
# initials from :full_name (takes at most 4 chars). If :full_name is empty, it
|
|
|
|
# uses "PLCH" as a placeholder (user won't get error complaining about
|
|
|
|
# initials being empty.
|
|
|
|
def sign_up_params
|
|
|
|
tmp = params.require(:user).permit(:full_name, :initials, :email, :password, :password_confirmation)
|
|
|
|
initials = tmp[:full_name].titleize.scan(/[A-Z]+/).join()
|
2021-07-23 17:56:28 +08:00
|
|
|
initials = if initials.strip.blank?
|
2016-10-13 16:00:36 +08:00
|
|
|
'PLCH'
|
|
|
|
else
|
|
|
|
initials[0..Constants::USER_INITIALS_MAX_LENGTH]
|
|
|
|
end
|
2016-02-12 23:52:43 +08:00
|
|
|
tmp.merge(:initials => initials)
|
|
|
|
end
|
|
|
|
|
2018-02-26 18:05:05 +08:00
|
|
|
def team_provider_params
|
|
|
|
params.require(:team).permit(:name)
|
|
|
|
end
|
|
|
|
|
|
|
|
def user_provider_params
|
|
|
|
params.permit(:user)
|
|
|
|
end
|
|
|
|
|
2016-02-12 23:52:43 +08:00
|
|
|
def account_update_params
|
|
|
|
params.require(:user).permit(
|
|
|
|
:full_name,
|
|
|
|
:initials,
|
|
|
|
:avatar,
|
|
|
|
:email,
|
|
|
|
:password,
|
|
|
|
:password_confirmation,
|
|
|
|
:current_password,
|
|
|
|
:change_password,
|
2021-04-14 15:44:09 +08:00
|
|
|
:change_avatar,
|
|
|
|
:external_id
|
2016-02-12 23:52:43 +08:00
|
|
|
)
|
|
|
|
end
|
|
|
|
|
2016-08-05 23:00:29 +08:00
|
|
|
def avatar_params
|
|
|
|
params.permit(
|
2016-08-18 02:49:20 +08:00
|
|
|
:file
|
2016-08-05 23:00:29 +08:00
|
|
|
)
|
2016-08-18 02:49:20 +08:00
|
|
|
end
|
2016-08-05 23:00:29 +08:00
|
|
|
|
2016-02-12 23:52:43 +08:00
|
|
|
private
|
|
|
|
|
2018-04-06 23:16:04 +08:00
|
|
|
def layout
|
|
|
|
'fluid' if action_name == 'edit'
|
|
|
|
end
|
|
|
|
|
2016-11-22 21:57:41 +08:00
|
|
|
def check_captcha
|
|
|
|
if Rails.configuration.x.enable_recaptcha
|
|
|
|
unless verify_recaptcha
|
2016-11-29 22:53:58 +08:00
|
|
|
# Construct new resource before rendering :new
|
2016-11-22 21:57:41 +08:00
|
|
|
self.resource = resource_class.new sign_up_params
|
2016-11-29 22:53:58 +08:00
|
|
|
|
2017-01-24 23:57:14 +08:00
|
|
|
# Also validate team
|
2017-01-25 00:06:51 +08:00
|
|
|
@team = Team.new(name: params[:team][:name])
|
2017-01-24 23:57:14 +08:00
|
|
|
@team.valid?
|
2016-11-29 22:53:58 +08:00
|
|
|
|
2016-11-22 21:57:41 +08:00
|
|
|
respond_with_navigational(resource) { render :new }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-02-26 18:05:05 +08:00
|
|
|
def registration_enabled?
|
|
|
|
render_403 unless Rails.configuration.x.enable_user_registration
|
|
|
|
end
|
|
|
|
|
|
|
|
def sign_up_with_provider_enabled?
|
|
|
|
render_403 unless Rails.configuration.x.linkedin_signin_enabled
|
|
|
|
end
|
|
|
|
|
2016-02-12 23:52:43 +08:00
|
|
|
# Redirect to login page after signing up
|
|
|
|
def after_sign_up_path_for(resource)
|
|
|
|
new_user_session_path
|
|
|
|
end
|
|
|
|
|
|
|
|
# Redirect to login page after signing up
|
|
|
|
def after_inactive_sign_up_path_for(resource)
|
|
|
|
new_user_session_path
|
|
|
|
end
|
|
|
|
end
|