mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-10-31 02:57:57 +00:00 
			
		
		
		
	Chore: Making Account Signup Optional (#563)
Introduce new environment variable that lets you control account signups ENABLE_ACCOUNT_SIGNUP :( true | false | api_only ) Fixes: #406 Co-authored-by: Pranav Raj S <pranavrajs@gmail.com>
This commit is contained in:
		| @@ -2,6 +2,12 @@ SECRET_KEY_BASE= | |||||||
| # Force all access to the app over SSL, default is set to false | # Force all access to the app over SSL, default is set to false | ||||||
| FORCE_SSL= | FORCE_SSL= | ||||||
|  |  | ||||||
|  | # This lets you control new sign ups on your chatwoot installation | ||||||
|  | # true : default option, allows sign ups | ||||||
|  | # false : disables all the end points related to sign ups | ||||||
|  | # api_only: disables the UI for signup, but you can create sign ups via the account apis | ||||||
|  | ENABLE_ACCOUNT_SIGNUP=  | ||||||
|  |  | ||||||
| #redis config | #redis config | ||||||
| REDIS_URL=redis://redis:6379 | REDIS_URL=redis://redis:6379 | ||||||
| # If you are using docker-compose, set this variable's value to be any string, | # If you are using docker-compose, set this variable's value to be any string, | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ class Api::V1::AccountsController < Api::BaseController | |||||||
|   skip_before_action :verify_authenticity_token, only: [:create] |   skip_before_action :verify_authenticity_token, only: [:create] | ||||||
|   skip_before_action :authenticate_user!, :set_current_user, :check_subscription, :handle_with_exception, |   skip_before_action :authenticate_user!, :set_current_user, :check_subscription, :handle_with_exception, | ||||||
|                      only: [:create], raise: false |                      only: [:create], raise: false | ||||||
|  |   before_action :check_signup_enabled | ||||||
|  |  | ||||||
|   rescue_from CustomExceptions::Account::InvalidEmail, |   rescue_from CustomExceptions::Account::InvalidEmail, | ||||||
|               CustomExceptions::Account::UserExists, |               CustomExceptions::Account::UserExists, | ||||||
| @@ -30,4 +31,8 @@ class Api::V1::AccountsController < Api::BaseController | |||||||
|   def account_params |   def account_params | ||||||
|     params.permit(:account_name, :email) |     params.permit(:account_name, :email) | ||||||
|   end |   end | ||||||
|  |  | ||||||
|  |   def check_signup_enabled | ||||||
|  |     raise ActionController::RoutingError, 'Not Found' if ENV.fetch('ENABLE_ACCOUNT_SIGNUP', true) == 'false' | ||||||
|  |   end | ||||||
| end | end | ||||||
|   | |||||||
| @@ -36,6 +36,7 @@ export default { | |||||||
|           path: 'signup', |           path: 'signup', | ||||||
|           name: 'auth_signup', |           name: 'auth_signup', | ||||||
|           component: Signup, |           component: Signup, | ||||||
|  |           meta: { requireSignupEnabled: true }, | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|           path: 'reset/password', |           path: 'reset/password', | ||||||
|   | |||||||
| @@ -97,6 +97,14 @@ export const validateAuthenticateRoutePermission = (to, from, next) => { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| const validateRouteAccess = (to, from, next) => { | const validateRouteAccess = (to, from, next) => { | ||||||
|  |   if ( | ||||||
|  |     window.chatwootConfig.signupEnabled !== 'true' && | ||||||
|  |     to.meta && | ||||||
|  |     to.meta.requireSignupEnabled | ||||||
|  |   ) { | ||||||
|  |     next(frontendURL('dashboard')); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   if (authIgnoreRoutes.includes(to.name)) { |   if (authIgnoreRoutes.includes(to.name)) { | ||||||
|     return next(); |     return next(); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -1,24 +1,44 @@ | |||||||
| <template> | <template> | ||||||
|   <div class="medium-12 column login"> |   <div class="medium-12 column login"> | ||||||
|     <div class="text-center medium-12 login__hero align-self-top"> |     <div class="text-center medium-12 login__hero align-self-top"> | ||||||
|       <img src="~dashboard/assets/images/woot-logo.svg" alt="Woot-logo" class="hero__logo" /> |       <img | ||||||
|       <h2 class="hero__title">{{$t('LOGIN.TITLE')}}</h2> |         src="~dashboard/assets/images/woot-logo.svg" | ||||||
|  |         alt="Woot-logo" | ||||||
|  |         class="hero__logo" | ||||||
|  |       /> | ||||||
|  |       <h2 class="hero__title"> | ||||||
|  |         {{ $t('LOGIN.TITLE') }} | ||||||
|  |       </h2> | ||||||
|     </div> |     </div> | ||||||
|     <div class="row align-center"> |     <div class="row align-center"> | ||||||
|       <div class="small-12 medium-4 column"> |       <div class="small-12 medium-4 column"> | ||||||
|         <form class="login-box column align-self-top" v-on:submit.prevent="login()"> |         <form class="login-box column align-self-top" @submit.prevent="login()"> | ||||||
|           <div class="column log-in-form"> |           <div class="column log-in-form"> | ||||||
|             <!-- <h4 class="text-center">{{$t('LOGIN.TITLE')}}</h4> --> |             <!-- <h4 class="text-center">{{$t('LOGIN.TITLE')}}</h4> --> | ||||||
|             <label :class="{ 'error': $v.credentials.email.$error }"> |             <label :class="{ error: $v.credentials.email.$error }"> | ||||||
|               {{$t('LOGIN.EMAIL.LABEL')}} |               {{ $t('LOGIN.EMAIL.LABEL') }} | ||||||
|               <input type="text" v-bind:placeholder="$t('LOGIN.EMAIL.PLACEHOLDER')" v-model.trim="credentials.email" @input="$v.credentials.email.$touch"> |               <input | ||||||
|  |                 v-model.trim="credentials.email" | ||||||
|  |                 type="text" | ||||||
|  |                 :placeholder="$t('LOGIN.EMAIL.PLACEHOLDER')" | ||||||
|  |                 @input="$v.credentials.email.$touch" | ||||||
|  |               /> | ||||||
|             </label> |             </label> | ||||||
|             <label :class="{ 'error': $v.credentials.password.$error }"> |             <label :class="{ error: $v.credentials.password.$error }"> | ||||||
|               {{$t('LOGIN.PASSWORD.LABEL')}} |               {{ $t('LOGIN.PASSWORD.LABEL') }} | ||||||
|               <input type="password" v-bind:placeholder="$t('LOGIN.PASSWORD.PLACEHOLDER')" v-model.trim="credentials.password" @input="$v.credentials.password.$touch"> |               <input | ||||||
|  |                 v-model.trim="credentials.password" | ||||||
|  |                 type="password" | ||||||
|  |                 :placeholder="$t('LOGIN.PASSWORD.PLACEHOLDER')" | ||||||
|  |                 @input="$v.credentials.password.$touch" | ||||||
|  |               /> | ||||||
|             </label> |             </label> | ||||||
|             <woot-submit-button |             <woot-submit-button | ||||||
|               :disabled="$v.credentials.email.$invalid || $v.credentials.password.$invalid || loginApi.showLoading" |               :disabled=" | ||||||
|  |                 $v.credentials.email.$invalid || | ||||||
|  |                   $v.credentials.password.$invalid || | ||||||
|  |                   loginApi.showLoading | ||||||
|  |               " | ||||||
|               :button-text="$t('LOGIN.SUBMIT')" |               :button-text="$t('LOGIN.SUBMIT')" | ||||||
|               :loading="loginApi.showLoading" |               :loading="loginApi.showLoading" | ||||||
|               button-class="large expanded" |               button-class="large expanded" | ||||||
| @@ -30,10 +50,10 @@ | |||||||
|         <div class="column text-center sigin__footer"> |         <div class="column text-center sigin__footer"> | ||||||
|           <p> |           <p> | ||||||
|             <router-link to="auth/reset/password"> |             <router-link to="auth/reset/password"> | ||||||
|               {{$t('LOGIN.FORGOT_PASSWORD')}} |               {{ $t('LOGIN.FORGOT_PASSWORD') }} | ||||||
|             </router-link> |             </router-link> | ||||||
|           </p> |           </p> | ||||||
|           <p> |           <p v-if="showSignupLink()"> | ||||||
|             <router-link to="auth/signup"> |             <router-link to="auth/signup"> | ||||||
|               {{ $t('LOGIN.CREATE_NEW_ACCOUNT') }} |               {{ $t('LOGIN.CREATE_NEW_ACCOUNT') }} | ||||||
|             </router-link> |             </router-link> | ||||||
| @@ -89,6 +109,9 @@ export default { | |||||||
|       this.loginApi.message = message; |       this.loginApi.message = message; | ||||||
|       bus.$emit('newToastMessage', this.loginApi.message); |       bus.$emit('newToastMessage', this.loginApi.message); | ||||||
|     }, |     }, | ||||||
|  |     showSignupLink() { | ||||||
|  |       return window.chatwootConfig.signupEnabled === 'true'; | ||||||
|  |     }, | ||||||
|     login() { |     login() { | ||||||
|       this.loginApi.showLoading = true; |       this.loginApi.showLoading = true; | ||||||
|       const credentials = { |       const credentials = { | ||||||
| @@ -100,7 +123,7 @@ export default { | |||||||
|         .then(() => { |         .then(() => { | ||||||
|           this.showAlert(this.$t('LOGIN.API.SUCCESS_MESSAGE')); |           this.showAlert(this.$t('LOGIN.API.SUCCESS_MESSAGE')); | ||||||
|         }) |         }) | ||||||
|         .catch((response) => { |         .catch(response => { | ||||||
|           if (response && response.status === 401) { |           if (response && response.status === 401) { | ||||||
|             this.showAlert(this.$t('LOGIN.API.UNAUTH')); |             this.showAlert(this.$t('LOGIN.API.UNAUTH')); | ||||||
|             return; |             return; | ||||||
|   | |||||||
| @@ -31,8 +31,9 @@ | |||||||
|     <%= yield %> |     <%= yield %> | ||||||
|     <script> |     <script> | ||||||
|       window.chatwootConfig = { |       window.chatwootConfig = { | ||||||
|         fbAppId: '<%= ENV['FB_APP_ID'] %>', |         fbAppId: '<%= ENV.fetch('FB_APP_ID', nil) %>', | ||||||
|         billingEnabled: '<%= ENV['BILLING_ENABLED'] %>' |         billingEnabled: <%= ActiveModel::Type::Boolean.new.cast(ENV.fetch('BILLING_ENABLED', false)) %>, | ||||||
|  |         signupEnabled: '<%= ENV.fetch('ENABLE_ACCOUNT_SIGNUP', true) %>' | ||||||
|       } |       } | ||||||
|     </script> |     </script> | ||||||
|   </body> |   </body> | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ RSpec.describe 'Accounts API', type: :request do | |||||||
|  |  | ||||||
|       before do |       before do | ||||||
|         allow(AccountBuilder).to receive(:new).and_return(account_builder) |         allow(AccountBuilder).to receive(:new).and_return(account_builder) | ||||||
|  |         ENV['ENABLE_ACCOUNT_SIGNUP'] = nil | ||||||
|       end |       end | ||||||
|  |  | ||||||
|       it 'calls account builder' do |       it 'calls account builder' do | ||||||
| @@ -40,5 +41,37 @@ RSpec.describe 'Accounts API', type: :request do | |||||||
|         expect(response.body).to eq({ message: I18n.t('errors.signup.failed') }.to_json) |         expect(response.body).to eq({ message: I18n.t('errors.signup.failed') }.to_json) | ||||||
|       end |       end | ||||||
|     end |     end | ||||||
|  |  | ||||||
|  |     context 'when ENABLE_ACCOUNT_SIGNUP env variable is set to false' do | ||||||
|  |       let(:email) { Faker::Internet.email } | ||||||
|  |  | ||||||
|  |       it 'responds 404 on requests' do | ||||||
|  |         params = { account_name: 'test', email: email } | ||||||
|  |         ENV['ENABLE_ACCOUNT_SIGNUP'] = 'false' | ||||||
|  |  | ||||||
|  |         post api_v1_accounts_url, | ||||||
|  |              params: params, | ||||||
|  |              as: :json | ||||||
|  |  | ||||||
|  |         expect(response).to have_http_status(:not_found) | ||||||
|  |         ENV['ENABLE_ACCOUNT_SIGNUP'] = nil | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  |  | ||||||
|  |     context 'when ENABLE_ACCOUNT_SIGNUP env variable is set to api_only' do | ||||||
|  |       let(:email) { Faker::Internet.email } | ||||||
|  |  | ||||||
|  |       it 'does not respond 404 on requests' do | ||||||
|  |         params = { account_name: 'test', email: email } | ||||||
|  |         ENV['ENABLE_ACCOUNT_SIGNUP'] = 'api_only' | ||||||
|  |  | ||||||
|  |         post api_v1_accounts_url, | ||||||
|  |              params: params, | ||||||
|  |              as: :json | ||||||
|  |  | ||||||
|  |         expect(response).not_to have_http_status(:not_found) | ||||||
|  |         ENV['ENABLE_ACCOUNT_SIGNUP'] = nil | ||||||
|  |       end | ||||||
|  |     end | ||||||
|   end |   end | ||||||
| end | end | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Sojan Jose
					Sojan Jose