Skip to content

Commit

Permalink
Add popup for operation not permitted when no tenant id is found for …
Browse files Browse the repository at this point in the history
…some APIs
  • Loading branch information
nkshah2 committed Jul 17, 2023
1 parent 8a5530c commit ba608cf
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 7 deletions.
4 changes: 2 additions & 2 deletions build/static/css/main.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion build/static/css/main.css.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion build/static/js/bundle.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion build/static/js/bundle.js.map

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions src/ui/components/common/modals/TenantIdModals.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved.
*
* This software is licensed under the Apache License, Version 2.0 (the
* "License") as published by the Apache Software Foundation.
*
* You may not use this file except in compliance with the License. You may
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
@import "../../../styles/mixin.scss";
31 changes: 31 additions & 0 deletions src/ui/components/common/modals/TenantIdModals.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* Copyright (c) 2022, VRAI Labs and/or its affiliates. All rights reserved.
*
* This software is licensed under the Apache License, Version 2.0 (the
* "License") as published by the Apache Software Foundation.
*
* You may not use this file except in compliance with the License. You may
* obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/

import { LayoutModalProps } from "../../layout/layoutModal";

export type MissingTenantIdModalProps = Omit<LayoutModalProps, "modalContent"> & {
message: string;
};

export const getMissingTenantIdModalProps = (props: MissingTenantIdModalProps): LayoutModalProps => {
const closeModalRef: React.MutableRefObject<(() => void) | undefined> = { current: undefined };

return {
...props,
modalContent: <div>{props.message}</div>,
header: <h2 className="missing-tenant-modal-title">Operation not allowed</h2>,
closeCallbackRef: closeModalRef,
};
};
25 changes: 24 additions & 1 deletion src/ui/components/userDetail/userDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { getTenantsObjectsForIds } from "../../../utils/user";
import { PopupContentContext } from "../../contexts/PopupContentContext";
import { useTenantsListContext } from "../../contexts/TenantsListContext";
import { EmailVerificationStatus, UserRecipeType, UserWithRecipeId } from "../../pages/usersList/types";
import { getMissingTenantIdModalProps } from "../common/modals/TenantIdModals";
import { OnSelectUserFunction } from "../usersListTable/UsersListTable";
import { UserDetailContextProvider } from "./context/UserDetailContext";
import { UserTenantsList } from "./tenantList/UserTenantsList";
Expand Down Expand Up @@ -64,6 +65,7 @@ export const UserDetail: React.FC<UserDetailProps> = (props) => {
const { getUserMetaData } = useMetadataService();
const { getSessionsForUser } = useSessionsForUserService();
const { tenantsListFromStore } = useTenantsListContext();
const { showModal } = useContext(PopupContentContext);

const loadUserDetail = useCallback(async () => {
const userDetailsResponse = await getUser(user, recipeId);
Expand All @@ -77,7 +79,15 @@ export const UserDetail: React.FC<UserDetailProps> = (props) => {
const { showToast } = useContext(PopupContentContext);

const updateUser = useCallback(
async (userId: string, data: UserWithRecipeId): Promise<UpdateUserInformationResponse> => {
async (
userId: string,
data: UserWithRecipeId
): Promise<
| UpdateUserInformationResponse
| {
status: "NO_API_CALLED";
}
> => {
let tenantId: string | undefined;
const tenants: Tenant[] = getTenantsObjectsForIds(tenantsListFromStore ?? [], data.user.tenantIds);
let matchingTenants: Tenant[] = [];
Expand All @@ -98,6 +108,19 @@ export const UserDetail: React.FC<UserDetailProps> = (props) => {
tenantId = matchingTenants[0].tenantId;
}

if (tenantId === undefined) {
setShowLoadingOverlay(false);
showModal(
getMissingTenantIdModalProps({
message: `User does not belong to a tenant that has the ${data.recipeId} recipe enabled`,
})
);

return {
status: "NO_API_CALLED",
};
}

const userInfoResponse = await updateUserInformation({
userId,
recipeId: data.recipeId,
Expand Down
35 changes: 35 additions & 0 deletions src/ui/components/userDetail/userDetailForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { getTenantsObjectsForIds } from "../../../utils/user";
import { PopupContentContext } from "../../contexts/PopupContentContext";
import { useTenantsListContext } from "../../contexts/TenantsListContext";
import { UserProps } from "../../pages/usersList/types";
import { getMissingTenantIdModalProps } from "../common/modals/TenantIdModals";
import InputField from "../inputField/InputField";
import { LayoutModalProps } from "../layout/layoutModal";
import { PhoneNumberInput } from "../phoneNumber/PhoneNumberInput";
Expand Down Expand Up @@ -161,6 +162,7 @@ export const UserDetailChangePhoneForm: FC<UserDetailChangePhoneFormProps> = (
const { showToast } = useContext(PopupContentContext);
const { updateUserInformation } = useUserService();
const { tenantsListFromStore } = useTenantsListContext();
const { showModal } = useContext(PopupContentContext);

const isPhoneMatch = phone === repeatPhone;

Expand All @@ -172,6 +174,16 @@ export const UserDetailChangePhoneForm: FC<UserDetailChangePhoneFormProps> = (
const tenants: Tenant[] = getTenantsObjectsForIds(tenantsListFromStore ?? [], props.tenantIds);
const matchingTenants = tenants.filter((tenant) => tenant.passwordless.enabled === true);

if (matchingTenants.length === 0) {
void onCancel();
showModal(
getMissingTenantIdModalProps({
message: "User does not belong to a tenant that has the passwordless recipe enabled",
})
);
return;
}

const response = await updateUserInformation({
userId,
phone,
Expand Down Expand Up @@ -242,6 +254,7 @@ export const UserDetailChangeEmailForm: FC<UserDetailChangeEmailFormProps> = (
const { showToast } = useContext(PopupContentContext);
const { updateUserInformation } = useUserService();
const { tenantsListFromStore } = useTenantsListContext();
const { showModal } = useContext(PopupContentContext);

const isEmailMatch = email === repeatEmail;

Expand All @@ -266,6 +279,16 @@ export const UserDetailChangeEmailForm: FC<UserDetailChangeEmailFormProps> = (
tenantId = matchingTenants[0].tenantId;
}

if (tenantId === undefined) {
await onCancel();
showModal(
getMissingTenantIdModalProps({
message: `User does not belong to a tenant that has the ${recipeId} recipe enabled`,
})
);
return;
}

const response = await updateUserInformation({
userId,
email,
Expand Down Expand Up @@ -338,6 +361,7 @@ export const UserDetailChangePasswordForm: FC<UserDetailChangePasswordFormProps>
const { showToast } = useContext(PopupContentContext);
const { updatePassword } = usePasswordResetService();
const { tenantsListFromStore } = useTenantsListContext();
const { showModal } = useContext(PopupContentContext);

const isPasswordMatch = password === repeatPassword;

Expand All @@ -348,6 +372,17 @@ export const UserDetailChangePasswordForm: FC<UserDetailChangePasswordFormProps>

const tenants = getTenantsObjectsForIds(tenantsListFromStore ?? [], props.tenantIds);
const matchingTenantIds = tenants.filter((_tenant) => _tenant.emailPassword.enabled === true);

if (matchingTenantIds.length === 0) {
await onCancel();
showModal(
getMissingTenantIdModalProps({
message: "User does not belong to a tenant that has the emailpassword recipe enabled",
})
);
return;
}

const response = await updatePassword(
userId,
password,
Expand Down
14 changes: 13 additions & 1 deletion src/ui/components/userDetail/userDetailInfoGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,15 @@ type UserDetailInfoGridProps = Pick<
> & {
userDetail: UserWithRecipeId;
refetchData: () => Promise<void>;
onUpdateCallback: (userId: string, updatedValue: UserWithRecipeId) => Promise<UpdateUserInformationResponse>;
onUpdateCallback: (
userId: string,
updatedValue: UserWithRecipeId
) => Promise<
| UpdateUserInformationResponse
| {
status: "NO_API_CALLED";
}
>;
emailVerificationStatus: EmailVerificationStatus | undefined;
};

Expand Down Expand Up @@ -228,6 +236,10 @@ export const UserDetailInfoGrid: FC<UserDetailInfoGridProps> = (props) => {
showLoadingOverlay();
const response = await onUpdateCallback(userDetail.user.id, userState);

if (response.status === "NO_API_CALLED") {
return;
}

if (response.status === "OK") {
await refetchData();
setIsEditing(false);
Expand Down

0 comments on commit ba608cf

Please sign in to comment.