Added new security question to sign up, Added notification for unconfirmed emails
• Added: - new security question to sign up - notification for unconfirmed emails - modal for describing issue with Gab emails
This commit is contained in:
parent
9c0fc47777
commit
3c07e9d63b
@ -74,8 +74,9 @@ class Api::BaseController < ApplicationController
|
|||||||
render json: { error: 'This method requires an authenticated user' }, status: 422
|
render json: { error: 'This method requires an authenticated user' }, status: 422
|
||||||
elsif current_user.disabled?
|
elsif current_user.disabled?
|
||||||
render json: { error: 'Your login is currently disabled' }, status: 403
|
render json: { error: 'Your login is currently disabled' }, status: 403
|
||||||
elsif !current_user.confirmed?
|
# : todo : when figure out email/catpcha, put this back
|
||||||
render json: { error: 'Your login is missing a confirmed e-mail address' }, status: 403
|
# elsif !current_user.confirmed?
|
||||||
|
# render json: { error: 'Your login is missing a confirmed e-mail address' }, status: 403
|
||||||
elsif !current_user.approved?
|
elsif !current_user.approved?
|
||||||
render json: { error: 'Your login is currently pending approval' }, status: 403
|
render json: { error: 'Your login is currently pending approval' }, status: 403
|
||||||
else
|
else
|
||||||
|
@ -18,6 +18,27 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController
|
|||||||
render json: @account, serializer: REST::CredentialAccountSerializer
|
render json: @account, serializer: REST::CredentialAccountSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def resend_email_confirmation
|
||||||
|
@account = current_account
|
||||||
|
|
||||||
|
if !@account.user.confirmed?
|
||||||
|
redisResult = Redis.current.get("account:#{@account.id}:last_email_confirmation_resend") || 0
|
||||||
|
|
||||||
|
@lastSentDate = redisResult
|
||||||
|
if redisResult != 0
|
||||||
|
@lastSentDate = Time.at(redisResult.to_i).utc
|
||||||
|
end
|
||||||
|
|
||||||
|
if @lastSentDate == 0 || (@lastSentDate != 0 && Time.now.utc - @lastSentDate >= 1.hour)
|
||||||
|
@user = Account.find(@account.id).user || raise(ActiveRecord::RecordNotFound)
|
||||||
|
Redis.current.set("account:#{@account.id}:last_email_confirmation_resend", Time.now.utc.to_i)
|
||||||
|
@user.resend_confirmation_instructions
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
render json: { success: true, message: 'ok' }
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def account_params
|
def account_params
|
||||||
@ -35,4 +56,5 @@ class Api::V1::Accounts::CredentialsController < Api::BaseController
|
|||||||
'setting_default_language' => source_params.fetch(:language, @account.user.setting_default_language),
|
'setting_default_language' => source_params.fetch(:language, @account.user.setting_default_language),
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -4,6 +4,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
|
|||||||
layout :determine_layout
|
layout :determine_layout
|
||||||
|
|
||||||
before_action :set_invite, only: [:new, :create]
|
before_action :set_invite, only: [:new, :create]
|
||||||
|
before_action :set_challenge, only: [:new]
|
||||||
before_action :check_enabled_registrations, only: [:new, :create]
|
before_action :check_enabled_registrations, only: [:new, :create]
|
||||||
before_action :configure_sign_up_params, only: [:create]
|
before_action :configure_sign_up_params, only: [:create]
|
||||||
before_action :set_sessions, only: [:edit, :update]
|
before_action :set_sessions, only: [:edit, :update]
|
||||||
@ -15,6 +16,16 @@ class Auth::RegistrationsController < Devise::RegistrationsController
|
|||||||
super(&:build_invite_request)
|
super(&:build_invite_request)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
if session[:challenge_answer].to_s == params[:user][:challenge].to_s.strip
|
||||||
|
# Reset after, may be errors to return and this ensures its still visible
|
||||||
|
set_challenge
|
||||||
|
super
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
not_found
|
not_found
|
||||||
end
|
end
|
||||||
@ -96,6 +107,12 @@ class Auth::RegistrationsController < Devise::RegistrationsController
|
|||||||
@invite = invite&.valid_for_use? ? invite : nil
|
@invite = invite&.valid_for_use? ? invite : nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_challenge
|
||||||
|
@challenge_add_1 = rand(0...9)
|
||||||
|
@challenge_add_2 = rand(0...9)
|
||||||
|
session[:challenge_answer] = @challenge_add_1 + @challenge_add_2
|
||||||
|
end
|
||||||
|
|
||||||
def determine_layout
|
def determine_layout
|
||||||
%w(edit update).include?(action_name) ? 'admin' : 'auth'
|
%w(edit update).include?(action_name) ? 'admin' : 'auth'
|
||||||
end
|
end
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
import isObject from 'lodash.isobject'
|
import isObject from 'lodash.isobject'
|
||||||
import api from '../api'
|
import api from '../api'
|
||||||
import { me } from '../initial_state'
|
import {
|
||||||
|
me,
|
||||||
|
emailConfirmed,
|
||||||
|
} from '../initial_state'
|
||||||
import { importFetchedAccount } from './importer'
|
import { importFetchedAccount } from './importer'
|
||||||
|
|
||||||
export const SAVE_USER_PROFILE_INFORMATION_FETCH_REQUEST = 'SAVE_USER_PROFILE_INFORMATION_FETCH_REQUEST'
|
export const SAVE_USER_PROFILE_INFORMATION_FETCH_REQUEST = 'SAVE_USER_PROFILE_INFORMATION_FETCH_REQUEST'
|
||||||
export const SAVE_USER_PROFILE_INFORMATION_FETCH_SUCCESS = 'SAVE_USER_PROFILE_INFORMATION_FETCH_SUCCESS'
|
export const SAVE_USER_PROFILE_INFORMATION_FETCH_SUCCESS = 'SAVE_USER_PROFILE_INFORMATION_FETCH_SUCCESS'
|
||||||
export const SAVE_USER_PROFILE_INFORMATION_FETCH_FAIL = 'SAVE_USER_PROFILE_INFORMATION_FETCH_FAIL'
|
export const SAVE_USER_PROFILE_INFORMATION_FETCH_FAIL = 'SAVE_USER_PROFILE_INFORMATION_FETCH_FAIL'
|
||||||
|
export const RESEND_USER_CONFIRMATION_EMAIL_SUCCESS = 'RESEND_USER_CONFIRMATION_EMAIL_SUCCESS'
|
||||||
|
|
||||||
export const saveUserProfileInformation = (data) => {
|
export const saveUserProfileInformation = (data) => {
|
||||||
return function (dispatch, getState) {
|
return function (dispatch, getState) {
|
||||||
@ -51,4 +55,13 @@ function saveUserProfileInformationFail(error) {
|
|||||||
type: SAVE_USER_PROFILE_INFORMATION_FETCH_FAIL,
|
type: SAVE_USER_PROFILE_INFORMATION_FETCH_FAIL,
|
||||||
error,
|
error,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const resendUserConfirmationEmail = () => (dispatch, getState) => {
|
||||||
|
if (!me || emailConfirmed) return
|
||||||
|
|
||||||
|
api(getState).post('/api/v1/accounts/resend_email_confirmation').then((response) => {
|
||||||
|
dispatch({ type: RESEND_USER_CONFIRMATION_EMAIL_SUCCESS })
|
||||||
|
})
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
import {
|
||||||
|
me,
|
||||||
|
meUsername,
|
||||||
|
} from '../../initial_state'
|
||||||
|
import Button from '../button'
|
||||||
|
import Text from '../text'
|
||||||
|
import ModalLayout from './modal_layout'
|
||||||
|
|
||||||
|
class EmailConfirmationReminderModal extends React.PureComponent {
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { onClose } = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ModalLayout
|
||||||
|
title='Having Email Confirmation Issues?'
|
||||||
|
width={480}
|
||||||
|
onClose={onClose}
|
||||||
|
>
|
||||||
|
<Text size='medium' weight='medium' className={_s.mb10}>
|
||||||
|
Many email providers block Gab’s emails.
|
||||||
|
</Text>
|
||||||
|
<Text size='medium' color='secondary'>
|
||||||
|
Please check your spam folder for the confirmation email. If you still do not see an email please reach out to us for help.
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<div className={[_s.d, _s.flexRow, _s.pt15, _s.pb10].join(' ')}>
|
||||||
|
<Button
|
||||||
|
isOutline
|
||||||
|
color='brand'
|
||||||
|
backgroundColor='none'
|
||||||
|
href={`mailto:support@gab.com?subject=Please%20confirm%20my%20email%20(${me})&body=My%20username%20is:%20${meUsername}%20and%20account%20id%20is:%20${me}`}
|
||||||
|
className={[_s.flexRow, _s.aiCenter, _s.jcCenter, _s.mr10].join(' ')}
|
||||||
|
>
|
||||||
|
<Text color='inherit' weight='medium' align='center'>
|
||||||
|
Email Gab Support
|
||||||
|
</Text>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</ModalLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
EmailConfirmationReminderModal.propTypes = {
|
||||||
|
onClose: PropTypes.func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EmailConfirmationReminderModal
|
@ -16,6 +16,7 @@ import {
|
|||||||
MODAL_DISPLAY_OPTIONS,
|
MODAL_DISPLAY_OPTIONS,
|
||||||
MODAL_EDIT_PROFILE,
|
MODAL_EDIT_PROFILE,
|
||||||
MODAL_EDIT_SHORTCUTS,
|
MODAL_EDIT_SHORTCUTS,
|
||||||
|
MODAL_EMAIL_CONFIRMATION_REMINDER,
|
||||||
MODAL_EMBED,
|
MODAL_EMBED,
|
||||||
MODAL_GROUP_CREATE,
|
MODAL_GROUP_CREATE,
|
||||||
MODAL_GROUP_DELETE,
|
MODAL_GROUP_DELETE,
|
||||||
@ -48,6 +49,7 @@ import {
|
|||||||
DisplayOptionsModal,
|
DisplayOptionsModal,
|
||||||
EditProfileModal,
|
EditProfileModal,
|
||||||
EditShortcutsModal,
|
EditShortcutsModal,
|
||||||
|
EmailConfirmationReminderModal,
|
||||||
EmbedModal,
|
EmbedModal,
|
||||||
GroupCreateModal,
|
GroupCreateModal,
|
||||||
GroupDeleteModal,
|
GroupDeleteModal,
|
||||||
@ -83,6 +85,7 @@ MODAL_COMPONENTS[MODAL_CONFIRM] = ConfirmationModal
|
|||||||
MODAL_COMPONENTS[MODAL_DISPLAY_OPTIONS] = DisplayOptionsModal
|
MODAL_COMPONENTS[MODAL_DISPLAY_OPTIONS] = DisplayOptionsModal
|
||||||
MODAL_COMPONENTS[MODAL_EDIT_SHORTCUTS] = EditShortcutsModal
|
MODAL_COMPONENTS[MODAL_EDIT_SHORTCUTS] = EditShortcutsModal
|
||||||
MODAL_COMPONENTS[MODAL_EDIT_PROFILE] = EditProfileModal
|
MODAL_COMPONENTS[MODAL_EDIT_PROFILE] = EditProfileModal
|
||||||
|
MODAL_COMPONENTS[MODAL_EMAIL_CONFIRMATION_REMINDER] = EmailConfirmationReminderModal
|
||||||
MODAL_COMPONENTS[MODAL_EMBED] = EmbedModal
|
MODAL_COMPONENTS[MODAL_EMBED] = EmbedModal
|
||||||
MODAL_COMPONENTS[MODAL_GROUP_CREATE] = GroupCreateModal
|
MODAL_COMPONENTS[MODAL_GROUP_CREATE] = GroupCreateModal
|
||||||
MODAL_COMPONENTS[MODAL_GROUP_DELETE] = GroupDeleteModal
|
MODAL_COMPONENTS[MODAL_GROUP_DELETE] = GroupDeleteModal
|
||||||
|
@ -2,8 +2,10 @@ import React from 'react'
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { connect } from 'react-redux'
|
import { connect } from 'react-redux'
|
||||||
import {
|
import {
|
||||||
|
CX,
|
||||||
BREAKPOINT_SMALL,
|
BREAKPOINT_SMALL,
|
||||||
} from '../../constants'
|
} from '../../constants'
|
||||||
|
import { emailConfirmed } from '../../initial_state'
|
||||||
import Button from '../button'
|
import Button from '../button'
|
||||||
import { openModal } from '../../actions/modal'
|
import { openModal } from '../../actions/modal'
|
||||||
import Responsive from '../../features/ui/util/responsive_component'
|
import Responsive from '../../features/ui/util/responsive_component'
|
||||||
@ -26,10 +28,18 @@ class SidebarLayout extends React.PureComponent {
|
|||||||
children,
|
children,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
|
const innerContainerClasses = CX({
|
||||||
|
d: 1,
|
||||||
|
posFixed: 1,
|
||||||
|
calcH53PX: emailConfirmed,
|
||||||
|
calcH106PX: !emailConfirmed,
|
||||||
|
bottom0: 1,
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header role='banner' className={[_s.d, _s.flexGrow1, _s.z3, _s.aiEnd].join(' ')}>
|
<header role='banner' className={[_s.d, _s.flexGrow1, _s.z3, _s.aiEnd].join(' ')}>
|
||||||
<div className={[_s.d, _s.w240PX].join(' ')}>
|
<div className={[_s.d, _s.w240PX].join(' ')}>
|
||||||
<div className={[_s.d, _s.posFixed, _s.calcH53PX, _s.bottom0].join(' ')}>
|
<div className={innerContainerClasses}>
|
||||||
<div className={[_s.d, _s.h100PC, _s.aiStart, _s.w240PX, _s.pr15, _s.py10, _s.noScrollbar, _s.overflowYScroll].join(' ')}>
|
<div className={[_s.d, _s.h100PC, _s.aiStart, _s.w240PX, _s.pr15, _s.py10, _s.noScrollbar, _s.overflowYScroll].join(' ')}>
|
||||||
<div className={[_s.d, _s.w100PC].join(' ')}>
|
<div className={[_s.d, _s.w100PC].join(' ')}>
|
||||||
{
|
{
|
||||||
|
@ -46,6 +46,7 @@ export const MODAL_CONFIRM = 'CONFIRM'
|
|||||||
export const MODAL_DISPLAY_OPTIONS = 'DISPLAY_OPTIONS'
|
export const MODAL_DISPLAY_OPTIONS = 'DISPLAY_OPTIONS'
|
||||||
export const MODAL_EDIT_PROFILE = 'EDIT_PROFILE'
|
export const MODAL_EDIT_PROFILE = 'EDIT_PROFILE'
|
||||||
export const MODAL_EDIT_SHORTCUTS = 'EDIT_SHORTCUTS'
|
export const MODAL_EDIT_SHORTCUTS = 'EDIT_SHORTCUTS'
|
||||||
|
export const MODAL_EMAIL_CONFIRMATION_REMINDER = 'EMAIL_CONFIRMATION_REMINDER'
|
||||||
export const MODAL_EMBED = 'EMBED'
|
export const MODAL_EMBED = 'EMBED'
|
||||||
export const MODAL_GROUP_CREATE = 'GROUP_CREATE'
|
export const MODAL_GROUP_CREATE = 'GROUP_CREATE'
|
||||||
export const MODAL_GROUP_DELETE = 'GROUP_DELETE'
|
export const MODAL_GROUP_DELETE = 'GROUP_DELETE'
|
||||||
|
@ -26,5 +26,7 @@ export const lastReadNotificationId = getMeta('last_read_notification_id');
|
|||||||
export const monthlyExpensesComplete = getMeta('monthly_expenses_complete');
|
export const monthlyExpensesComplete = getMeta('monthly_expenses_complete');
|
||||||
export const favouritesCount = getMeta('favourites_count');
|
export const favouritesCount = getMeta('favourites_count');
|
||||||
export const isFirstSession = getMeta('is_first_session');
|
export const isFirstSession = getMeta('is_first_session');
|
||||||
|
export const emailConfirmed = getMeta('email_confirmed');
|
||||||
|
export const meEmail = getMeta('email');
|
||||||
|
|
||||||
export default initialState;
|
export default initialState;
|
||||||
|
@ -2,12 +2,14 @@ import {
|
|||||||
SAVE_USER_PROFILE_INFORMATION_FETCH_REQUEST,
|
SAVE_USER_PROFILE_INFORMATION_FETCH_REQUEST,
|
||||||
SAVE_USER_PROFILE_INFORMATION_FETCH_SUCCESS,
|
SAVE_USER_PROFILE_INFORMATION_FETCH_SUCCESS,
|
||||||
SAVE_USER_PROFILE_INFORMATION_FETCH_FAIL,
|
SAVE_USER_PROFILE_INFORMATION_FETCH_FAIL,
|
||||||
|
RESEND_USER_CONFIRMATION_EMAIL_SUCCESS,
|
||||||
} from '../actions/user'
|
} from '../actions/user'
|
||||||
import { Map as ImmutableMap } from 'immutable'
|
import { Map as ImmutableMap } from 'immutable'
|
||||||
|
|
||||||
const initialState = ImmutableMap({
|
const initialState = ImmutableMap({
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
isError: false,
|
isError: false,
|
||||||
|
emailConfirmationResends: 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
export default function (state = initialState, action) {
|
export default function (state = initialState, action) {
|
||||||
@ -18,6 +20,8 @@ export default function (state = initialState, action) {
|
|||||||
return state
|
return state
|
||||||
case SAVE_USER_PROFILE_INFORMATION_FETCH_FAIL:
|
case SAVE_USER_PROFILE_INFORMATION_FETCH_FAIL:
|
||||||
return state.set('isError', true)
|
return state.set('isError', true)
|
||||||
|
case RESEND_USER_CONFIRMATION_EMAIL_SUCCESS:
|
||||||
|
return state.set('emailConfirmationResends', state.get('emailConfirmationResends') + 1)
|
||||||
default:
|
default:
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
@ -443,6 +443,7 @@ pre {
|
|||||||
.topNeg50PX { top: -50px; }
|
.topNeg50PX { top: -50px; }
|
||||||
.top0 { top: 0; }
|
.top0 { top: 0; }
|
||||||
.top120PX { top: 120px; }
|
.top120PX { top: 120px; }
|
||||||
|
.top53PX { top: 53px; }
|
||||||
.top60PC { top: 60%; }
|
.top60PC { top: 60%; }
|
||||||
.top50PC { top: 50%; }
|
.top50PC { top: 50%; }
|
||||||
|
|
||||||
@ -478,12 +479,15 @@ pre {
|
|||||||
.maxH340PX { max-height: 340px; }
|
.maxH340PX { max-height: 340px; }
|
||||||
.maxH200PX { max-height: 200px; }
|
.maxH200PX { max-height: 200px; }
|
||||||
.maxH56PX { max-height: 56px; }
|
.maxH56PX { max-height: 56px; }
|
||||||
|
.maxH56PX { max-height: 42px; }
|
||||||
|
.calcH106PX { height: calc(100vh - 106px); }
|
||||||
.calcH53PX { height: calc(100vh - 53px); }
|
.calcH53PX { height: calc(100vh - 53px); }
|
||||||
.calcH80VH106PX { height: calc(80vh - 106px); }
|
.calcH80VH106PX { height: calc(80vh - 106px); }
|
||||||
|
|
||||||
.minH100VH { min-height: 100vh; }
|
.minH100VH { min-height: 100vh; }
|
||||||
.minH50VH { min-height: 50vh; }
|
.minH50VH { min-height: 50vh; }
|
||||||
.minH200PX { min-height: 200px; }
|
.minH200PX { min-height: 200px; }
|
||||||
|
.minH106PX { min-height: 106px; }
|
||||||
.minH98PX { min-height: 98px; }
|
.minH98PX { min-height: 98px; }
|
||||||
.minH80PX { min-height: 80px; }
|
.minH80PX { min-height: 80px; }
|
||||||
.minH58PX { min-height: 58px; }
|
.minH58PX { min-height: 58px; }
|
||||||
|
@ -253,6 +253,10 @@ class User < ApplicationRecord
|
|||||||
@invite_code = code
|
@invite_code = code
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def challenge
|
||||||
|
#
|
||||||
|
end
|
||||||
|
|
||||||
def password_required?
|
def password_required?
|
||||||
return false if Devise.pam_authentication || Devise.ldap_authentication
|
return false if Devise.pam_authentication || Devise.ldap_authentication
|
||||||
super
|
super
|
||||||
|
@ -39,6 +39,8 @@ class InitialStateSerializer < ActiveModel::Serializer
|
|||||||
store[:monthly_expenses_complete] = Redis.current.get("monthly_funding_amount") || 0
|
store[:monthly_expenses_complete] = Redis.current.get("monthly_funding_amount") || 0
|
||||||
store[:favourites_count] = object.current_account.favourites.count.to_s
|
store[:favourites_count] = object.current_account.favourites.count.to_s
|
||||||
store[:is_first_session] = is_first_session object.current_account
|
store[:is_first_session] = is_first_session object.current_account
|
||||||
|
store[:email_confirmed] = object.current_account.user.confirmed?
|
||||||
|
store[:email] = object.current_account.user.confirmed? ? '[hidden]' : object.current_account.user.email
|
||||||
end
|
end
|
||||||
|
|
||||||
store
|
store
|
||||||
|
@ -34,6 +34,9 @@
|
|||||||
|
|
||||||
= f.input :invite_code, as: :hidden
|
= f.input :invite_code, as: :hidden
|
||||||
|
|
||||||
|
.fields-group
|
||||||
|
= f.input :challenge, wrapper: :with_label, label: "Are you human? What is #{@challenge_add_1} + #{@challenge_add_2} = ", required: true, input_html: { 'aria-label' => "Are you human? What is #{@challenge_add_1} + #{@challenge_add_2}", :autocomplete => 'off' }
|
||||||
|
|
||||||
.fields-group-agreement
|
.fields-group-agreement
|
||||||
= f.input :agreement, as: :boolean, wrapper: :with_label, label: t('auth.checkbox_agreement_html', about_tos_path: about_tos_path)
|
= f.input :agreement, as: :boolean, wrapper: :with_label, label: t('auth.checkbox_agreement_html', about_tos_path: about_tos_path)
|
||||||
|
|
||||||
|
@ -190,7 +190,7 @@ Devise.setup do |config|
|
|||||||
# able to access the website for two days without confirming their account,
|
# able to access the website for two days without confirming their account,
|
||||||
# access will be blocked just in the third day. Default is 0.days, meaning
|
# access will be blocked just in the third day. Default is 0.days, meaning
|
||||||
# the user cannot access the website without confirming their account.
|
# the user cannot access the website without confirming their account.
|
||||||
# config.allow_unconfirmed_access_for = 2.days
|
config.allow_unconfirmed_access_for = 10.years
|
||||||
|
|
||||||
# A period that the user is allowed to confirm their account before their
|
# A period that the user is allowed to confirm their account before their
|
||||||
# token becomes invalid. For example, if set to 3.days, the user can confirm
|
# token becomes invalid. For example, if set to 3.days, the user can confirm
|
||||||
@ -198,7 +198,7 @@ Devise.setup do |config|
|
|||||||
# their account can't be confirmed with the token any more.
|
# their account can't be confirmed with the token any more.
|
||||||
# Default is nil, meaning there is no restriction on how long a user can take
|
# Default is nil, meaning there is no restriction on how long a user can take
|
||||||
# before confirming their account.
|
# before confirming their account.
|
||||||
config.confirm_within = 2.days
|
config.confirm_within = 12.days
|
||||||
|
|
||||||
# If true, requires any email changes to be confirmed (exactly the same way as
|
# If true, requires any email changes to be confirmed (exactly the same way as
|
||||||
# initial account confirmation) to be applied. Requires additional unconfirmed_email
|
# initial account confirmation) to be applied. Requires additional unconfirmed_email
|
||||||
|
@ -405,6 +405,7 @@ Rails.application.routes.draw do
|
|||||||
namespace :accounts do
|
namespace :accounts do
|
||||||
get :verify_credentials, to: 'credentials#show'
|
get :verify_credentials, to: 'credentials#show'
|
||||||
patch :update_credentials, to: 'credentials#update'
|
patch :update_credentials, to: 'credentials#update'
|
||||||
|
post :resend_email_confirmation, to: 'credentials#resend_email_confirmation'
|
||||||
resource :search, only: :show, controller: :search
|
resource :search, only: :show, controller: :search
|
||||||
resources :relationships, only: :index
|
resources :relationships, only: :index
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user