mirror of
https://github.com/coder/coder.git
synced 2025-07-12 00:14:10 +00:00
chore(site): refactor useAuth and related hooks (#12567)
Close https://github.com/coder/coder/issues/12487
This commit is contained in:
@ -13,33 +13,33 @@ import type {
|
||||
import { delay } from "utils/delay";
|
||||
import { getTemplateVersionFiles } from "utils/templateVersion";
|
||||
|
||||
export const templateByNameKey = (orgId: string, name: string) => [
|
||||
orgId,
|
||||
export const templateByNameKey = (organizationId: string, name: string) => [
|
||||
organizationId,
|
||||
"template",
|
||||
name,
|
||||
"settings",
|
||||
];
|
||||
|
||||
export const templateByName = (
|
||||
orgId: string,
|
||||
organizationId: string,
|
||||
name: string,
|
||||
): QueryOptions<Template> => {
|
||||
return {
|
||||
queryKey: templateByNameKey(orgId, name),
|
||||
queryFn: async () => API.getTemplateByName(orgId, name),
|
||||
queryKey: templateByNameKey(organizationId, name),
|
||||
queryFn: async () => API.getTemplateByName(organizationId, name),
|
||||
};
|
||||
};
|
||||
|
||||
const getTemplatesQueryKey = (orgId: string, deprecated?: boolean) => [
|
||||
orgId,
|
||||
const getTemplatesQueryKey = (organizationId: string, deprecated?: boolean) => [
|
||||
organizationId,
|
||||
"templates",
|
||||
deprecated,
|
||||
];
|
||||
|
||||
export const templates = (orgId: string, deprecated?: boolean) => {
|
||||
export const templates = (organizationId: string, deprecated?: boolean) => {
|
||||
return {
|
||||
queryKey: getTemplatesQueryKey(orgId, deprecated),
|
||||
queryFn: () => API.getTemplates(orgId, { deprecated }),
|
||||
queryKey: getTemplatesQueryKey(organizationId, deprecated),
|
||||
queryFn: () => API.getTemplates(organizationId, { deprecated }),
|
||||
};
|
||||
};
|
||||
|
||||
@ -90,10 +90,10 @@ export const setGroupRole = (
|
||||
};
|
||||
};
|
||||
|
||||
export const templateExamples = (orgId: string) => {
|
||||
export const templateExamples = (organizationId: string) => {
|
||||
return {
|
||||
queryKey: [...getTemplatesQueryKey(orgId), "examples"],
|
||||
queryFn: () => API.getTemplateExamples(orgId),
|
||||
queryKey: [...getTemplatesQueryKey(organizationId), "examples"],
|
||||
queryFn: () => API.getTemplateExamples(organizationId),
|
||||
};
|
||||
};
|
||||
|
||||
@ -105,14 +105,14 @@ export const templateVersion = (versionId: string) => {
|
||||
};
|
||||
|
||||
export const templateVersionByName = (
|
||||
orgId: string,
|
||||
organizationId: string,
|
||||
templateName: string,
|
||||
versionName: string,
|
||||
) => {
|
||||
return {
|
||||
queryKey: ["templateVersion", orgId, templateName, versionName],
|
||||
queryKey: ["templateVersion", organizationId, templateName, versionName],
|
||||
queryFn: () =>
|
||||
API.getTemplateVersionByName(orgId, templateName, versionName),
|
||||
API.getTemplateVersionByName(organizationId, templateName, versionName),
|
||||
};
|
||||
};
|
||||
|
||||
@ -136,19 +136,25 @@ export const templateVersionVariables = (versionId: string) => {
|
||||
};
|
||||
};
|
||||
|
||||
export const createTemplateVersion = (orgId: string) => {
|
||||
export const createTemplateVersion = (organizationId: string) => {
|
||||
return {
|
||||
mutationFn: async (request: CreateTemplateVersionRequest) => {
|
||||
const newVersion = await API.createTemplateVersion(orgId, request);
|
||||
const newVersion = await API.createTemplateVersion(
|
||||
organizationId,
|
||||
request,
|
||||
);
|
||||
return newVersion;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const createAndBuildTemplateVersion = (orgId: string) => {
|
||||
export const createAndBuildTemplateVersion = (organizationId: string) => {
|
||||
return {
|
||||
mutationFn: async (request: CreateTemplateVersionRequest) => {
|
||||
const newVersion = await API.createTemplateVersion(orgId, request);
|
||||
const newVersion = await API.createTemplateVersion(
|
||||
organizationId,
|
||||
request,
|
||||
);
|
||||
await waitBuildToBeFinished(newVersion);
|
||||
return newVersion;
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
import type { FC } from "react";
|
||||
import { getUsers } from "api/api";
|
||||
import { useMe } from "contexts/auth/useMe";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { UserAvatar } from "../UserAvatar/UserAvatar";
|
||||
import { FilterSearchMenu, OptionItem } from "./filter";
|
||||
import { type UseFilterMenuOptions, useFilterMenu } from "./menu";
|
||||
@ -18,7 +18,7 @@ export const useUserFilterMenu = ({
|
||||
UseFilterMenuOptions<UserOption>,
|
||||
"value" | "onChange" | "enabled"
|
||||
>) => {
|
||||
const me = useMe();
|
||||
const { user: me } = useAuthenticated();
|
||||
|
||||
const addMeAsFirstOption = (options: UserOption[]) => {
|
||||
options = options.filter((option) => option.value !== me.username);
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
import { useQuery } from "react-query";
|
||||
import { getWorkspaceProxies, getWorkspaceProxyRegions } from "api/api";
|
||||
import type { Region, WorkspaceProxy } from "api/typesGenerated";
|
||||
import { usePermissions } from "contexts/auth/usePermissions";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { type ProxyLatencyReport, useProxyLatency } from "./useProxyLatency";
|
||||
|
||||
export interface ProxyContextValue {
|
||||
@ -116,7 +116,7 @@ export const ProxyProvider: FC<PropsWithChildren> = ({ children }) => {
|
||||
}
|
||||
});
|
||||
|
||||
const permissions = usePermissions();
|
||||
const { permissions } = useAuthenticated();
|
||||
const query = async (): Promise<Region[]> => {
|
||||
const endpoint = permissions.editWorkspaceProxies
|
||||
? getWorkspaceProxies
|
||||
|
33
site/src/contexts/auth/AuthProvider.test.tsx
Normal file
33
site/src/contexts/auth/AuthProvider.test.tsx
Normal file
@ -0,0 +1,33 @@
|
||||
import { renderHook } from "@testing-library/react";
|
||||
import type { FC, PropsWithChildren } from "react";
|
||||
import { QueryClientProvider } from "react-query";
|
||||
import { createTestQueryClient } from "testHelpers/renderHelpers";
|
||||
import { AuthProvider, useAuthContext } from "./AuthProvider";
|
||||
|
||||
const Wrapper: FC<PropsWithChildren> = ({ children }) => {
|
||||
return (
|
||||
<QueryClientProvider client={createTestQueryClient()}>
|
||||
<AuthProvider>{children}</AuthProvider>
|
||||
</QueryClientProvider>
|
||||
);
|
||||
};
|
||||
|
||||
describe("useAuth", () => {
|
||||
it("throws an error if it is used outside of <AuthProvider />", () => {
|
||||
jest.spyOn(console, "error").mockImplementation(() => {});
|
||||
|
||||
expect(() => {
|
||||
renderHook(() => useAuthContext());
|
||||
}).toThrow("useAuth should be used inside of <AuthProvider />");
|
||||
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("returns AuthContextValue when used inside of <AuthProvider />", () => {
|
||||
expect(() => {
|
||||
renderHook(() => useAuthContext(), {
|
||||
wrapper: Wrapper,
|
||||
});
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
@ -3,6 +3,7 @@ import {
|
||||
type FC,
|
||||
type PropsWithChildren,
|
||||
useCallback,
|
||||
useContext,
|
||||
} from "react";
|
||||
import { useMutation, useQuery, useQueryClient } from "react-query";
|
||||
import { isApiError } from "api/errors";
|
||||
@ -34,6 +35,7 @@ export type AuthContextValue = {
|
||||
user: User | undefined;
|
||||
permissions: Permissions | undefined;
|
||||
authMethods: AuthMethods | undefined;
|
||||
organizationId: string | undefined;
|
||||
signInError: unknown;
|
||||
updateProfileError: unknown;
|
||||
signOut: () => void;
|
||||
@ -121,9 +123,20 @@ export const AuthProvider: FC<PropsWithChildren> = ({ children }) => {
|
||||
authMethods: authMethodsQuery.data,
|
||||
signInError: loginMutation.error,
|
||||
updateProfileError: updateProfileMutation.error,
|
||||
organizationId: userQuery.data?.organization_ids[0],
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useAuthContext = () => {
|
||||
const context = useContext(AuthContext);
|
||||
|
||||
if (!context) {
|
||||
throw new Error("useAuth should be used inside of <AuthProvider />");
|
||||
}
|
||||
|
||||
return context;
|
||||
};
|
||||
|
@ -1,7 +1,15 @@
|
||||
import { screen } from "@testing-library/react";
|
||||
import { renderHook, screen } from "@testing-library/react";
|
||||
import { rest } from "msw";
|
||||
import { renderWithAuth } from "testHelpers/renderHelpers";
|
||||
import type { FC, PropsWithChildren } from "react";
|
||||
import { QueryClientProvider } from "react-query";
|
||||
import { MockPermissions, MockUser } from "testHelpers/entities";
|
||||
import {
|
||||
createTestQueryClient,
|
||||
renderWithAuth,
|
||||
} from "testHelpers/renderHelpers";
|
||||
import { server } from "testHelpers/server";
|
||||
import { AuthContext, type AuthContextValue } from "./AuthProvider";
|
||||
import { useAuthenticated } from "./RequireAuth";
|
||||
|
||||
describe("RequireAuth", () => {
|
||||
it("redirects to /login if user is not authenticated", async () => {
|
||||
@ -24,3 +32,71 @@ describe("RequireAuth", () => {
|
||||
await screen.findByText("Login");
|
||||
});
|
||||
});
|
||||
|
||||
const createAuthWrapper = (override: Partial<AuthContextValue>) => {
|
||||
const value = {
|
||||
user: undefined,
|
||||
isLoading: false,
|
||||
isSignedOut: false,
|
||||
isSigningOut: false,
|
||||
isConfiguringTheFirstUser: false,
|
||||
isSignedIn: false,
|
||||
isSigningIn: false,
|
||||
isUpdatingProfile: false,
|
||||
permissions: undefined,
|
||||
authMethods: undefined,
|
||||
organizationId: undefined,
|
||||
signInError: undefined,
|
||||
updateProfileError: undefined,
|
||||
signOut: jest.fn(),
|
||||
signIn: jest.fn(),
|
||||
updateProfile: jest.fn(),
|
||||
...override,
|
||||
};
|
||||
const Wrapper: FC<PropsWithChildren> = ({ children }) => {
|
||||
return (
|
||||
<QueryClientProvider client={createTestQueryClient()}>
|
||||
<AuthContext.Provider value={value}>{children}</AuthContext.Provider>
|
||||
</QueryClientProvider>
|
||||
);
|
||||
};
|
||||
|
||||
return Wrapper;
|
||||
};
|
||||
|
||||
describe("useAuthenticated", () => {
|
||||
it("throws an error if it is used outside of a context with user", () => {
|
||||
jest.spyOn(console, "error").mockImplementation(() => {});
|
||||
|
||||
expect(() => {
|
||||
renderHook(() => useAuthenticated(), {
|
||||
wrapper: createAuthWrapper({ user: undefined }),
|
||||
});
|
||||
}).toThrow("User is not authenticated.");
|
||||
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("throws an error if it is used outside of a context with permissions", () => {
|
||||
jest.spyOn(console, "error").mockImplementation(() => {});
|
||||
|
||||
expect(() => {
|
||||
renderHook(() => useAuthenticated(), {
|
||||
wrapper: createAuthWrapper({ user: MockUser }),
|
||||
});
|
||||
}).toThrow("Permissions are not available.");
|
||||
|
||||
jest.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("returns auth context values for authenticated context", () => {
|
||||
expect(() => {
|
||||
renderHook(() => useAuthenticated(), {
|
||||
wrapper: createAuthWrapper({
|
||||
user: MockUser,
|
||||
permissions: MockPermissions,
|
||||
}),
|
||||
});
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
@ -6,11 +6,11 @@ import { Loader } from "components/Loader/Loader";
|
||||
import { ProxyProvider } from "contexts/ProxyContext";
|
||||
import { DashboardProvider } from "modules/dashboard/DashboardProvider";
|
||||
import { embedRedirect } from "utils/redirect";
|
||||
import { useAuth } from "./useAuth";
|
||||
import { type AuthContextValue, useAuthContext } from "./AuthProvider";
|
||||
|
||||
export const RequireAuth: FC = () => {
|
||||
const { signOut, isSigningOut, isSignedOut, isSignedIn, isLoading } =
|
||||
useAuth();
|
||||
useAuthContext();
|
||||
const location = useLocation();
|
||||
const isHomePage = location.pathname === "/";
|
||||
const navigateTo = isHomePage
|
||||
@ -62,3 +62,23 @@ export const RequireAuth: FC = () => {
|
||||
</DashboardProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useAuthenticated = () => {
|
||||
const auth = useAuthContext();
|
||||
|
||||
if (!auth.user) {
|
||||
throw new Error("User is not authenticated.");
|
||||
}
|
||||
|
||||
if (!auth.permissions) {
|
||||
throw new Error("Permissions are not available.");
|
||||
}
|
||||
|
||||
// We can do some TS magic here but I would rather to be explicit on what
|
||||
// values are not undefined when authenticated
|
||||
return auth as AuthContextValue & {
|
||||
user: Exclude<AuthContextValue["user"], undefined>;
|
||||
permissions: Exclude<AuthContextValue["permissions"], undefined>;
|
||||
organizationId: Exclude<AuthContextValue["organizationId"], undefined>;
|
||||
};
|
||||
};
|
||||
|
@ -1,12 +0,0 @@
|
||||
import { useContext } from "react";
|
||||
import { AuthContext } from "./AuthProvider";
|
||||
|
||||
export const useAuth = () => {
|
||||
const context = useContext(AuthContext);
|
||||
|
||||
if (!context) {
|
||||
throw new Error("useAuth should be used inside of <AuthProvider />");
|
||||
}
|
||||
|
||||
return context;
|
||||
};
|
@ -1,12 +0,0 @@
|
||||
import type { User } from "api/typesGenerated";
|
||||
import { useAuth } from "./useAuth";
|
||||
|
||||
export const useMe = (): User => {
|
||||
const { user } = useAuth();
|
||||
|
||||
if (!user) {
|
||||
throw new Error("User is not authenticated");
|
||||
}
|
||||
|
||||
return user;
|
||||
};
|
@ -1,11 +0,0 @@
|
||||
import { useMe } from "./useMe";
|
||||
|
||||
export const useOrganizationId = (): string => {
|
||||
const me = useMe();
|
||||
|
||||
if (me.organization_ids.length < 1) {
|
||||
throw new Error("User is not a member of any organizations");
|
||||
}
|
||||
|
||||
return me.organization_ids[0];
|
||||
};
|
@ -1,12 +0,0 @@
|
||||
import type { Permissions } from "./permissions";
|
||||
import { useAuth } from "./useAuth";
|
||||
|
||||
export const usePermissions = (): Permissions => {
|
||||
const { permissions } = useAuth();
|
||||
|
||||
if (!permissions) {
|
||||
throw new Error("User is not authenticated.");
|
||||
}
|
||||
|
||||
return permissions;
|
||||
};
|
@ -5,7 +5,7 @@ import Snackbar from "@mui/material/Snackbar";
|
||||
import { type FC, type HTMLAttributes, Suspense } from "react";
|
||||
import { Outlet } from "react-router-dom";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { usePermissions } from "contexts/auth/usePermissions";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { LicenseBanner } from "modules/dashboard/LicenseBanner/LicenseBanner";
|
||||
import { ServiceBanner } from "modules/dashboard/ServiceBanner/ServiceBanner";
|
||||
import { dashboardContentBottomPadding } from "theme/constants";
|
||||
@ -15,7 +15,7 @@ import { Navbar } from "./Navbar/Navbar";
|
||||
import { useUpdateCheck } from "./useUpdateCheck";
|
||||
|
||||
export const DashboardLayout: FC = () => {
|
||||
const permissions = usePermissions();
|
||||
const { permissions } = useAuthenticated();
|
||||
const updateCheck = useUpdateCheck(permissions.viewUpdateCheck);
|
||||
const canViewDeployment = Boolean(permissions.viewDeploymentValues);
|
||||
|
||||
|
@ -2,11 +2,11 @@ import type { FC } from "react";
|
||||
import { useQuery } from "react-query";
|
||||
import { health } from "api/queries/debug";
|
||||
import { deploymentStats } from "api/queries/deployment";
|
||||
import { usePermissions } from "contexts/auth/usePermissions";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { DeploymentBannerView } from "./DeploymentBannerView";
|
||||
|
||||
export const DeploymentBanner: FC = () => {
|
||||
const permissions = usePermissions();
|
||||
const { permissions } = useAuthenticated();
|
||||
const deploymentStatsQuery = useQuery(deploymentStats());
|
||||
const healthQuery = useQuery({
|
||||
...health(),
|
||||
|
@ -1,7 +1,5 @@
|
||||
import type { FC } from "react";
|
||||
import { useAuth } from "contexts/auth/useAuth";
|
||||
import { useMe } from "contexts/auth/useMe";
|
||||
import { usePermissions } from "contexts/auth/usePermissions";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useProxy } from "contexts/ProxyContext";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { useFeatureVisibility } from "../useFeatureVisibility";
|
||||
@ -9,9 +7,7 @@ import { NavbarView } from "./NavbarView";
|
||||
|
||||
export const Navbar: FC = () => {
|
||||
const { appearance, buildInfo } = useDashboard();
|
||||
const { signOut } = useAuth();
|
||||
const me = useMe();
|
||||
const permissions = usePermissions();
|
||||
const { user: me, permissions, signOut } = useAuthenticated();
|
||||
const featureVisibility = useFeatureVisibility();
|
||||
const canViewAuditLog =
|
||||
featureVisibility["audit_log"] && Boolean(permissions.viewAuditLog);
|
||||
|
@ -16,7 +16,7 @@ import { Abbr } from "components/Abbr/Abbr";
|
||||
import { displayError } from "components/GlobalSnackbar/utils";
|
||||
import { CoderIcon } from "components/Icons/CoderIcon";
|
||||
import { Latency } from "components/Latency/Latency";
|
||||
import { usePermissions } from "contexts/auth/usePermissions";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import type { ProxyContextValue } from "contexts/ProxyContext";
|
||||
import { BUTTON_SM_HEIGHT, navHeight } from "theme/constants";
|
||||
import { UserDropdown } from "./UserDropdown/UserDropdown";
|
||||
@ -215,7 +215,7 @@ const ProxyMenu: FC<ProxyMenuProps> = ({ proxyContextValue }) => {
|
||||
const latencies = proxyContextValue.proxyLatencies;
|
||||
const isLoadingLatencies = Object.keys(latencies).length === 0;
|
||||
const isLoading = proxyContextValue.isLoading || isLoadingLatencies;
|
||||
const permissions = usePermissions();
|
||||
const { permissions } = useAuthenticated();
|
||||
|
||||
const proxyLatencyLoading = (proxy: TypesGen.Region): boolean => {
|
||||
if (!refetchDate) {
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
} from "api/queries/templates";
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { CreateTemplateForm } from "./CreateTemplateForm";
|
||||
import type { CreateTemplatePageViewProps } from "./types";
|
||||
@ -24,7 +24,7 @@ export const DuplicateTemplateView: FC<CreateTemplatePageViewProps> = ({
|
||||
isCreating,
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
const organizationId = useOrganizationId();
|
||||
const { organizationId } = useAuthenticated();
|
||||
const [searchParams] = useSearchParams();
|
||||
const templateByNameQuery = useQuery(
|
||||
templateByName(organizationId, searchParams.get("fromTemplate")!),
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
} from "api/queries/templates";
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { CreateTemplateForm } from "./CreateTemplateForm";
|
||||
import type { CreateTemplatePageViewProps } from "./types";
|
||||
@ -27,7 +27,7 @@ export const ImportStarterTemplateView: FC<CreateTemplatePageViewProps> = ({
|
||||
isCreating,
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
const organizationId = useOrganizationId();
|
||||
const { organizationId } = useAuthenticated();
|
||||
const [searchParams] = useSearchParams();
|
||||
const templateExamplesQuery = useQuery(templateExamples(organizationId));
|
||||
const templateExample = templateExamplesQuery.data?.find(
|
||||
|
@ -7,7 +7,7 @@ import {
|
||||
JobError,
|
||||
templateVersionVariables,
|
||||
} from "api/queries/templates";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { CreateTemplateForm } from "./CreateTemplateForm";
|
||||
import type { CreateTemplatePageViewProps } from "./types";
|
||||
@ -21,7 +21,7 @@ export const UploadTemplateView: FC<CreateTemplatePageViewProps> = ({
|
||||
error,
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
const organizationId = useOrganizationId();
|
||||
const { organizationId } = useAuthenticated();
|
||||
|
||||
const dashboard = useDashboard();
|
||||
const formPermissions = getFormPermissions(dashboard.entitlements);
|
||||
|
@ -63,7 +63,7 @@ export interface CreateUserFormProps {
|
||||
onCancel: () => void;
|
||||
error?: unknown;
|
||||
isLoading: boolean;
|
||||
myOrgId: string;
|
||||
organizationId: string;
|
||||
authMethods?: TypesGen.AuthMethods;
|
||||
}
|
||||
|
||||
@ -83,14 +83,14 @@ const validationSchema = Yup.object({
|
||||
|
||||
export const CreateUserForm: FC<
|
||||
React.PropsWithChildren<CreateUserFormProps>
|
||||
> = ({ onSubmit, onCancel, error, isLoading, myOrgId, authMethods }) => {
|
||||
> = ({ onSubmit, onCancel, error, isLoading, organizationId, authMethods }) => {
|
||||
const form: FormikContextType<TypesGen.CreateUserRequest> =
|
||||
useFormik<TypesGen.CreateUserRequest>({
|
||||
initialValues: {
|
||||
email: "",
|
||||
password: "",
|
||||
username: "",
|
||||
organization_id: myOrgId,
|
||||
organization_id: organizationId,
|
||||
disable_login: false,
|
||||
login_type: "",
|
||||
},
|
||||
|
@ -5,7 +5,7 @@ import { useNavigate } from "react-router-dom";
|
||||
import { authMethods, createUser } from "api/queries/users";
|
||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { Margins } from "components/Margins/Margins";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { CreateUserForm } from "./CreateUserForm";
|
||||
|
||||
@ -14,7 +14,7 @@ export const Language = {
|
||||
};
|
||||
|
||||
export const CreateUserPage: FC = () => {
|
||||
const myOrgId = useOrganizationId();
|
||||
const { organizationId } = useAuthenticated();
|
||||
const navigate = useNavigate();
|
||||
const queryClient = useQueryClient();
|
||||
const createUserMutation = useMutation(createUser(queryClient));
|
||||
@ -38,7 +38,7 @@ export const CreateUserPage: FC = () => {
|
||||
navigate("/users");
|
||||
}}
|
||||
isLoading={createUserMutation.isLoading}
|
||||
myOrgId={myOrgId}
|
||||
organizationId={organizationId}
|
||||
/>
|
||||
</Margins>
|
||||
);
|
||||
|
@ -17,8 +17,7 @@ import type {
|
||||
} from "api/typesGenerated";
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useMe } from "contexts/auth/useMe";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useEffectEvent } from "hooks/hookPolyfills";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { generateWorkspaceName } from "modules/workspaces/generateWorkspaceName";
|
||||
@ -34,9 +33,8 @@ export type CreateWorkspaceMode = (typeof createWorkspaceModes)[number];
|
||||
export type ExternalAuthPollingState = "idle" | "polling" | "abandoned";
|
||||
|
||||
const CreateWorkspacePage: FC = () => {
|
||||
const organizationId = useOrganizationId();
|
||||
const { template: templateName } = useParams() as { template: string };
|
||||
const me = useMe();
|
||||
const { user: me, organizationId } = useAuthenticated();
|
||||
const navigate = useNavigate();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const mode = getWorkspaceMode(searchParams);
|
||||
|
@ -6,8 +6,8 @@ import { deploymentConfig } from "api/queries/deployment";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { Margins } from "components/Margins/Margins";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { RequirePermission } from "contexts/auth/RequirePermission";
|
||||
import { usePermissions } from "contexts/auth/usePermissions";
|
||||
import { Sidebar } from "./Sidebar";
|
||||
|
||||
type DeploySettingsContextValue = {
|
||||
@ -30,7 +30,7 @@ export const useDeploySettings = (): DeploySettingsContextValue => {
|
||||
|
||||
export const DeploySettingsLayout: FC = () => {
|
||||
const deploymentConfigQuery = useQuery(deploymentConfig());
|
||||
const permissions = usePermissions();
|
||||
const { permissions } = useAuthenticated();
|
||||
|
||||
return (
|
||||
<RequirePermission isFeatureVisible={permissions.viewDeploymentValues}>
|
||||
|
@ -11,13 +11,13 @@ import {
|
||||
} from "api/queries/externalAuth";
|
||||
import { SignInLayout } from "components/SignInLayout/SignInLayout";
|
||||
import { Welcome } from "components/Welcome/Welcome";
|
||||
import { usePermissions } from "contexts/auth/usePermissions";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import ExternalAuthPageView from "./ExternalAuthPageView";
|
||||
|
||||
const ExternalAuthPage: FC = () => {
|
||||
const { provider } = useParams() as { provider: string };
|
||||
const [searchParams] = useSearchParams();
|
||||
const permissions = usePermissions();
|
||||
const { permissions } = useAuthenticated();
|
||||
const queryClient = useQueryClient();
|
||||
const externalAuthProviderOpts = externalAuthProvider(provider);
|
||||
const externalAuthProviderQuery = useQuery({
|
||||
|
@ -3,14 +3,14 @@ import { Helmet } from "react-helmet-async";
|
||||
import { useMutation, useQueryClient } from "react-query";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { createGroup } from "api/queries/groups";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { pageTitle } from "utils/page";
|
||||
import CreateGroupPageView from "./CreateGroupPageView";
|
||||
|
||||
export const CreateGroupPage: FC = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const navigate = useNavigate();
|
||||
const organizationId = useOrganizationId();
|
||||
const { organizationId } = useAuthenticated();
|
||||
const createGroupMutation = useMutation(createGroup(queryClient));
|
||||
|
||||
return (
|
||||
|
@ -4,15 +4,14 @@ import { useQuery } from "react-query";
|
||||
import { getErrorMessage } from "api/errors";
|
||||
import { groups } from "api/queries/groups";
|
||||
import { displayError } from "components/GlobalSnackbar/utils";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { usePermissions } from "contexts/auth/usePermissions";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
|
||||
import { pageTitle } from "utils/page";
|
||||
import GroupsPageView from "./GroupsPageView";
|
||||
|
||||
export const GroupsPage: FC = () => {
|
||||
const organizationId = useOrganizationId();
|
||||
const { createGroup: canCreateGroup } = usePermissions();
|
||||
const { organizationId, permissions } = useAuthenticated();
|
||||
const { createGroup: canCreateGroup } = permissions;
|
||||
const { template_rbac: isTemplateRBACEnabled } = useFeatureVisibility();
|
||||
const groupsQuery = useQuery(groups(organizationId));
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import type { FC } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { Navigate, useLocation, useNavigate } from "react-router-dom";
|
||||
import { useAuth } from "contexts/auth/useAuth";
|
||||
import { useAuthContext } from "contexts/auth/AuthProvider";
|
||||
import { getApplicationName } from "utils/appearance";
|
||||
import { retrieveRedirect } from "utils/redirect";
|
||||
import { LoginPageView } from "./LoginPageView";
|
||||
@ -16,7 +16,7 @@ export const LoginPage: FC = () => {
|
||||
isSigningIn,
|
||||
authMethods,
|
||||
signInError,
|
||||
} = useAuth();
|
||||
} = useAuthContext();
|
||||
const redirectTo = retrieveRedirect(location.search);
|
||||
const applicationName = getApplicationName();
|
||||
const navigate = useNavigate();
|
||||
|
@ -4,7 +4,7 @@ import { useMutation } from "react-query";
|
||||
import { Navigate, useNavigate } from "react-router-dom";
|
||||
import { createFirstUser } from "api/queries/users";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useAuth } from "contexts/auth/useAuth";
|
||||
import { useAuthContext } from "contexts/auth/AuthProvider";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { SetupPageView } from "./SetupPageView";
|
||||
|
||||
@ -15,7 +15,7 @@ export const SetupPage: FC = () => {
|
||||
isConfiguringTheFirstUser,
|
||||
isSignedIn,
|
||||
isSigningIn,
|
||||
} = useAuth();
|
||||
} = useAuthContext();
|
||||
const createFirstUserMutation = useMutation(createFirstUser());
|
||||
const setupIsComplete = !isConfiguringTheFirstUser;
|
||||
const navigate = useNavigate();
|
||||
|
@ -3,13 +3,13 @@ import { Helmet } from "react-helmet-async";
|
||||
import { useQuery } from "react-query";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { templateExamples } from "api/queries/templates";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { StarterTemplatePageView } from "./StarterTemplatePageView";
|
||||
|
||||
const StarterTemplatePage: FC = () => {
|
||||
const { exampleId } = useParams() as { exampleId: string };
|
||||
const organizationId = useOrganizationId();
|
||||
const { organizationId } = useAuthenticated();
|
||||
const templateExamplesQuery = useQuery(templateExamples(organizationId));
|
||||
const starterTemplate = templateExamplesQuery.data?.find(
|
||||
(example) => example.id === exampleId,
|
||||
|
@ -3,13 +3,13 @@ import { Helmet } from "react-helmet-async";
|
||||
import { useQuery } from "react-query";
|
||||
import { templateExamples } from "api/queries/templates";
|
||||
import type { TemplateExample } from "api/typesGenerated";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { getTemplatesByTag } from "utils/starterTemplates";
|
||||
import { StarterTemplatesPageView } from "./StarterTemplatesPageView";
|
||||
|
||||
const StarterTemplatesPage: FC = () => {
|
||||
const organizationId = useOrganizationId();
|
||||
const { organizationId } = useAuthenticated();
|
||||
const templateExamplesQuery = useQuery(templateExamples(organizationId));
|
||||
const starterTemplatesByTag = templateExamplesQuery.data
|
||||
? // Currently, the scratch template should not be displayed on the starter templates page.
|
||||
|
@ -17,7 +17,7 @@ jest.mock("components/SyntaxHighlighter/SyntaxHighlighter", () => ({
|
||||
test("displays the template files even when there is no previous version", async () => {
|
||||
server.use(
|
||||
rest.get(
|
||||
"/api/v2/organizations/:orgId/templates/:template/versions/:version/previous",
|
||||
"/api/v2/organizations/:organizationId/templates/:template/versions/:version/previous",
|
||||
(req, res, ctx) => {
|
||||
return res(ctx.status(404));
|
||||
},
|
||||
|
@ -3,19 +3,19 @@ import { Helmet } from "react-helmet-async";
|
||||
import { useQuery } from "react-query";
|
||||
import { previousTemplateVersion, templateFiles } from "api/queries/templates";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { TemplateFiles } from "modules/templates/TemplateFiles/TemplateFiles";
|
||||
import { useTemplateLayoutContext } from "pages/TemplatePage/TemplateLayout";
|
||||
import { getTemplatePageTitle } from "../utils";
|
||||
|
||||
const TemplateFilesPage: FC = () => {
|
||||
const orgId = useOrganizationId();
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { template, activeVersion } = useTemplateLayoutContext();
|
||||
const { data: currentFiles } = useQuery(
|
||||
templateFiles(activeVersion.job.file_id),
|
||||
);
|
||||
const previousVersionQuery = useQuery(
|
||||
previousTemplateVersion(orgId, template.name, activeVersion.name),
|
||||
previousTemplateVersion(organizationId, template.name, activeVersion.name),
|
||||
);
|
||||
const previousVersion = previousVersionQuery.data;
|
||||
const hasPreviousVersion =
|
||||
|
@ -17,7 +17,7 @@ import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { Margins } from "components/Margins/Margins";
|
||||
import { TAB_PADDING_Y, TabLink, Tabs, TabsList } from "components/Tabs/Tabs";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { TemplatePageHeader } from "./TemplatePageHeader";
|
||||
|
||||
const templatePermissions = (
|
||||
@ -38,8 +38,8 @@ const templatePermissions = (
|
||||
},
|
||||
});
|
||||
|
||||
const fetchTemplate = async (orgId: string, templateName: string) => {
|
||||
const template = await getTemplateByName(orgId, templateName);
|
||||
const fetchTemplate = async (organizationId: string, templateName: string) => {
|
||||
const template = await getTemplateByName(organizationId, templateName);
|
||||
const [activeVersion, permissions] = await Promise.all([
|
||||
getTemplateVersion(template.active_version_id),
|
||||
checkAuthorization({
|
||||
@ -74,11 +74,11 @@ export const TemplateLayout: FC<PropsWithChildren> = ({
|
||||
children = <Outlet />,
|
||||
}) => {
|
||||
const navigate = useNavigate();
|
||||
const orgId = useOrganizationId();
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { template: templateName } = useParams() as { template: string };
|
||||
const { data, error, isLoading } = useQuery({
|
||||
queryKey: ["template", templateName],
|
||||
queryFn: () => fetchTemplate(orgId, templateName),
|
||||
queryFn: () => fetchTemplate(organizationId, templateName),
|
||||
});
|
||||
const location = useLocation();
|
||||
const paths = location.pathname.split("/");
|
||||
|
@ -6,7 +6,7 @@ import { updateTemplateMeta } from "api/api";
|
||||
import { templateByNameKey } from "api/queries/templates";
|
||||
import type { UpdateTemplateMeta } from "api/typesGenerated";
|
||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { useTemplateSettings } from "../TemplateSettingsLayout";
|
||||
@ -15,7 +15,7 @@ import { TemplateSettingsPageView } from "./TemplateSettingsPageView";
|
||||
export const TemplateSettingsPage: FC = () => {
|
||||
const { template: templateName } = useParams() as { template: string };
|
||||
const navigate = useNavigate();
|
||||
const orgId = useOrganizationId();
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { template } = useTemplateSettings();
|
||||
const queryClient = useQueryClient();
|
||||
const { entitlements, experiments } = useDashboard();
|
||||
@ -42,7 +42,7 @@ export const TemplateSettingsPage: FC = () => {
|
||||
//
|
||||
// we use data.name because an admin may have updated templateName to something new
|
||||
await queryClient.invalidateQueries(
|
||||
templateByNameKey(orgId, data.name),
|
||||
templateByNameKey(organizationId, data.name),
|
||||
);
|
||||
}
|
||||
displaySuccess("Template updated successfully");
|
||||
|
@ -4,7 +4,7 @@ import { useMutation, useQuery, useQueryClient } from "react-query";
|
||||
import { setGroupRole, setUserRole, templateACL } from "api/queries/templates";
|
||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { Paywall } from "components/Paywall/Paywall";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
|
||||
import { docs } from "utils/docs";
|
||||
import { pageTitle } from "utils/page";
|
||||
@ -12,7 +12,7 @@ import { useTemplateSettings } from "../TemplateSettingsLayout";
|
||||
import { TemplatePermissionsPageView } from "./TemplatePermissionsPageView";
|
||||
|
||||
export const TemplatePermissionsPage: FC = () => {
|
||||
const organizationId = useOrganizationId();
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { template, permissions } = useTemplateSettings();
|
||||
const { template_rbac: isTemplateRBACEnabled } = useFeatureVisibility();
|
||||
const templateACLQuery = useQuery(templateACL(template.id));
|
||||
|
@ -6,7 +6,7 @@ import { updateTemplateMeta } from "api/api";
|
||||
import { templateByNameKey } from "api/queries/templates";
|
||||
import type { UpdateTemplateMeta } from "api/typesGenerated";
|
||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { useTemplateSettings } from "../TemplateSettingsLayout";
|
||||
@ -16,7 +16,7 @@ const TemplateSchedulePage: FC = () => {
|
||||
const { template: templateName } = useParams() as { template: string };
|
||||
const navigate = useNavigate();
|
||||
const queryClient = useQueryClient();
|
||||
const orgId = useOrganizationId();
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { template } = useTemplateSettings();
|
||||
const { entitlements } = useDashboard();
|
||||
const allowAdvancedScheduling =
|
||||
@ -31,7 +31,7 @@ const TemplateSchedulePage: FC = () => {
|
||||
{
|
||||
onSuccess: async () => {
|
||||
await queryClient.invalidateQueries(
|
||||
templateByNameKey(orgId, templateName),
|
||||
templateByNameKey(organizationId, templateName),
|
||||
);
|
||||
displaySuccess("Template updated successfully");
|
||||
// clear browser storage of workspaces impending deletion
|
||||
|
@ -9,7 +9,7 @@ import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { Margins } from "components/Margins/Margins";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { Sidebar } from "./Sidebar";
|
||||
|
||||
@ -27,9 +27,9 @@ export function useTemplateSettings() {
|
||||
}
|
||||
|
||||
export const TemplateSettingsLayout: FC = () => {
|
||||
const orgId = useOrganizationId();
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { template: templateName } = useParams() as { template: string };
|
||||
const templateQuery = useQuery(templateByName(orgId, templateName));
|
||||
const templateQuery = useQuery(templateByName(organizationId, templateName));
|
||||
const permissionsQuery = useQuery({
|
||||
...checkAuthorization({
|
||||
checks: {
|
||||
|
@ -16,7 +16,7 @@ import type {
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { useTemplateSettings } from "../TemplateSettingsLayout";
|
||||
import { TemplateVariablesPageView } from "./TemplateVariablesPageView";
|
||||
@ -26,7 +26,7 @@ export const TemplateVariablesPage: FC = () => {
|
||||
organization: string;
|
||||
template: string;
|
||||
};
|
||||
const orgId = useOrganizationId();
|
||||
const { organizationId } = useAuthenticated();
|
||||
const { template } = useTemplateSettings();
|
||||
const navigate = useNavigate();
|
||||
const queryClient = useQueryClient();
|
||||
@ -50,7 +50,7 @@ export const TemplateVariablesPage: FC = () => {
|
||||
mutateAsync: sendCreateAndBuildTemplateVersion,
|
||||
error: buildError,
|
||||
isLoading: isBuilding,
|
||||
} = useMutation(createAndBuildTemplateVersion(orgId));
|
||||
} = useMutation(createAndBuildTemplateVersion(organizationId));
|
||||
const {
|
||||
mutateAsync: sendUpdateActiveTemplateVersion,
|
||||
error: publishError,
|
||||
|
@ -18,7 +18,7 @@ import type {
|
||||
} from "api/typesGenerated";
|
||||
import { displayError } from "components/GlobalSnackbar/utils";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useWatchVersionLogs } from "modules/templates/useWatchVersionLogs";
|
||||
import { type FileTree, traverse } from "utils/filetree";
|
||||
import { pageTitle } from "utils/page";
|
||||
@ -36,10 +36,10 @@ export const TemplateVersionEditorPage: FC = () => {
|
||||
const navigate = useNavigate();
|
||||
const { version: versionName, template: templateName } =
|
||||
useParams() as Params;
|
||||
const orgId = useOrganizationId();
|
||||
const templateQuery = useQuery(templateByName(orgId, templateName));
|
||||
const { organizationId } = useAuthenticated();
|
||||
const templateQuery = useQuery(templateByName(organizationId, templateName));
|
||||
const templateVersionOptions = templateVersionByName(
|
||||
orgId,
|
||||
organizationId,
|
||||
templateName,
|
||||
versionName,
|
||||
);
|
||||
@ -49,7 +49,7 @@ export const TemplateVersionEditorPage: FC = () => {
|
||||
});
|
||||
const uploadFileMutation = useMutation(uploadFile());
|
||||
const createTemplateVersionMutation = useMutation(
|
||||
createTemplateVersion(orgId),
|
||||
createTemplateVersion(organizationId),
|
||||
);
|
||||
const resourcesQuery = useQuery({
|
||||
...resources(templateVersionQuery.data?.id ?? ""),
|
||||
@ -71,7 +71,7 @@ export const TemplateVersionEditorPage: FC = () => {
|
||||
mutationFn: publishVersion,
|
||||
onSuccess: async () => {
|
||||
await queryClient.invalidateQueries(
|
||||
templateByNameKey(orgId, templateName),
|
||||
templateByNameKey(organizationId, templateName),
|
||||
);
|
||||
},
|
||||
});
|
||||
|
@ -8,8 +8,7 @@ import {
|
||||
templateVersion,
|
||||
templateVersionByName,
|
||||
} from "api/queries/templates";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { usePermissions } from "contexts/auth/usePermissions";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { pageTitle } from "utils/page";
|
||||
import TemplateVersionPageView from "./TemplateVersionPageView";
|
||||
|
||||
@ -21,14 +20,14 @@ type Params = {
|
||||
export const TemplateVersionPage: FC = () => {
|
||||
const { version: versionName, template: templateName } =
|
||||
useParams() as Params;
|
||||
const orgId = useOrganizationId();
|
||||
const { organizationId } = useAuthenticated();
|
||||
|
||||
/**
|
||||
* Template version files
|
||||
*/
|
||||
const templateQuery = useQuery(templateByName(orgId, templateName));
|
||||
const templateQuery = useQuery(templateByName(organizationId, templateName));
|
||||
const selectedVersionQuery = useQuery(
|
||||
templateVersionByName(orgId, templateName, versionName),
|
||||
templateVersionByName(organizationId, templateName, versionName),
|
||||
);
|
||||
const selectedVersionFilesQuery = useQuery({
|
||||
...templateFiles(selectedVersionQuery.data?.job.file_id ?? ""),
|
||||
@ -43,7 +42,7 @@ export const TemplateVersionPage: FC = () => {
|
||||
enabled: Boolean(activeVersionQuery.data),
|
||||
});
|
||||
|
||||
const permissions = usePermissions();
|
||||
const { permissions } = useAuthenticated();
|
||||
const versionId = selectedVersionQuery.data?.id;
|
||||
const createWorkspaceUrl = useMemo(() => {
|
||||
const params = new URLSearchParams();
|
||||
|
@ -2,14 +2,12 @@ import type { FC } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useQuery } from "react-query";
|
||||
import { templateExamples, templates } from "api/queries/templates";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { usePermissions } from "contexts/auth/usePermissions";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { TemplatesPageView } from "./TemplatesPageView";
|
||||
|
||||
export const TemplatesPage: FC = () => {
|
||||
const organizationId = useOrganizationId();
|
||||
const permissions = usePermissions();
|
||||
const { organizationId, permissions } = useAuthenticated();
|
||||
const templatesQuery = useQuery(templates(organizationId));
|
||||
const examplesQuery = useQuery({
|
||||
...templateExamples(organizationId),
|
||||
|
@ -2,20 +2,17 @@ import type { FC } from "react";
|
||||
import { useQuery } from "react-query";
|
||||
import { groupsForUser } from "api/queries/groups";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import { useAuth } from "contexts/auth/useAuth";
|
||||
import { useMe } from "contexts/auth/useMe";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { usePermissions } from "contexts/auth/usePermissions";
|
||||
import { useAuthContext } from "contexts/auth/AuthProvider";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { Section } from "../Section";
|
||||
import { AccountForm } from "./AccountForm";
|
||||
import { AccountUserGroups } from "./AccountUserGroups";
|
||||
|
||||
export const AccountPage: FC = () => {
|
||||
const me = useMe();
|
||||
const permissions = usePermissions();
|
||||
const organizationId = useOrganizationId();
|
||||
const { updateProfile, updateProfileError, isUpdatingProfile } = useAuth();
|
||||
const { user: me, permissions, organizationId } = useAuthenticated();
|
||||
const { updateProfile, updateProfileError, isUpdatingProfile } =
|
||||
useAuthContext();
|
||||
const { entitlements } = useDashboard();
|
||||
|
||||
const hasGroupsFeature = entitlements.features.user_role_management.enabled;
|
||||
|
@ -3,12 +3,12 @@ import type { FC } from "react";
|
||||
import { useMutation, useQueryClient } from "react-query";
|
||||
import { updateAppearanceSettings } from "api/queries/users";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import { useMe } from "contexts/auth/useMe";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { Section } from "../Section";
|
||||
import { AppearanceForm } from "./AppearanceForm";
|
||||
|
||||
export const AppearancePage: FC = () => {
|
||||
const me = useMe();
|
||||
const { user: me } = useAuthenticated();
|
||||
const queryClient = useQueryClient();
|
||||
const updateAppearanceSettingsMutation = useMutation(
|
||||
updateAppearanceSettings("me", queryClient),
|
||||
|
@ -4,12 +4,12 @@ import { Outlet } from "react-router-dom";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { Margins } from "components/Margins/Margins";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import { useMe } from "contexts/auth/useMe";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { Sidebar } from "./Sidebar";
|
||||
|
||||
const Layout: FC = () => {
|
||||
const me = useMe();
|
||||
const { user: me } = useAuthenticated();
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -4,12 +4,12 @@ import { getErrorMessage } from "api/errors";
|
||||
import { getApps, revokeApp } from "api/queries/oauth2";
|
||||
import { DeleteDialog } from "components/Dialogs/DeleteDialog/DeleteDialog";
|
||||
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { useMe } from "contexts/auth/useMe";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { Section } from "../Section";
|
||||
import OAuth2ProviderPageView from "./OAuth2ProviderPageView";
|
||||
|
||||
const OAuth2ProviderPage: FC = () => {
|
||||
const me = useMe();
|
||||
const { user: me } = useAuthenticated();
|
||||
const queryClient = useQueryClient();
|
||||
const userOAuth2AppsQuery = useQuery(getApps(me.id));
|
||||
const revokeAppMutation = useMutation(revokeApp(queryClient, me.id));
|
||||
|
@ -7,12 +7,12 @@ import {
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { useMe } from "contexts/auth/useMe";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { Section } from "../Section";
|
||||
import { ScheduleForm } from "./ScheduleForm";
|
||||
|
||||
export const SchedulePage: FC = () => {
|
||||
const me = useMe();
|
||||
const { user: me } = useAuthenticated();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const {
|
||||
|
@ -5,7 +5,7 @@ import { authMethods, updatePassword } from "api/queries/users";
|
||||
import { displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import { useMe } from "contexts/auth/useMe";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { Section } from "../Section";
|
||||
import { SecurityForm } from "./SecurityForm";
|
||||
import {
|
||||
@ -14,7 +14,7 @@ import {
|
||||
} from "./SingleSignOnSection";
|
||||
|
||||
export const SecurityPage: FC = () => {
|
||||
const me = useMe();
|
||||
const { user: me } = useAuthenticated();
|
||||
const updatePasswordMutation = useMutation(updatePassword());
|
||||
const authMethodsQuery = useQuery(authMethods());
|
||||
const { data: userLoginType } = useQuery({
|
||||
|
@ -13,13 +13,14 @@ import { Loader } from "components/Loader/Loader";
|
||||
import { Margins } from "components/Margins/Margins";
|
||||
import { PageHeader, PageHeaderTitle } from "components/PageHeader/PageHeader";
|
||||
import { TAB_PADDING_Y, TabLink, Tabs, TabsList } from "components/Tabs/Tabs";
|
||||
import { usePermissions } from "contexts/auth/usePermissions";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { USERS_LINK } from "modules/dashboard/Navbar/NavbarView";
|
||||
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
|
||||
|
||||
export const UsersLayout: FC = () => {
|
||||
const { permissions } = useAuthenticated();
|
||||
const { createUser: canCreateUser, createGroup: canCreateGroup } =
|
||||
usePermissions();
|
||||
permissions;
|
||||
const navigate = useNavigate();
|
||||
const { template_rbac: isTemplateRBACEnabled } = useFeatureVisibility();
|
||||
const location = useLocation();
|
||||
|
@ -21,9 +21,7 @@ import { DeleteDialog } from "components/Dialogs/DeleteDialog/DeleteDialog";
|
||||
import { useFilter } from "components/Filter/filter";
|
||||
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
|
||||
import { isNonInitialPage } from "components/PaginationWidget/utils";
|
||||
import { useMe } from "contexts/auth/useMe";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { usePermissions } from "contexts/auth/usePermissions";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { usePaginatedQuery } from "hooks/usePaginatedQuery";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { pageTitle } from "utils/page";
|
||||
@ -40,12 +38,13 @@ export const UsersPage: FC = () => {
|
||||
const { entitlements } = useDashboard();
|
||||
const [searchParams] = searchParamsResult;
|
||||
|
||||
const organizationId = useOrganizationId();
|
||||
const { organizationId } = useAuthenticated();
|
||||
const groupsByUserIdQuery = useQuery(groupsByUserId(organizationId));
|
||||
const authMethodsQuery = useQuery(authMethods());
|
||||
|
||||
const me = useMe();
|
||||
const { updateUsers: canEditUsers, viewDeploymentValues } = usePermissions();
|
||||
const { user: me } = useAuthenticated();
|
||||
const { permissions } = useAuthenticated();
|
||||
const { updateUsers: canEditUsers, viewDeploymentValues } = permissions;
|
||||
const rolesQuery = useQuery(roles());
|
||||
const { data: deploymentValues } = useQuery({
|
||||
...deploymentConfig(),
|
||||
|
@ -10,7 +10,7 @@ import type { Workspace } from "api/typesGenerated";
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { Margins } from "components/Margins/Margins";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useEffectEvent } from "hooks/hookPolyfills";
|
||||
import { Navbar } from "modules/dashboard/Navbar/Navbar";
|
||||
import { ServiceBanner } from "modules/dashboard/ServiceBanner/ServiceBanner";
|
||||
@ -25,7 +25,7 @@ export const WorkspacePage: FC = () => {
|
||||
};
|
||||
const workspaceName = params.workspace;
|
||||
const username = params.username.replace("@", "");
|
||||
const orgId = useOrganizationId();
|
||||
const { organizationId } = useAuthenticated();
|
||||
|
||||
// Workspace
|
||||
const workspaceQueryOptions = workspaceByOwnerAndName(
|
||||
@ -37,7 +37,7 @@ export const WorkspacePage: FC = () => {
|
||||
|
||||
// Template
|
||||
const templateQuery = useQuery({
|
||||
...templateByName(orgId, workspace?.template_name ?? ""),
|
||||
...templateByName(organizationId, workspace?.template_name ?? ""),
|
||||
enabled: workspace !== undefined,
|
||||
});
|
||||
const template = templateQuery.data;
|
||||
|
@ -25,7 +25,7 @@ import {
|
||||
import { displayError } from "components/GlobalSnackbar/utils";
|
||||
import { MemoizedInlineMarkdown } from "components/Markdown/Markdown";
|
||||
import { Stack } from "components/Stack/Stack";
|
||||
import { useMe } from "contexts/auth/useMe";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useWorkspaceBuildLogs } from "hooks/useWorkspaceBuildLogs";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
import { useFeatureVisibility } from "modules/dashboard/useFeatureVisibility";
|
||||
@ -57,7 +57,7 @@ export const WorkspaceReadyPage: FC<WorkspaceReadyPageProps> = ({
|
||||
}
|
||||
|
||||
// Owner
|
||||
const me = useMe();
|
||||
const { user: me } = useAuthenticated();
|
||||
const isOwner = me.roles.find((role) => role.name === "owner") !== undefined;
|
||||
|
||||
// Debug mode
|
||||
|
@ -6,8 +6,7 @@ import { templates } from "api/queries/templates";
|
||||
import type { Workspace } from "api/typesGenerated";
|
||||
import { useFilter } from "components/Filter/filter";
|
||||
import { useUserFilterMenu } from "components/Filter/UserFilter";
|
||||
import { useOrganizationId } from "contexts/auth/useOrganizationId";
|
||||
import { usePermissions } from "contexts/auth/usePermissions";
|
||||
import { useAuthenticated } from "contexts/auth/RequireAuth";
|
||||
import { useEffectEvent } from "hooks/hookPolyfills";
|
||||
import { usePagination } from "hooks/usePagination";
|
||||
import { useDashboard } from "modules/dashboard/useDashboard";
|
||||
@ -40,7 +39,7 @@ const WorkspacesPage: FC = () => {
|
||||
const searchParamsResult = useSafeSearchParams();
|
||||
const pagination = usePagination({ searchParamsResult });
|
||||
|
||||
const organizationId = useOrganizationId();
|
||||
const { organizationId, permissions } = useAuthenticated();
|
||||
const templatesQuery = useQuery(templates(organizationId, false));
|
||||
|
||||
const filterProps = useWorkspacesFilter({
|
||||
@ -63,7 +62,6 @@ const WorkspacesPage: FC = () => {
|
||||
const { entitlements } = useDashboard();
|
||||
const canCheckWorkspaces =
|
||||
entitlements.features["workspace_batch_actions"].enabled;
|
||||
const permissions = usePermissions();
|
||||
const batchActions = useBatchActions({
|
||||
onSuccess: async () => {
|
||||
await refetch();
|
||||
@ -156,7 +154,7 @@ const useWorkspacesFilter = ({
|
||||
onUpdate: onFilterChange,
|
||||
});
|
||||
|
||||
const permissions = usePermissions();
|
||||
const { permissions } = useAuthenticated();
|
||||
const canFilterByUser = permissions.viewDeploymentValues;
|
||||
const userMenu = useUserFilterMenu({
|
||||
value: filter.values.owner,
|
||||
@ -166,7 +164,7 @@ const useWorkspacesFilter = ({
|
||||
});
|
||||
|
||||
const templateMenu = useTemplateFilterMenu({
|
||||
orgId: organizationId,
|
||||
organizationId,
|
||||
value: filter.values.template,
|
||||
onChange: (option) =>
|
||||
filter.update({ ...filter.values, template: option?.value }),
|
||||
|
@ -10,8 +10,8 @@ import type { StatusOption, TemplateOption } from "./options";
|
||||
export const useTemplateFilterMenu = ({
|
||||
value,
|
||||
onChange,
|
||||
orgId,
|
||||
}: { orgId: string } & Pick<
|
||||
organizationId,
|
||||
}: { organizationId: string } & Pick<
|
||||
UseFilterMenuOptions<TemplateOption>,
|
||||
"value" | "onChange"
|
||||
>) => {
|
||||
@ -21,7 +21,7 @@ export const useTemplateFilterMenu = ({
|
||||
id: "template",
|
||||
getSelectedOption: async () => {
|
||||
// Show all templates including deprecated
|
||||
const templates = await getTemplates(orgId);
|
||||
const templates = await getTemplates(organizationId);
|
||||
const template = templates.find((template) => template.name === value);
|
||||
if (template) {
|
||||
return {
|
||||
@ -37,7 +37,7 @@ export const useTemplateFilterMenu = ({
|
||||
},
|
||||
getOptions: async (query) => {
|
||||
// Show all templates including deprecated
|
||||
const templates = await getTemplates(orgId);
|
||||
const templates = await getTemplates(organizationId);
|
||||
const filteredTemplates = templates.filter(
|
||||
(template) =>
|
||||
template.name.toLowerCase().includes(query.toLowerCase()) ||
|
||||
|
Reference in New Issue
Block a user