Skip to content

Commit

Permalink
[SDP-975]: Multi-tenancy - Add Organization (Tenant) Name field for L…
Browse files Browse the repository at this point in the history
…ogin & Forgot/Reset Password screens (#50)

* feat: add tenant name on login

* fix: requires organization name
  • Loading branch information
ceciliaromao authored Nov 27, 2023
1 parent fb37a7e commit 3927e29
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 16 deletions.
20 changes: 16 additions & 4 deletions src/apiQueries/useForgotPasswordLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@ import { fetchApi } from "helpers/fetchApi";
import { AppError } from "types";

type ForgotPasswordLinkProps = {
organizationName: string;
email: string;
recaptchaToken: string;
};

export const useForgotPasswordLink = () => {
const mutation = useMutation({
mutationFn: ({ email, recaptchaToken }: ForgotPasswordLinkProps) => {
mutationFn: ({
organizationName,
email,
recaptchaToken,
}: ForgotPasswordLinkProps) => {
return fetchApi(
`${API_URL}/forgot-password`,
{
Expand All @@ -20,7 +25,10 @@ export const useForgotPasswordLink = () => {
recaptcha_token: recaptchaToken,
}),
},
{ withoutAuth: true },
{
withoutAuth: true,
organizationName,
},
);
},
cacheTime: 0,
Expand All @@ -30,9 +38,13 @@ export const useForgotPasswordLink = () => {
...mutation,
error: mutation.error as AppError,
data: mutation.data as { message: string },
mutateAsync: async ({ email, recaptchaToken }: ForgotPasswordLinkProps) => {
mutateAsync: async ({
organizationName,
email,
recaptchaToken,
}: ForgotPasswordLinkProps) => {
try {
await mutation.mutateAsync({ email, recaptchaToken });
await mutation.mutateAsync({ organizationName, email, recaptchaToken });
} catch (e) {
// do nothing
}
Expand Down
16 changes: 13 additions & 3 deletions src/apiQueries/useResetPassword.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@ import { fetchApi } from "helpers/fetchApi";
import { AppError } from "types";

type ResetPasswordProps = {
organizationName: string;
password: string;
resetToken: string;
};

export const useResetPassword = () => {
const mutation = useMutation({
mutationFn: ({ password, resetToken }: ResetPasswordProps) => {
mutationFn: ({
organizationName,
password,
resetToken,
}: ResetPasswordProps) => {
return fetchApi(
`${API_URL}/reset-password`,
{
Expand All @@ -29,6 +34,7 @@ export const useResetPassword = () => {

return response;
},
organizationName,
},
);
},
Expand All @@ -39,9 +45,13 @@ export const useResetPassword = () => {
...mutation,
error: mutation.error as AppError,
data: mutation.data as boolean,
mutateAsync: async ({ password, resetToken }: ResetPasswordProps) => {
mutateAsync: async ({
organizationName,
password,
resetToken,
}: ResetPasswordProps) => {
try {
await mutation.mutateAsync({ password, resetToken });
await mutation.mutateAsync({ organizationName, password, resetToken });
} catch (e) {
// do nothing
}
Expand Down
3 changes: 2 additions & 1 deletion src/helpers/fetchApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type FetchApiOptions = {
withoutAuth?: boolean;
omitContentType?: boolean;
customCallback?: (request: Response) => void;
organizationName?: string;
};

export const fetchApi = async (
Expand Down Expand Up @@ -43,7 +44,7 @@ export const fetchApi = async (
config.headers = {
...config.headers,
Authorization: `Bearer ${token}`,
"SDP-Tenant-Name": getSdpTenantName(),
"SDP-Tenant-Name": options?.organizationName || getSdpTenantName(),
...(!options?.omitContentType
? {
"Content-Type":
Expand Down
14 changes: 12 additions & 2 deletions src/pages/ForgotPassword.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@ export const ForgotPassword = () => {
const navigate = useNavigate();
const recaptchaRef = useRef<Recaptcha>(null);

const [organizationName, setOrganizationName] = useState("");
const [email, setEmail] = useState("");
const [recaptchaToken, setRecaptchaToken] = useState("");

const handleForgotPassword = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
sendLink({ email, recaptchaToken });
sendLink({ organizationName, email, recaptchaToken });
};

const onRecaptchaSubmit = (token: string | null) => {
Expand Down Expand Up @@ -79,6 +80,15 @@ export const ForgotPassword = () => {
Forgot password
</Heading>

<Input
fieldSize="sm"
id="fp-organization-name"
name="fp-organization-name"
label="Organization name"
onChange={(e) => setOrganizationName(e.target.value)}
value={organizationName}
type="text"
/>
<Input
fieldSize="sm"
id="fp-email"
Expand All @@ -99,7 +109,7 @@ export const ForgotPassword = () => {
variant="primary"
size="sm"
type="submit"
disabled={!email || !recaptchaToken}
disabled={!organizationName || !email || !recaptchaToken}
isLoading={isLoading}
data-callback="onRecaptchaSubmit"
>
Expand Down
15 changes: 13 additions & 2 deletions src/pages/MFAuth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const MFAuth = () => {
const recaptchaRef = useRef<Recaptcha>(null);

const { userAccount } = useRedux("userAccount");
const [organizationName, setOrganizationName] = useState("");
const [recaptchaToken, setRecaptchaToken] = useState("");
const [mfaCode, setMfaCode] = useState("");
const [rememberMe, setRememberMe] = useState(false);
Expand Down Expand Up @@ -74,7 +75,7 @@ export const MFAuth = () => {

const headers = {
"Device-ID": deviceId,
"SDP-Tenant-Name": getSdpTenantName(),
"SDP-Tenant-Name": organizationName || getSdpTenantName(),
};

dispatch(mfaAction({ mfaCode, rememberMe, recaptchaToken, headers }));
Expand Down Expand Up @@ -127,6 +128,16 @@ export const MFAuth = () => {

{!USE_SSO && (
<>
<Input
fieldSize="sm"
id="2fa-organization-name"
name="2fa-organization-name"
label="Organization name"
onChange={(e) => setOrganizationName(e.target.value)}
value={organizationName}
type="text"
/>

<Input
fieldSize="sm"
id="2fa-verification-code"
Expand Down Expand Up @@ -156,7 +167,7 @@ export const MFAuth = () => {
variant="primary"
size="sm"
type="submit"
disabled={!mfaCode || !recaptchaToken}
disabled={!organizationName || !mfaCode || !recaptchaToken}
isLoading={userAccount.status === "PENDING"}
data-callback="onRecaptchaSubmit"
>
Expand Down
20 changes: 18 additions & 2 deletions src/pages/ResetPassword.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const ResetPassword = () => {

const navigate = useNavigate();

const [organizationName, setOrganizationName] = useState("");
const [password, setPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [confirmationToken, setConfirmationToken] = useState("");
Expand All @@ -28,7 +29,7 @@ export const ResetPassword = () => {

const handleResetPassword = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
mutateAsync({ password, resetToken: confirmationToken });
mutateAsync({ organizationName, password, resetToken: confirmationToken });
};

useEffect(() => {
Expand Down Expand Up @@ -56,7 +57,12 @@ export const ResetPassword = () => {
const allInputsValid = () => {
if (errorPassword || errorPasswordMatch || errorConfirmationToken) {
return false;
} else if (password && confirmPassword && confirmationToken) {
} else if (
organizationName &&
password &&
confirmPassword &&
confirmationToken
) {
return true;
}

Expand Down Expand Up @@ -104,6 +110,16 @@ export const ResetPassword = () => {
</div>
</div>

<Input
fieldSize="sm"
id="rp-organization-name"
name="rp-organization-name"
label="Organization name"
onChange={(e) => setOrganizationName(e.target.value)}
value={organizationName}
type="text"
/>

<Input
fieldSize="sm"
id="rp-token"
Expand Down
15 changes: 13 additions & 2 deletions src/pages/SignIn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export const SignIn = () => {
const recaptchaRef = useRef<Recaptcha>(null);

const { userAccount } = useRedux("userAccount");
const [organizationName, setOrganizationName] = useState("");
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [recaptchaToken, setRecaptchaToken] = useState("");
Expand Down Expand Up @@ -89,7 +90,7 @@ export const SignIn = () => {

const headers = {
"Device-ID": deviceId,
"SDP-Tenant-Name": getSdpTenantName(),
"SDP-Tenant-Name": organizationName || getSdpTenantName(),
};

dispatch(signInAction({ email, password, recaptchaToken, headers }));
Expand Down Expand Up @@ -130,6 +131,14 @@ export const SignIn = () => {
</Heading>
{!USE_SSO && (
<>
<Input
fieldSize="sm"
id="si-organization-name"
name="si-organization-name"
label="Organization name"
onChange={(e) => setOrganizationName(e.target.value)}
type="text"
/>
<Input
fieldSize="sm"
id="si-email"
Expand Down Expand Up @@ -168,7 +177,9 @@ export const SignIn = () => {
variant="primary"
size="sm"
type="submit"
disabled={!email || !password || !recaptchaToken}
disabled={
!organizationName || !email || !password || !recaptchaToken
}
isLoading={userAccount.status === "PENDING"}
data-callback="onRecaptchaSubmit"
>
Expand Down

0 comments on commit 3927e29

Please sign in to comment.