mirror of
https://github.com/astuto/astuto.git
synced 2025-12-16 11:47:56 +01:00
Add the possibility to enable/disable default OAuths (#303)
This commit is contained in:
committed by
GitHub
parent
719f1ad4e9
commit
32d19cbe7c
75
app/javascript/actions/OAuth/updateDefaultOAuth.ts
Normal file
75
app/javascript/actions/OAuth/updateDefaultOAuth.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import { Action } from "redux";
|
||||
import { ThunkAction } from "redux-thunk";
|
||||
|
||||
import { IOAuthJSON } from "../../interfaces/IOAuth";
|
||||
import { State } from "../../reducers/rootReducer";
|
||||
import buildRequestHeaders from "../../helpers/buildRequestHeaders";
|
||||
import HttpStatus from "../../constants/http_status";
|
||||
|
||||
export const DEFAULT_OAUTH_UPDATE_START = 'DEFAULT_OAUTH_UPDATE_START';
|
||||
interface DefaultOAuthUpdateStartAction {
|
||||
type: typeof DEFAULT_OAUTH_UPDATE_START;
|
||||
}
|
||||
|
||||
export const DEFAULT_OAUTH_UPDATE_SUCCESS = 'DEFAULT_OAUTH_UPDATE_SUCCESS';
|
||||
interface DefaultOAuthUpdateSuccessAction {
|
||||
type: typeof DEFAULT_OAUTH_UPDATE_SUCCESS;
|
||||
id: number;
|
||||
isEnabled: boolean;
|
||||
}
|
||||
|
||||
export const DEFAULT_OAUTH_UPDATE_FAILURE = 'DEFAULT_OAUTH_UPDATE_FAILURE';
|
||||
interface DefaultOAuthUpdateFailureAction {
|
||||
type: typeof DEFAULT_OAUTH_UPDATE_FAILURE;
|
||||
error: string;
|
||||
}
|
||||
|
||||
export type DefaultOAuthUpdateActionTypes =
|
||||
DefaultOAuthUpdateStartAction |
|
||||
DefaultOAuthUpdateSuccessAction |
|
||||
DefaultOAuthUpdateFailureAction;
|
||||
|
||||
const defaultOAuthUpdateStart = (): DefaultOAuthUpdateStartAction => ({
|
||||
type: DEFAULT_OAUTH_UPDATE_START,
|
||||
});
|
||||
|
||||
const defaultOAuthUpdateSuccess = (
|
||||
id: number,
|
||||
isEnabled: boolean,
|
||||
): DefaultOAuthUpdateSuccessAction => ({
|
||||
type: DEFAULT_OAUTH_UPDATE_SUCCESS,
|
||||
id,
|
||||
isEnabled,
|
||||
});
|
||||
|
||||
const defaultOAuthUpdateFailure = (error: string): DefaultOAuthUpdateFailureAction => ({
|
||||
type: DEFAULT_OAUTH_UPDATE_FAILURE,
|
||||
error,
|
||||
});
|
||||
|
||||
interface UpdateDefaultOAuthParams {
|
||||
id: number;
|
||||
isEnabled?: boolean;
|
||||
authenticityToken: string;
|
||||
}
|
||||
|
||||
export const updateDefaultOAuth = ({
|
||||
id,
|
||||
isEnabled = null,
|
||||
authenticityToken,
|
||||
}: UpdateDefaultOAuthParams): ThunkAction<void, State, null, Action<string>> => async (dispatch) => {
|
||||
try {
|
||||
dispatch(defaultOAuthUpdateStart());
|
||||
|
||||
const res = await fetch(`/o_auths/${id}/tenant_default_o_auths`, {
|
||||
method: isEnabled ? 'POST' : 'DELETE',
|
||||
headers: buildRequestHeaders(authenticityToken),
|
||||
});
|
||||
await res.json();
|
||||
|
||||
if (res.status === HttpStatus.Created || res.status === HttpStatus.Accepted)
|
||||
dispatch(defaultOAuthUpdateSuccess(id, isEnabled));
|
||||
} catch (e) {
|
||||
console.log('An error occurred while enabling/disabling default OAuth');
|
||||
}
|
||||
};
|
||||
@@ -15,6 +15,7 @@ interface Props {
|
||||
submitError: string;
|
||||
|
||||
handleToggleEnabledOAuth(id: number, enabled: boolean): void;
|
||||
handleToggleEnabledDefaultOAuth(id: number, enabled: boolean): void;
|
||||
handleDeleteOAuth(id: number): void;
|
||||
|
||||
setPage: React.Dispatch<React.SetStateAction<AuthenticationPages>>;
|
||||
@@ -27,6 +28,7 @@ const AuthenticationIndexPage = ({
|
||||
submitError,
|
||||
|
||||
handleToggleEnabledOAuth,
|
||||
handleToggleEnabledDefaultOAuth,
|
||||
handleDeleteOAuth,
|
||||
|
||||
setPage,
|
||||
@@ -48,6 +50,7 @@ const AuthenticationIndexPage = ({
|
||||
<OAuthProvidersList
|
||||
oAuths={oAuths.items}
|
||||
handleToggleEnabledOAuth={handleToggleEnabledOAuth}
|
||||
handleToggleEnabledDefaultOAuth={handleToggleEnabledDefaultOAuth}
|
||||
handleDeleteOAuth={handleDeleteOAuth}
|
||||
setPage={setPage}
|
||||
setSelectedOAuth={setSelectedOAuth}
|
||||
|
||||
@@ -16,6 +16,7 @@ interface Props {
|
||||
onSubmitOAuth(oAuth: IOAuth, authenticityToken: string): Promise<any>;
|
||||
onUpdateOAuth(id: number, form: ISiteSettingsOAuthForm, authenticityToken: string): Promise<any>;
|
||||
onToggleEnabledOAuth(id: number, isEnabled: boolean, authenticityToken: string): void;
|
||||
onToggleEnabledDefaultOAuth(id: number, isEnabled: boolean, authenticityToken: string): void;
|
||||
onDeleteOAuth(id: number, authenticityToken: string): void;
|
||||
|
||||
isSubmitting: boolean;
|
||||
@@ -32,6 +33,7 @@ const AuthenticationSiteSettingsP = ({
|
||||
onSubmitOAuth,
|
||||
onUpdateOAuth,
|
||||
onToggleEnabledOAuth,
|
||||
onToggleEnabledDefaultOAuth,
|
||||
onDeleteOAuth,
|
||||
isSubmitting,
|
||||
submitError,
|
||||
@@ -58,6 +60,10 @@ const AuthenticationSiteSettingsP = ({
|
||||
onToggleEnabledOAuth(id, enabled, authenticityToken);
|
||||
};
|
||||
|
||||
const handleToggleEnabledDefaultOAuth = (id: number, enabled: boolean) => {
|
||||
onToggleEnabledDefaultOAuth(id, enabled, authenticityToken);
|
||||
};
|
||||
|
||||
const handleDeleteOAuth = (id: number) => {
|
||||
onDeleteOAuth(id, authenticityToken);
|
||||
};
|
||||
@@ -67,6 +73,7 @@ const AuthenticationSiteSettingsP = ({
|
||||
<AuthenticationIndexPage
|
||||
oAuths={oAuths}
|
||||
handleToggleEnabledOAuth={handleToggleEnabledOAuth}
|
||||
handleToggleEnabledDefaultOAuth={handleToggleEnabledDefaultOAuth}
|
||||
handleDeleteOAuth={handleDeleteOAuth}
|
||||
setPage={setPage}
|
||||
setSelectedOAuth={setSelectedOAuth}
|
||||
|
||||
@@ -12,6 +12,7 @@ import { MutedText } from '../../common/CustomTexts';
|
||||
interface Props {
|
||||
oAuth: IOAuth;
|
||||
handleToggleEnabledOAuth(id: number, enabled: boolean): void;
|
||||
handleToggleEnabledDefaultOAuth(id: number, enabled: boolean): void;
|
||||
handleDeleteOAuth(id: number): void;
|
||||
setPage: React.Dispatch<React.SetStateAction<AuthenticationPages>>;
|
||||
setSelectedOAuth: React.Dispatch<React.SetStateAction<number>>;
|
||||
@@ -20,6 +21,7 @@ interface Props {
|
||||
const OAuthProviderItem = ({
|
||||
oAuth,
|
||||
handleToggleEnabledOAuth,
|
||||
handleToggleEnabledDefaultOAuth,
|
||||
handleDeleteOAuth,
|
||||
setPage,
|
||||
setSelectedOAuth,
|
||||
@@ -41,48 +43,59 @@ const OAuthProviderItem = ({
|
||||
/>
|
||||
</div>
|
||||
:
|
||||
<div><MutedText>{I18n.t('site_settings.authentication.default_oauth')}</MutedText></div>
|
||||
<div className="oAuthIsEnabled">
|
||||
<Switch
|
||||
label={I18n.t(`common.${oAuth.isEnabled ? 'enabled' : 'disabled'}`)}
|
||||
onClick={() => handleToggleEnabledDefaultOAuth(oAuth.id, !oAuth.defaultOAuthIsEnabled)}
|
||||
checked={oAuth.defaultOAuthIsEnabled}
|
||||
htmlId={`oAuth${oAuth.name}EnabledSwitch`}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{
|
||||
oAuth.tenantId &&
|
||||
<div className="oAuthActions">
|
||||
<CopyToClipboardButton
|
||||
label={I18n.t('site_settings.authentication.copy_url')}
|
||||
textToCopy={oAuth.callbackUrl}
|
||||
/>
|
||||
|
||||
<ActionLink
|
||||
onClick={() =>
|
||||
window.open(`/o_auths/${oAuth.id}/start?reason=test`, '', 'width=640, height=640')
|
||||
}
|
||||
icon={<TestIcon />}
|
||||
customClass='testAction'
|
||||
>
|
||||
{I18n.t('common.buttons.test')}
|
||||
</ActionLink>
|
||||
|
||||
<ActionLink
|
||||
onClick={() => {
|
||||
setSelectedOAuth(oAuth.id);
|
||||
setPage('edit');
|
||||
}}
|
||||
icon={<EditIcon />}
|
||||
customClass='editAction'
|
||||
>
|
||||
{I18n.t('common.buttons.edit')}
|
||||
</ActionLink>
|
||||
|
||||
<ActionLink
|
||||
onClick={() => confirm(I18n.t('common.confirmation')) && handleDeleteOAuth(oAuth.id)}
|
||||
icon={<DeleteIcon />}
|
||||
customClass='deleteAction'
|
||||
>
|
||||
{I18n.t('common.buttons.delete')}
|
||||
</ActionLink>
|
||||
</div>
|
||||
oAuth.tenantId ?
|
||||
<div className="oAuthActions">
|
||||
<CopyToClipboardButton
|
||||
label={I18n.t('site_settings.authentication.copy_url')}
|
||||
textToCopy={oAuth.callbackUrl}
|
||||
/>
|
||||
|
||||
<ActionLink
|
||||
onClick={() =>
|
||||
window.open(`/o_auths/${oAuth.id}/start?reason=test`, '', 'width=640, height=640')
|
||||
}
|
||||
icon={<TestIcon />}
|
||||
customClass='testAction'
|
||||
>
|
||||
{I18n.t('common.buttons.test')}
|
||||
</ActionLink>
|
||||
|
||||
<ActionLink
|
||||
onClick={() => {
|
||||
setSelectedOAuth(oAuth.id);
|
||||
setPage('edit');
|
||||
}}
|
||||
icon={<EditIcon />}
|
||||
customClass='editAction'
|
||||
>
|
||||
{I18n.t('common.buttons.edit')}
|
||||
</ActionLink>
|
||||
|
||||
<ActionLink
|
||||
onClick={() => confirm(I18n.t('common.confirmation')) && handleDeleteOAuth(oAuth.id)}
|
||||
icon={<DeleteIcon />}
|
||||
customClass='deleteAction'
|
||||
>
|
||||
{I18n.t('common.buttons.delete')}
|
||||
</ActionLink>
|
||||
</div>
|
||||
:
|
||||
<div className="defaultOAuthDiv">
|
||||
<span className="defaultOAuthLabel"><MutedText>{I18n.t('site_settings.authentication.default_oauth')}</MutedText></span>
|
||||
</div>
|
||||
}
|
||||
</li>
|
||||
);
|
||||
|
||||
@@ -9,6 +9,7 @@ import OAuthProviderItem from './OAuthProviderItem';
|
||||
interface Props {
|
||||
oAuths: Array<IOAuth>;
|
||||
handleToggleEnabledOAuth(id: number, enabled: boolean): void;
|
||||
handleToggleEnabledDefaultOAuth(id: number, enabled: boolean): void;
|
||||
handleDeleteOAuth(id: number): void;
|
||||
setPage: React.Dispatch<React.SetStateAction<AuthenticationPages>>;
|
||||
setSelectedOAuth: React.Dispatch<React.SetStateAction<number>>;
|
||||
@@ -17,6 +18,7 @@ interface Props {
|
||||
const OAuthProvidersList = ({
|
||||
oAuths,
|
||||
handleToggleEnabledOAuth,
|
||||
handleToggleEnabledDefaultOAuth,
|
||||
handleDeleteOAuth,
|
||||
setPage,
|
||||
setSelectedOAuth,
|
||||
@@ -35,6 +37,7 @@ const OAuthProvidersList = ({
|
||||
<OAuthProviderItem
|
||||
oAuth={oAuth}
|
||||
handleToggleEnabledOAuth={handleToggleEnabledOAuth}
|
||||
handleToggleEnabledDefaultOAuth={handleToggleEnabledDefaultOAuth}
|
||||
handleDeleteOAuth={handleDeleteOAuth}
|
||||
setPage={setPage}
|
||||
setSelectedOAuth={setSelectedOAuth}
|
||||
|
||||
@@ -45,6 +45,8 @@ export interface ITenantSignUpTenantForm {
|
||||
subdomain: string;
|
||||
}
|
||||
|
||||
export type AuthMethod = 'none' | 'email' | 'oauth';
|
||||
|
||||
const TenantSignUpP = ({
|
||||
oAuths,
|
||||
oAuthLoginCompleted,
|
||||
@@ -58,9 +60,12 @@ const TenantSignUpP = ({
|
||||
baseUrl,
|
||||
authenticityToken
|
||||
}: Props) => {
|
||||
// authMethod is either 'none', 'email' or 'oauth'
|
||||
const [authMethod, setAuthMethod] = useState<AuthMethod>(oAuthLoginCompleted ? 'oauth' : 'none');
|
||||
|
||||
const [userData, setUserData] = useState({
|
||||
fullName: '',
|
||||
email: '',
|
||||
fullName: oAuthLoginCompleted ? oauthUserName : '',
|
||||
email: oAuthLoginCompleted ? oauthUserEmail : '',
|
||||
password: '',
|
||||
passwordConfirmation: '',
|
||||
});
|
||||
@@ -72,20 +77,18 @@ const TenantSignUpP = ({
|
||||
|
||||
const [currentStep, setCurrentStep] = useState(oAuthLoginCompleted ? 2 : 1);
|
||||
|
||||
const [emailAuth, setEmailAuth] = useState(false);
|
||||
|
||||
const handleSignUpSubmit = (siteName: string, subdomain: string) => {
|
||||
handleSubmit(
|
||||
oAuthLoginCompleted ? oauthUserName : userData.fullName,
|
||||
oAuthLoginCompleted ? oauthUserEmail : userData.email,
|
||||
userData.fullName,
|
||||
userData.email,
|
||||
userData.password,
|
||||
siteName,
|
||||
subdomain,
|
||||
oAuthLoginCompleted,
|
||||
authMethod == 'oauth',
|
||||
authenticityToken,
|
||||
).then(res => {
|
||||
if (res?.status !== HttpStatus.Created) return;
|
||||
if (oAuthLoginCompleted) {
|
||||
if (authMethod == 'oauth') {
|
||||
let redirectUrl = new URL(baseUrl);
|
||||
redirectUrl.hostname = `${subdomain}.${redirectUrl.hostname}`;
|
||||
window.location.href = `${redirectUrl.toString()}users/sign_in`;
|
||||
@@ -107,12 +110,9 @@ const TenantSignUpP = ({
|
||||
<UserSignUpForm
|
||||
currentStep={currentStep}
|
||||
setCurrentStep={setCurrentStep}
|
||||
emailAuth={emailAuth}
|
||||
setEmailAuth={setEmailAuth}
|
||||
authMethod={authMethod}
|
||||
setAuthMethod={setAuthMethod}
|
||||
oAuths={oAuths}
|
||||
oAuthLoginCompleted={oAuthLoginCompleted}
|
||||
oauthUserEmail={oauthUserEmail}
|
||||
oauthUserName={oauthUserName}
|
||||
userData={userData}
|
||||
setUserData={setUserData}
|
||||
/>
|
||||
|
||||
@@ -5,7 +5,7 @@ import I18n from 'i18n-js';
|
||||
import Box from '../common/Box';
|
||||
import Button from '../common/Button';
|
||||
import OAuthProviderLink from '../common/OAuthProviderLink';
|
||||
import { ITenantSignUpUserForm } from './TenantSignUpP';
|
||||
import { AuthMethod, ITenantSignUpUserForm } from './TenantSignUpP';
|
||||
import { DangerText } from '../common/CustomTexts';
|
||||
import { getLabel, getValidationMessage } from '../../helpers/formUtils';
|
||||
import { EMAIL_REGEX } from '../../constants/regex';
|
||||
@@ -16,12 +16,9 @@ import { BackIcon, EditIcon } from '../common/Icons';
|
||||
interface Props {
|
||||
currentStep: number;
|
||||
setCurrentStep(step: number): void;
|
||||
emailAuth: boolean;
|
||||
setEmailAuth(enabled: boolean): void;
|
||||
authMethod: AuthMethod;
|
||||
setAuthMethod(method: AuthMethod): void;
|
||||
oAuths: Array<IOAuth>;
|
||||
oAuthLoginCompleted: boolean;
|
||||
oauthUserEmail?: string;
|
||||
oauthUserName?: string;
|
||||
userData: ITenantSignUpUserForm;
|
||||
setUserData({}: ITenantSignUpUserForm): void;
|
||||
}
|
||||
@@ -29,12 +26,9 @@ interface Props {
|
||||
const UserSignUpForm = ({
|
||||
currentStep,
|
||||
setCurrentStep,
|
||||
emailAuth,
|
||||
setEmailAuth,
|
||||
authMethod,
|
||||
setAuthMethod,
|
||||
oAuths,
|
||||
oAuthLoginCompleted,
|
||||
oauthUserEmail,
|
||||
oauthUserName,
|
||||
userData,
|
||||
setUserData,
|
||||
}: Props) => {
|
||||
@@ -44,7 +38,15 @@ const UserSignUpForm = ({
|
||||
setError,
|
||||
getValues,
|
||||
formState: { errors }
|
||||
} = useForm<ITenantSignUpUserForm>();
|
||||
} = useForm<ITenantSignUpUserForm>({
|
||||
defaultValues: {
|
||||
fullName: userData.fullName,
|
||||
email: userData.email,
|
||||
password: userData.password,
|
||||
passwordConfirmation: userData.passwordConfirmation,
|
||||
}
|
||||
});
|
||||
|
||||
const onSubmit: SubmitHandler<ITenantSignUpUserForm> = data => {
|
||||
if (data.password !== data.passwordConfirmation) {
|
||||
setError('passwordConfirmation', I18n.t('common.validations.password_mismatch'));
|
||||
@@ -60,36 +62,40 @@ const UserSignUpForm = ({
|
||||
<h3>Create user account</h3>
|
||||
|
||||
{
|
||||
currentStep === 1 && !emailAuth &&
|
||||
currentStep === 1 && authMethod == 'none' &&
|
||||
<>
|
||||
<Button className="emailAuth" onClick={() => setEmailAuth(true)}>
|
||||
<Button className="emailAuth" onClick={() => setAuthMethod('email')}>
|
||||
Sign up with email
|
||||
</Button>
|
||||
|
||||
{
|
||||
oAuths.filter(oAuth => oAuth.isEnabled).map((oAuth, i) =>
|
||||
<OAuthProviderLink
|
||||
oAuthId={oAuth.id}
|
||||
oAuthName={oAuth.name}
|
||||
oAuthLogo={oAuth.logo}
|
||||
oAuthReason='tenantsignup'
|
||||
isSignUp
|
||||
key={i}
|
||||
/>
|
||||
)
|
||||
}
|
||||
{ oAuths.length > 0 && <hr /> }
|
||||
|
||||
<div className="oauthProviderList">
|
||||
{
|
||||
oAuths.filter(oAuth => oAuth.isEnabled).map((oAuth, i) =>
|
||||
<OAuthProviderLink
|
||||
oAuthId={oAuth.id}
|
||||
oAuthName={oAuth.name}
|
||||
oAuthLogo={oAuth.logo}
|
||||
oAuthReason='tenantsignup'
|
||||
isSignUp
|
||||
key={i}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
|
||||
{
|
||||
currentStep === 1 && emailAuth &&
|
||||
currentStep === 1 && (authMethod == 'email' || authMethod == 'oauth') &&
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<ActionLink
|
||||
onClick={() => setEmailAuth(false)}
|
||||
onClick={() => setAuthMethod('none')}
|
||||
icon={<BackIcon />}
|
||||
customClass="backButton"
|
||||
>
|
||||
{I18n.t('common.buttons.back')}
|
||||
Use another method
|
||||
</ActionLink>
|
||||
|
||||
<div className="formRow">
|
||||
@@ -106,6 +112,7 @@ const UserSignUpForm = ({
|
||||
<div className="formRow">
|
||||
<input
|
||||
{...register('email', { required: true, pattern: EMAIL_REGEX })}
|
||||
disabled={authMethod == 'oauth'}
|
||||
type="email"
|
||||
placeholder={getLabel('user', 'email')}
|
||||
id="userEmail"
|
||||
@@ -117,29 +124,32 @@ const UserSignUpForm = ({
|
||||
</DangerText>
|
||||
</div>
|
||||
|
||||
<div className="formRow">
|
||||
<div className="userPasswordDiv">
|
||||
<input
|
||||
{...register('password', { required: true, minLength: 6, maxLength: 128 })}
|
||||
type="password"
|
||||
placeholder={getLabel('user', 'password')}
|
||||
id="userPassword"
|
||||
className="formControl"
|
||||
/>
|
||||
<DangerText>{ errors.password && I18n.t('common.validations.password', { n: 6 }) }</DangerText>
|
||||
</div>
|
||||
{
|
||||
authMethod == 'email' &&
|
||||
<div className="formRow">
|
||||
<div className="userPasswordDiv">
|
||||
<input
|
||||
{...register('password', { required: true, minLength: 6, maxLength: 128 })}
|
||||
type="password"
|
||||
placeholder={getLabel('user', 'password')}
|
||||
id="userPassword"
|
||||
className="formControl"
|
||||
/>
|
||||
<DangerText>{ errors.password && I18n.t('common.validations.password', { n: 6 }) }</DangerText>
|
||||
</div>
|
||||
|
||||
<div className="userPasswordConfirmationDiv">
|
||||
<input
|
||||
{...register('passwordConfirmation')}
|
||||
type="password"
|
||||
placeholder={getLabel('user', 'password_confirmation')}
|
||||
id="userPasswordConfirmation"
|
||||
className="formControl"
|
||||
/>
|
||||
<DangerText>{ errors.passwordConfirmation && I18n.t('common.validations.password_mismatch') }</DangerText>
|
||||
<div className="userPasswordConfirmationDiv">
|
||||
<input
|
||||
{...register('passwordConfirmation')}
|
||||
type="password"
|
||||
placeholder={getLabel('user', 'password_confirmation')}
|
||||
id="userPasswordConfirmation"
|
||||
className="formControl"
|
||||
/>
|
||||
<DangerText>{ errors.passwordConfirmation && I18n.t('common.validations.password_mismatch') }</DangerText>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<Button
|
||||
onClick={() => null}
|
||||
@@ -151,9 +161,9 @@ const UserSignUpForm = ({
|
||||
}
|
||||
|
||||
{
|
||||
currentStep === 2 && !oAuthLoginCompleted &&
|
||||
currentStep === 2 &&
|
||||
<p className="userRecap">
|
||||
<b>{oAuthLoginCompleted ? oauthUserName : userData.fullName}</b> ({oAuthLoginCompleted ? oauthUserEmail : userData.email})
|
||||
<b>{userData.fullName}</b> ({userData.email})
|
||||
<ActionLink onClick={() => setCurrentStep(currentStep-1)} icon={<EditIcon />} customClass="editUser">Edit</ActionLink>
|
||||
</p>
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import I18n from 'i18n-js';
|
||||
import { useState } from 'react';
|
||||
import ActionLink from './ActionLink';
|
||||
import { CopyIcon, DoneIcon } from './Icons';
|
||||
import { SuccessText } from './CustomTexts';
|
||||
|
||||
interface Props {
|
||||
label: string;
|
||||
@@ -40,7 +41,7 @@ const CopyToClipboardButton = ({
|
||||
</ActionLink>
|
||||
:
|
||||
<span style={{display: 'flex', marginRight: 12}}>
|
||||
{copiedLabel}
|
||||
<SuccessText>{copiedLabel}</SuccessText>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@ import AuthenticationSiteSettingsP from "../components/SiteSettings/Authenticati
|
||||
import { ISiteSettingsOAuthForm } from "../components/SiteSettings/Authentication/OAuthForm";
|
||||
import { IOAuth } from "../interfaces/IOAuth";
|
||||
import { State } from "../reducers/rootReducer";
|
||||
import { updateDefaultOAuth } from "../actions/OAuth/updateDefaultOAuth";
|
||||
|
||||
const mapStateToProps = (state: State) => ({
|
||||
oAuths: state.oAuths,
|
||||
@@ -33,6 +34,10 @@ const mapDispatchToProps = (dispatch: any) => ({
|
||||
dispatch(updateOAuth({id, isEnabled, authenticityToken}));
|
||||
},
|
||||
|
||||
onToggleEnabledDefaultOAuth(id: number, isEnabled: boolean, authenticityToken: string) {
|
||||
dispatch(updateDefaultOAuth({id, isEnabled, authenticityToken}));
|
||||
},
|
||||
|
||||
onDeleteOAuth(id: number, authenticityToken: string) {
|
||||
dispatch(deleteOAuth(id, authenticityToken));
|
||||
},
|
||||
|
||||
@@ -14,6 +14,7 @@ export interface IOAuth {
|
||||
|
||||
callbackUrl?: string;
|
||||
tenantId?: number;
|
||||
defaultOAuthIsEnabled: boolean;
|
||||
}
|
||||
|
||||
export interface IOAuthJSON {
|
||||
@@ -32,6 +33,7 @@ export interface IOAuthJSON {
|
||||
|
||||
callback_url?: string;
|
||||
tenant_id?: string;
|
||||
default_o_auth_is_enabled: boolean;
|
||||
}
|
||||
|
||||
export const oAuthJSON2JS = (oAuthJSON: IOAuthJSON): IOAuth => ({
|
||||
@@ -50,6 +52,7 @@ export const oAuthJSON2JS = (oAuthJSON: IOAuthJSON): IOAuth => ({
|
||||
|
||||
callbackUrl: oAuthJSON.callback_url,
|
||||
tenantId: oAuthJSON.tenant_id ? parseInt(oAuthJSON.tenant_id) : null,
|
||||
defaultOAuthIsEnabled: oAuthJSON.default_o_auth_is_enabled,
|
||||
});
|
||||
|
||||
export const oAuthJS2JSON = (oAuth: IOAuth) => ({
|
||||
@@ -68,4 +71,5 @@ export const oAuthJS2JSON = (oAuth: IOAuth) => ({
|
||||
|
||||
callback_url: oAuth.callbackUrl,
|
||||
tenant_id: oAuth.tenantId,
|
||||
default_o_auth_is_enabled: oAuth.defaultOAuthIsEnabled,
|
||||
});
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
} from '../actions/OAuth/deleteOAuth';
|
||||
|
||||
import { IOAuth, oAuthJSON2JS } from '../interfaces/IOAuth';
|
||||
import { DEFAULT_OAUTH_UPDATE_FAILURE, DEFAULT_OAUTH_UPDATE_START, DEFAULT_OAUTH_UPDATE_SUCCESS, DefaultOAuthUpdateActionTypes } from '../actions/OAuth/updateDefaultOAuth';
|
||||
|
||||
export interface OAuthsState {
|
||||
items: Array<IOAuth>;
|
||||
@@ -40,10 +41,12 @@ const oAuthsReducer = (
|
||||
OAuthsRequestActionTypes |
|
||||
OAuthSubmitActionTypes |
|
||||
OAuthUpdateActionTypes |
|
||||
OAuthDeleteActionTypes,
|
||||
OAuthDeleteActionTypes |
|
||||
DefaultOAuthUpdateActionTypes,
|
||||
) => {
|
||||
switch (action.type) {
|
||||
case OAUTHS_REQUEST_START:
|
||||
case DEFAULT_OAUTH_UPDATE_START:
|
||||
return {
|
||||
...state,
|
||||
areLoading: true,
|
||||
@@ -58,6 +61,7 @@ const oAuthsReducer = (
|
||||
};
|
||||
|
||||
case OAUTHS_REQUEST_FAILURE:
|
||||
case DEFAULT_OAUTH_UPDATE_FAILURE:
|
||||
return {
|
||||
...state,
|
||||
areLoading: false,
|
||||
@@ -79,6 +83,19 @@ const oAuthsReducer = (
|
||||
})
|
||||
};
|
||||
|
||||
case DEFAULT_OAUTH_UPDATE_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
areLoading: false,
|
||||
items: state.items.map(oAuth => {
|
||||
if (oAuth.id !== action.id) return oAuth;
|
||||
return {
|
||||
...oAuth,
|
||||
defaultOAuthIsEnabled: action.isEnabled,
|
||||
};
|
||||
}),
|
||||
};
|
||||
|
||||
case OAUTH_DELETE_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
|
||||
Reference in New Issue
Block a user