mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-05 02:26:26 +00:00
fix: select sub-org handler
This commit is contained in:
@@ -2693,7 +2693,7 @@ interface SelectSubOrganizationEvent {
|
|||||||
metadata: {
|
metadata: {
|
||||||
organizationId: string;
|
organizationId: string;
|
||||||
organizationName: string;
|
organizationName: string;
|
||||||
parentOrganizationId: string;
|
rootOrganizationId: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,10 +43,15 @@ export const registerLoginRouter = async (server: FastifyZodProvider) => {
|
|||||||
rateLimit: authRateLimit
|
rateLimit: authRateLimit
|
||||||
},
|
},
|
||||||
schema: {
|
schema: {
|
||||||
body: z.object({
|
body: z
|
||||||
organizationId: z.string().trim(),
|
.object({
|
||||||
userAgent: z.enum(["cli"]).optional()
|
organizationId: z.string().trim().optional(),
|
||||||
}),
|
subOrganizationId: z.string().trim().optional(),
|
||||||
|
userAgent: z.enum(["cli"]).optional()
|
||||||
|
})
|
||||||
|
.refine((body) => Boolean(body.organizationId || body.subOrganizationId), {
|
||||||
|
message: "organizationId or subOrganizationId is required"
|
||||||
|
}),
|
||||||
response: {
|
response: {
|
||||||
200: z.object({
|
200: z.object({
|
||||||
token: z.string(),
|
token: z.string(),
|
||||||
@@ -57,12 +62,25 @@ export const registerLoginRouter = async (server: FastifyZodProvider) => {
|
|||||||
},
|
},
|
||||||
handler: async (req, res) => {
|
handler: async (req, res) => {
|
||||||
const cfg = getConfig();
|
const cfg = getConfig();
|
||||||
const tokens = await server.services.login.selectOrganization({
|
let tokens;
|
||||||
userAgent: req.body.userAgent ?? req.headers["user-agent"],
|
|
||||||
authJwtToken: req.headers.authorization,
|
const targetOrgId = req.body.subOrganizationId ?? req.body.organizationId ?? "";
|
||||||
organizationId: req.body.organizationId,
|
|
||||||
ipAddress: req.realIp
|
if (req.body.subOrganizationId) {
|
||||||
});
|
tokens = await server.services.login.selectSubOrganization({
|
||||||
|
userAgent: req.body.userAgent ?? req.headers["user-agent"],
|
||||||
|
authJwtToken: req.headers.authorization,
|
||||||
|
subOrganizationId: req.body.subOrganizationId,
|
||||||
|
ipAddress: req.realIp
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
tokens = await server.services.login.selectOrganization({
|
||||||
|
userAgent: req.body.userAgent ?? req.headers["user-agent"],
|
||||||
|
authJwtToken: req.headers.authorization,
|
||||||
|
organizationId: req.body.organizationId as string,
|
||||||
|
ipAddress: req.realIp
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (tokens.isMfaEnabled) {
|
if (tokens.isMfaEnabled) {
|
||||||
return {
|
return {
|
||||||
@@ -75,7 +93,7 @@ export const registerLoginRouter = async (server: FastifyZodProvider) => {
|
|||||||
const githubOauthAccessToken = req.cookies[INFISICAL_PROVIDER_GITHUB_ACCESS_TOKEN];
|
const githubOauthAccessToken = req.cookies[INFISICAL_PROVIDER_GITHUB_ACCESS_TOKEN];
|
||||||
if (githubOauthAccessToken) {
|
if (githubOauthAccessToken) {
|
||||||
await server.services.githubOrgSync
|
await server.services.githubOrgSync
|
||||||
.syncUserGroups(req.body.organizationId, tokens.user.userId, githubOauthAccessToken)
|
.syncUserGroups(targetOrgId, tokens.user.userId, githubOauthAccessToken)
|
||||||
.finally(() => {
|
.finally(() => {
|
||||||
void res.setCookie(INFISICAL_PROVIDER_GITHUB_ACCESS_TOKEN, "", {
|
void res.setCookie(INFISICAL_PROVIDER_GITHUB_ACCESS_TOKEN, "", {
|
||||||
httpOnly: true,
|
httpOnly: true,
|
||||||
@@ -108,74 +126,6 @@ export const registerLoginRouter = async (server: FastifyZodProvider) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
server.route({
|
|
||||||
method: "POST",
|
|
||||||
url: "/select-sub-organization",
|
|
||||||
config: {
|
|
||||||
rateLimit: authRateLimit
|
|
||||||
},
|
|
||||||
schema: {
|
|
||||||
body: z.object({
|
|
||||||
subOrganizationId: z.string().trim(),
|
|
||||||
userAgent: z.enum(["cli"]).optional()
|
|
||||||
}),
|
|
||||||
response: {
|
|
||||||
200: z.object({
|
|
||||||
token: z.string(),
|
|
||||||
isMfaEnabled: z.boolean(),
|
|
||||||
mfaMethod: z.string().optional(),
|
|
||||||
subOrganization: z
|
|
||||||
.object({
|
|
||||||
id: z.string(),
|
|
||||||
name: z.string(),
|
|
||||||
slug: z.string()
|
|
||||||
})
|
|
||||||
.optional()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handler: async (req, res) => {
|
|
||||||
const cfg = getConfig();
|
|
||||||
const result = await server.services.login.selectSubOrganization({
|
|
||||||
userAgent: req.body.userAgent ?? req.headers["user-agent"],
|
|
||||||
authJwtToken: req.headers.authorization,
|
|
||||||
subOrganizationId: req.body.subOrganizationId,
|
|
||||||
ipAddress: req.realIp
|
|
||||||
});
|
|
||||||
|
|
||||||
if (result.isMfaEnabled) {
|
|
||||||
return {
|
|
||||||
token: result.mfa as string,
|
|
||||||
isMfaEnabled: true,
|
|
||||||
mfaMethod: result.mfaMethod
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void res.setCookie("jid", result.refresh, {
|
|
||||||
httpOnly: true,
|
|
||||||
path: "/",
|
|
||||||
sameSite: "strict",
|
|
||||||
secure: cfg.HTTPS_ENABLED
|
|
||||||
});
|
|
||||||
|
|
||||||
addAuthOriginDomainCookie(res);
|
|
||||||
|
|
||||||
void res.cookie("infisical-project-assume-privileges", "", {
|
|
||||||
httpOnly: true,
|
|
||||||
path: "/",
|
|
||||||
sameSite: "strict",
|
|
||||||
secure: cfg.HTTPS_ENABLED,
|
|
||||||
maxAge: 0
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
token: result.access,
|
|
||||||
isMfaEnabled: false,
|
|
||||||
subOrganization: result.subOrganization
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
server.route({
|
server.route({
|
||||||
method: "POST",
|
method: "POST",
|
||||||
url: "/login2",
|
url: "/login2",
|
||||||
|
|||||||
@@ -725,39 +725,58 @@ export const authLoginServiceFactory = ({
|
|||||||
authJwtToken = authJwtToken.replace("Bearer ", "");
|
authJwtToken = authJwtToken.replace("Bearer ", "");
|
||||||
|
|
||||||
const decodedToken = crypto.jwt().verify(authJwtToken, cfg.AUTH_SECRET) as AuthModeJwtTokenPayload;
|
const decodedToken = crypto.jwt().verify(authJwtToken, cfg.AUTH_SECRET) as AuthModeJwtTokenPayload;
|
||||||
|
|
||||||
if (!decodedToken.authMethod) throw new UnauthorizedError({ name: "Auth method not found on existing token" });
|
if (!decodedToken.authMethod) throw new UnauthorizedError({ name: "Auth method not found on existing token" });
|
||||||
if (!decodedToken.organizationId)
|
|
||||||
throw new BadRequestError({ message: "No organization selected in current token" });
|
|
||||||
|
|
||||||
const user = await userDAL.findUserEncKeyByUserId(decodedToken.userId);
|
const user = await userDAL.findUserEncKeyByUserId(decodedToken.userId);
|
||||||
if (!user) throw new BadRequestError({ message: "User not found", name: "Find user from token" });
|
if (!user) throw new BadRequestError({ message: "User not found", name: "Find user from token" });
|
||||||
|
|
||||||
|
// Check user membership in the sub-organization
|
||||||
|
const userSubOrgMembership = await membershipUserDAL.findOne({
|
||||||
|
actorUserId: user.id,
|
||||||
|
scopeOrgId: subOrganizationId,
|
||||||
|
scope: AccessScope.Organization,
|
||||||
|
status: OrgMembershipStatus.Accepted
|
||||||
|
});
|
||||||
|
|
||||||
// Fetch the sub-organization
|
// Fetch the sub-organization
|
||||||
const subOrg = await orgDAL.findById(subOrganizationId);
|
const subOrg = await orgDAL.findById(subOrganizationId);
|
||||||
if (!subOrg) {
|
|
||||||
throw new BadRequestError({ message: `Sub-organization with ID ${subOrganizationId} not found` });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify this is actually a sub-organization of the current root org
|
if (!userSubOrgMembership) {
|
||||||
if (subOrg.rootOrgId !== decodedToken.organizationId && subOrg.id !== decodedToken.organizationId) {
|
|
||||||
throw new ForbiddenRequestError({
|
throw new ForbiddenRequestError({
|
||||||
message: "Sub-organization does not belong to the current organization"
|
message: `User does not have access to the sub-organization named ${subOrg.name}`
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check user membership in the sub-organization
|
const subOrgmembershipRole = await membershipRoleDAL.findOne({ membershipId: userSubOrgMembership.id });
|
||||||
const orgMembership = await membershipUserDAL.findOne({
|
|
||||||
actorUserId: user.id,
|
|
||||||
scopeOrgId: subOrganizationId,
|
|
||||||
scope: AccessScope.Organization
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!orgMembership) {
|
// Check if authEnforced is true and the current auth method is not an enforced method
|
||||||
throw new ForbiddenRequestError({ message: "User is not a member of this sub-organization" });
|
if (
|
||||||
|
subOrg.authEnforced &&
|
||||||
|
!isAuthMethodSaml(decodedToken.authMethod) &&
|
||||||
|
decodedToken.authMethod !== AuthMethod.OIDC &&
|
||||||
|
!(subOrg.bypassOrgAuthEnabled && subOrgmembershipRole.role === OrgMembershipRole.Admin)
|
||||||
|
) {
|
||||||
|
throw new BadRequestError({
|
||||||
|
message: "Login with the auth method required by your organization."
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!orgMembership.isActive) {
|
if (subOrg.googleSsoAuthEnforced && decodedToken.authMethod !== AuthMethod.GOOGLE) {
|
||||||
throw new ForbiddenRequestError({ message: "User membership in sub-organization is inactive" });
|
const canBypass = subOrg.bypassOrgAuthEnabled && subOrgmembershipRole.role === OrgMembershipRole.Admin;
|
||||||
|
|
||||||
|
if (!canBypass) {
|
||||||
|
throw new ForbiddenRequestError({
|
||||||
|
message: "Google SSO is enforced for this organization. Please use Google SSO to login.",
|
||||||
|
error: "GoogleSsoEnforced"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decodedToken.authMethod === AuthMethod.GOOGLE) {
|
||||||
|
await orgDAL.updateById(subOrg.id, {
|
||||||
|
googleSsoAuthLastUsed: new Date()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check MFA requirements for the sub-organization
|
// Check MFA requirements for the sub-organization
|
||||||
@@ -797,8 +816,8 @@ export const authLoginServiceFactory = ({
|
|||||||
user,
|
user,
|
||||||
userAgent,
|
userAgent,
|
||||||
ip: ipAddress,
|
ip: ipAddress,
|
||||||
organizationId: decodedToken.organizationId, // Keep root org ID
|
...(subOrg.rootOrgId && { organizationId: subOrg.rootOrgId }),
|
||||||
subOrganizationId, // Add sub-org ID
|
subOrganizationId,
|
||||||
isMfaVerified: decodedToken.isMfaVerified,
|
isMfaVerified: decodedToken.isMfaVerified,
|
||||||
mfaMethod: decodedToken.mfaMethod
|
mfaMethod: decodedToken.mfaMethod
|
||||||
});
|
});
|
||||||
@@ -823,7 +842,7 @@ export const authLoginServiceFactory = ({
|
|||||||
metadata: {
|
metadata: {
|
||||||
organizationId: subOrganizationId,
|
organizationId: subOrganizationId,
|
||||||
organizationName: subOrg.name,
|
organizationName: subOrg.name,
|
||||||
parentOrganizationId: decodedToken.organizationId
|
rootOrganizationId: subOrg.rootOrgId ?? ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -831,12 +850,7 @@ export const authLoginServiceFactory = ({
|
|||||||
return {
|
return {
|
||||||
...tokens,
|
...tokens,
|
||||||
user,
|
user,
|
||||||
isMfaEnabled: false,
|
isMfaEnabled: false
|
||||||
subOrganization: {
|
|
||||||
id: subOrg.id,
|
|
||||||
name: subOrg.name,
|
|
||||||
slug: subOrg.slug
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -58,10 +58,17 @@ export const loginLDAPRedirect = async (loginLDAPDetails: LoginLDAPDTO) => {
|
|||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const selectOrganization = async (data: {
|
export type SelectOrganizationParams =
|
||||||
organizationId: string;
|
| {
|
||||||
userAgent?: UserAgentType;
|
organizationId: string;
|
||||||
}) => {
|
userAgent?: UserAgentType;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
subOrganizationId: string;
|
||||||
|
userAgent?: UserAgentType;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const selectOrganization = async (data: SelectOrganizationParams) => {
|
||||||
const { data: res } = await apiRequest.post<{
|
const { data: res } = await apiRequest.post<{
|
||||||
token: string;
|
token: string;
|
||||||
isMfaEnabled: boolean;
|
isMfaEnabled: boolean;
|
||||||
@@ -73,7 +80,7 @@ export const selectOrganization = async (data: {
|
|||||||
export const useSelectOrganization = () => {
|
export const useSelectOrganization = () => {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: async (details: { organizationId: string; userAgent?: UserAgentType }) => {
|
mutationFn: async (details: SelectOrganizationParams) => {
|
||||||
const data = await selectOrganization(details);
|
const data = await selectOrganization(details);
|
||||||
|
|
||||||
// If a custom user agent is set, then this session is meant for another consuming application, not the web application.
|
// If a custom user agent is set, then this session is meant for another consuming application, not the web application.
|
||||||
@@ -107,49 +114,6 @@ export const useSelectOrganization = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const selectSubOrganization = async (data: {
|
|
||||||
subOrganizationId: string;
|
|
||||||
userAgent?: UserAgentType;
|
|
||||||
}) => {
|
|
||||||
const { data: res } = await apiRequest.post<{
|
|
||||||
token: string;
|
|
||||||
isMfaEnabled: boolean;
|
|
||||||
mfaMethod?: MfaMethod;
|
|
||||||
subOrganization?: {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
slug: string;
|
|
||||||
};
|
|
||||||
}>("/api/v3/auth/select-sub-organization", data);
|
|
||||||
return res;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useSelectSubOrganization = () => {
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
return useMutation({
|
|
||||||
mutationFn: async (details: { subOrganizationId: string; userAgent?: UserAgentType }) => {
|
|
||||||
const data = await selectSubOrganization(details);
|
|
||||||
|
|
||||||
// If a custom user agent is set, then this session is meant for another consuming application, not the web application.
|
|
||||||
if (!details.userAgent && !data.isMfaEnabled) {
|
|
||||||
SecurityClient.setToken(data.token);
|
|
||||||
SecurityClient.setProviderAuthToken("");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.token && !data.isMfaEnabled) {
|
|
||||||
setAuthToken(data.token);
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
},
|
|
||||||
onSuccess: () => {
|
|
||||||
queryClient.invalidateQueries({
|
|
||||||
queryKey: [organizationKeys.getUserOrganizations, projectKeys.getAllUserProjects]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useLogin2 = () => {
|
export const useLogin2 = () => {
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: async (details: {
|
mutationFn: async (details: {
|
||||||
|
|||||||
@@ -62,7 +62,11 @@ import {
|
|||||||
useGetOrgTrialUrl,
|
useGetOrgTrialUrl,
|
||||||
useLogoutUser
|
useLogoutUser
|
||||||
} from "@app/hooks/api";
|
} from "@app/hooks/api";
|
||||||
import { authKeys, selectOrganization, selectSubOrganization } from "@app/hooks/api/auth/queries";
|
import {
|
||||||
|
authKeys,
|
||||||
|
selectOrganization,
|
||||||
|
type SelectOrganizationParams
|
||||||
|
} from "@app/hooks/api/auth/queries";
|
||||||
import { MfaMethod } from "@app/hooks/api/auth/types";
|
import { MfaMethod } from "@app/hooks/api/auth/types";
|
||||||
import { getAuthToken } from "@app/hooks/api/reactQuery";
|
import { getAuthToken } from "@app/hooks/api/reactQuery";
|
||||||
import { Organization, SubscriptionPlan } from "@app/hooks/api/types";
|
import { Organization, SubscriptionPlan } from "@app/hooks/api/types";
|
||||||
@@ -191,12 +195,26 @@ export const Navbar = () => {
|
|||||||
}
|
}
|
||||||
}, [subscription, isBillingPage, isModalIntrusive]);
|
}, [subscription, isBillingPage, isModalIntrusive]);
|
||||||
|
|
||||||
const handleOrgChange = async (orgId: string, onSuccess?: () => void | Promise<void>) => {
|
const handleOrgSelection = async ({
|
||||||
if (orgId === currentOrg.id) return;
|
organizationId,
|
||||||
|
subOrganizationId,
|
||||||
|
onSuccess
|
||||||
|
}: {
|
||||||
|
organizationId?: string;
|
||||||
|
subOrganizationId?: string;
|
||||||
|
onSuccess?: () => void | Promise<void>;
|
||||||
|
}) => {
|
||||||
|
if (!organizationId && !subOrganizationId) return;
|
||||||
|
|
||||||
const { token, isMfaEnabled, mfaMethod } = await selectOrganization({
|
const targetId = subOrganizationId ?? organizationId;
|
||||||
organizationId: orgId
|
|
||||||
});
|
if (targetId === currentOrg.id) return;
|
||||||
|
|
||||||
|
const selectionPayload: SelectOrganizationParams = subOrganizationId
|
||||||
|
? { subOrganizationId }
|
||||||
|
: { organizationId: organizationId as string };
|
||||||
|
|
||||||
|
const { token, isMfaEnabled, mfaMethod } = await selectOrganization(selectionPayload);
|
||||||
|
|
||||||
if (isMfaEnabled) {
|
if (isMfaEnabled) {
|
||||||
SecurityClient.setMfaToken(token);
|
SecurityClient.setMfaToken(token);
|
||||||
@@ -205,7 +223,7 @@ export const Navbar = () => {
|
|||||||
}
|
}
|
||||||
toggleShowMfa.on();
|
toggleShowMfa.on();
|
||||||
setMfaSuccessCallback(() => async () => {
|
setMfaSuccessCallback(() => async () => {
|
||||||
await handleOrgChange(orgId, onSuccess);
|
await handleOrgSelection({ organizationId, subOrganizationId, onSuccess });
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -216,7 +234,7 @@ export const Navbar = () => {
|
|||||||
queryClient.removeQueries({ queryKey: projectKeys.getAllUserProjects() });
|
queryClient.removeQueries({ queryKey: projectKeys.getAllUserProjects() });
|
||||||
|
|
||||||
await router.invalidate();
|
await router.invalidate();
|
||||||
await navigateUserToOrg(navigate, orgId);
|
await navigateUserToOrg(navigate, targetId);
|
||||||
queryClient.removeQueries({ queryKey: subOrgQuery.queryKey });
|
queryClient.removeQueries({ queryKey: subOrgQuery.queryKey });
|
||||||
|
|
||||||
if (onSuccess) {
|
if (onSuccess) {
|
||||||
@@ -234,43 +252,12 @@ export const Navbar = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (currentOrg.id !== rootOrg.id) {
|
if (currentOrg.id !== rootOrg.id) {
|
||||||
await handleOrgChange(rootOrg.id, navigateToBilling);
|
await handleOrgSelection({ organizationId: rootOrg.id, onSuccess: navigateToBilling });
|
||||||
} else {
|
} else {
|
||||||
await navigateToBilling();
|
await navigateToBilling();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubOrgChange = async (subOrgId: string) => {
|
|
||||||
if (subOrgId === currentOrg.id) return;
|
|
||||||
|
|
||||||
const { token, isMfaEnabled, mfaMethod } = await selectSubOrganization({
|
|
||||||
subOrganizationId: subOrgId
|
|
||||||
});
|
|
||||||
|
|
||||||
localStorage.setItem("orgData.id", subOrgId);
|
|
||||||
|
|
||||||
if (isMfaEnabled) {
|
|
||||||
SecurityClient.setMfaToken(token);
|
|
||||||
if (mfaMethod) {
|
|
||||||
setRequiredMfaMethod(mfaMethod);
|
|
||||||
}
|
|
||||||
toggleShowMfa.on();
|
|
||||||
setMfaSuccessCallback(() => () => handleSubOrgChange(subOrgId));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SecurityClient.setToken(token);
|
|
||||||
SecurityClient.setProviderAuthToken("");
|
|
||||||
|
|
||||||
queryClient.removeQueries({ queryKey: authKeys.getAuthToken });
|
|
||||||
queryClient.removeQueries({ queryKey: projectKeys.getAllUserProjects() });
|
|
||||||
await router.invalidate();
|
|
||||||
navigate({
|
|
||||||
to: "/organizations/$orgId/projects",
|
|
||||||
params: { orgId: subOrgId }
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const { mutateAsync } = useGetOrgTrialUrl();
|
const { mutateAsync } = useGetOrgTrialUrl();
|
||||||
|
|
||||||
const logout = useLogoutUser();
|
const logout = useLogoutUser();
|
||||||
@@ -340,7 +327,7 @@ export const Navbar = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleOrgChange(org?.id);
|
handleOrgSelection({ organizationId: org?.id });
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -465,7 +452,7 @@ export const Navbar = () => {
|
|||||||
</div>
|
</div>
|
||||||
{subOrganizations.map((subOrg) => (
|
{subOrganizations.map((subOrg) => (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
onClick={() => handleSubOrgChange(subOrg.id)}
|
onClick={() => handleOrgSelection({ subOrganizationId: subOrg.id })}
|
||||||
className="cursor-pointer font-normal"
|
className="cursor-pointer font-normal"
|
||||||
key={subOrg.id}
|
key={subOrg.id}
|
||||||
>
|
>
|
||||||
@@ -563,7 +550,7 @@ export const Navbar = () => {
|
|||||||
</div>
|
</div>
|
||||||
{subOrganizations.map((subOrg) => (
|
{subOrganizations.map((subOrg) => (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
onClick={() => handleSubOrgChange(subOrg.id)}
|
onClick={() => handleOrgSelection({ subOrganizationId: subOrg.id })}
|
||||||
className="cursor-pointer font-normal"
|
className="cursor-pointer font-normal"
|
||||||
key={subOrg.id}
|
key={subOrg.id}
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user