mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-08 12:28:54 +00:00
Merge pull request #3721 from Infisical/fix/user-stuck-on-invited
fix invite bug
This commit is contained in:
@@ -397,7 +397,7 @@ export const authLoginServiceFactory = ({
|
|||||||
|
|
||||||
// Check if the user actually has access to the specified organization.
|
// Check if the user actually has access to the specified organization.
|
||||||
const userOrgs = await orgDAL.findAllOrgsByUserId(user.id);
|
const userOrgs = await orgDAL.findAllOrgsByUserId(user.id);
|
||||||
const hasOrganizationMembership = userOrgs.some((org) => org.id === organizationId);
|
const hasOrganizationMembership = userOrgs.some((org) => org.id === organizationId && org.userStatus !== "invited");
|
||||||
const selectedOrg = await orgDAL.findById(organizationId);
|
const selectedOrg = await orgDAL.findById(organizationId);
|
||||||
|
|
||||||
if (!hasOrganizationMembership) {
|
if (!hasOrganizationMembership) {
|
||||||
|
|||||||
@@ -212,7 +212,7 @@ export const orgDALFactory = (db: TDbClient) => {
|
|||||||
// special query
|
// special query
|
||||||
const findAllOrgsByUserId = async (
|
const findAllOrgsByUserId = async (
|
||||||
userId: string
|
userId: string
|
||||||
): Promise<(TOrganizations & { orgAuthMethod: string; userRole: string })[]> => {
|
): Promise<(TOrganizations & { orgAuthMethod: string; userRole: string; userStatus: string })[]> => {
|
||||||
try {
|
try {
|
||||||
const org = (await db
|
const org = (await db
|
||||||
.replicaNode()(TableName.OrgMembership)
|
.replicaNode()(TableName.OrgMembership)
|
||||||
@@ -234,6 +234,7 @@ export const orgDALFactory = (db: TDbClient) => {
|
|||||||
})
|
})
|
||||||
.select(selectAllTableCols(TableName.Organization))
|
.select(selectAllTableCols(TableName.Organization))
|
||||||
.select(db.ref("role").withSchema(TableName.OrgMembership).as("userRole"))
|
.select(db.ref("role").withSchema(TableName.OrgMembership).as("userRole"))
|
||||||
|
.select(db.ref("status").withSchema(TableName.OrgMembership).as("userStatus"))
|
||||||
.select(
|
.select(
|
||||||
db.raw(`
|
db.raw(`
|
||||||
CASE
|
CASE
|
||||||
@@ -242,7 +243,7 @@ export const orgDALFactory = (db: TDbClient) => {
|
|||||||
ELSE ''
|
ELSE ''
|
||||||
END as "orgAuthMethod"
|
END as "orgAuthMethod"
|
||||||
`)
|
`)
|
||||||
)) as (TOrganizations & { orgAuthMethod: string; userRole: string })[];
|
)) as (TOrganizations & { orgAuthMethod: string; userRole: string; userStatus: string })[];
|
||||||
|
|
||||||
return org;
|
return org;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -183,7 +183,9 @@ export const orgServiceFactory = ({
|
|||||||
* */
|
* */
|
||||||
const findAllOrganizationOfUser = async (userId: string) => {
|
const findAllOrganizationOfUser = async (userId: string) => {
|
||||||
const orgs = await orgDAL.findAllOrgsByUserId(userId);
|
const orgs = await orgDAL.findAllOrgsByUserId(userId);
|
||||||
return orgs;
|
|
||||||
|
// Filter out orgs where the membership object is an invitation
|
||||||
|
return orgs.filter((org) => org.userStatus !== "invited");
|
||||||
};
|
};
|
||||||
/*
|
/*
|
||||||
* Get all workspace members
|
* Get all workspace members
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Helmet } from "react-helmet";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { faArrowRight } from "@fortawesome/free-solid-svg-icons";
|
import { faArrowRight } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { Link, useNavigate } from "@tanstack/react-router";
|
import { Link, useNavigate, useRouter } from "@tanstack/react-router";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { addSeconds, formatISO } from "date-fns";
|
import { addSeconds, formatISO } from "date-fns";
|
||||||
import { jwtDecode } from "jwt-decode";
|
import { jwtDecode } from "jwt-decode";
|
||||||
@@ -51,6 +51,7 @@ export const SelectOrganizationSection = () => {
|
|||||||
|
|
||||||
const [mfaSuccessCallback, setMfaSuccessCallback] = useState<() => void>(() => {});
|
const [mfaSuccessCallback, setMfaSuccessCallback] = useState<() => void>(() => {});
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
const queryParams = new URLSearchParams(window.location.search);
|
const queryParams = new URLSearchParams(window.location.search);
|
||||||
const orgId = queryParams.get("org_id");
|
const orgId = queryParams.get("org_id");
|
||||||
const callbackPort = queryParams.get("callback_port");
|
const callbackPort = queryParams.get("callback_port");
|
||||||
@@ -118,6 +119,8 @@ export const SelectOrganizationSection = () => {
|
|||||||
})
|
})
|
||||||
.finally(() => setIsInitialOrgCheckLoading(false));
|
.finally(() => setIsInitialOrgCheckLoading(false));
|
||||||
|
|
||||||
|
await router.invalidate();
|
||||||
|
|
||||||
if (isMfaEnabled) {
|
if (isMfaEnabled) {
|
||||||
SecurityClient.setMfaToken(token);
|
SecurityClient.setMfaToken(token);
|
||||||
if (mfaMethod) {
|
if (mfaMethod) {
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ import { SelectOrganizationPage } from "./SelectOrgPage";
|
|||||||
export const SelectOrganizationPageQueryParams = z.object({
|
export const SelectOrganizationPageQueryParams = z.object({
|
||||||
org_id: z.string().optional().catch(""),
|
org_id: z.string().optional().catch(""),
|
||||||
callback_port: z.coerce.number().optional().catch(undefined),
|
callback_port: z.coerce.number().optional().catch(undefined),
|
||||||
is_admin_login: z.boolean().optional().catch(false)
|
is_admin_login: z.boolean().optional().catch(false),
|
||||||
|
force: z.boolean().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
export const Route = createFileRoute("/_restrict-login-signup/login/select-organization")({
|
export const Route = createFileRoute("/_restrict-login-signup/login/select-organization")({
|
||||||
|
|||||||
@@ -28,8 +28,7 @@ import {
|
|||||||
import { MfaMethod } from "@app/hooks/api/auth/types";
|
import { MfaMethod } from "@app/hooks/api/auth/types";
|
||||||
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
|
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
|
||||||
import { ProjectType } from "@app/hooks/api/workspace/types";
|
import { ProjectType } from "@app/hooks/api/workspace/types";
|
||||||
|
import { isLoggedIn } from "@app/hooks/api/reactQuery";
|
||||||
import { navigateUserToOrg } from "../LoginPage/Login.utils";
|
|
||||||
|
|
||||||
// eslint-disable-next-line new-cap
|
// eslint-disable-next-line new-cap
|
||||||
const client = new jsrp.client();
|
const client = new jsrp.client();
|
||||||
@@ -71,6 +70,8 @@ export const SignupInvitePage = () => {
|
|||||||
|
|
||||||
const { mutateAsync: selectOrganization } = useSelectOrganization();
|
const { mutateAsync: selectOrganization } = useSelectOrganization();
|
||||||
|
|
||||||
|
const loggedIn = isLoggedIn();
|
||||||
|
|
||||||
// Verifies if the information that the users entered (name, workspace) is there, and if the password matched the criteria.
|
// Verifies if the information that the users entered (name, workspace) is there, and if the password matched the criteria.
|
||||||
const signupErrorCheck = async () => {
|
const signupErrorCheck = async () => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
@@ -242,29 +243,10 @@ export const SignupInvitePage = () => {
|
|||||||
if (response?.token) {
|
if (response?.token) {
|
||||||
SecurityClient.setSignupToken(response.token);
|
SecurityClient.setSignupToken(response.token);
|
||||||
setStep(2);
|
setStep(2);
|
||||||
|
} else if (loggedIn) {
|
||||||
|
navigate({ to: "/login/select-organization", search: { force: true } });
|
||||||
} else {
|
} else {
|
||||||
const redirectExistingUser = async () => {
|
navigate({ to: "/login" });
|
||||||
try {
|
|
||||||
const { token: mfaToken, isMfaEnabled } = await selectOrganization({
|
|
||||||
organizationId
|
|
||||||
});
|
|
||||||
|
|
||||||
if (isMfaEnabled) {
|
|
||||||
SecurityClient.setMfaToken(mfaToken);
|
|
||||||
toggleShowMfa.on();
|
|
||||||
setMfaSuccessCallback(() => redirectExistingUser);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// user will be redirected to dashboard
|
|
||||||
// if not logged in gets kicked out to login
|
|
||||||
await navigateUserToOrg(navigate, organizationId);
|
|
||||||
} catch (err) {
|
|
||||||
navigate({ to: "/login" });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
await redirectExistingUser();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ import { setAuthToken } from "@app/hooks/api/reactQuery";
|
|||||||
import { ProjectType } from "@app/hooks/api/workspace/types";
|
import { ProjectType } from "@app/hooks/api/workspace/types";
|
||||||
|
|
||||||
const QueryParamsSchema = z.object({
|
const QueryParamsSchema = z.object({
|
||||||
callback_port: z.coerce.number().optional().catch(undefined)
|
callback_port: z.coerce.number().optional().catch(undefined),
|
||||||
|
force: z.boolean().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
export const AuthConsentWrapper = () => {
|
export const AuthConsentWrapper = () => {
|
||||||
@@ -71,7 +72,7 @@ export const AuthConsentWrapper = () => {
|
|||||||
export const Route = createFileRoute("/_restrict-login-signup")({
|
export const Route = createFileRoute("/_restrict-login-signup")({
|
||||||
validateSearch: zodValidator(QueryParamsSchema),
|
validateSearch: zodValidator(QueryParamsSchema),
|
||||||
search: {
|
search: {
|
||||||
middlewares: [stripSearchParams({ callback_port: undefined })]
|
middlewares: [stripSearchParams({ callback_port: undefined, force: undefined })]
|
||||||
},
|
},
|
||||||
beforeLoad: async ({ context, location, search }) => {
|
beforeLoad: async ({ context, location, search }) => {
|
||||||
if (!context.serverConfig.initialized) {
|
if (!context.serverConfig.initialized) {
|
||||||
@@ -90,6 +91,12 @@ export const Route = createFileRoute("/_restrict-login-signup")({
|
|||||||
if (!data) return;
|
if (!data) return;
|
||||||
|
|
||||||
setAuthToken(data.token);
|
setAuthToken(data.token);
|
||||||
|
|
||||||
|
if (location.pathname === "/signupinvite") return;
|
||||||
|
|
||||||
|
// Avoid redirect if on select-organization page with force=true
|
||||||
|
if (location.pathname.endsWith("select-organization") && search?.force === true) return;
|
||||||
|
|
||||||
// to do cli login
|
// to do cli login
|
||||||
if (search?.callback_port) {
|
if (search?.callback_port) {
|
||||||
if (location.pathname.endsWith("select-organization") || location.pathname.endsWith("login"))
|
if (location.pathname.endsWith("select-organization") || location.pathname.endsWith("login"))
|
||||||
|
|||||||
Reference in New Issue
Block a user