mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-04 15:26:20 +00:00
Merge pull request #1313 from akhilmhdh/feat/migration-mode
feat(infisical-pg): added migration mode env and page
This commit is contained in:
@@ -6,6 +6,9 @@ export const client = new InfisicalClient({
|
|||||||
token: process.env.INFISICAL_TOKEN!
|
token: process.env.INFISICAL_TOKEN!
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const getIsMigrationMode = async () =>
|
||||||
|
(await client.getSecret("MIGRATION_MODE")).secretValue === "true";
|
||||||
|
|
||||||
export const getPort = async () => (await client.getSecret("PORT")).secretValue || 4000;
|
export const getPort = async () => (await client.getSecret("PORT")).secretValue || 4000;
|
||||||
export const getEncryptionKey = async () => {
|
export const getEncryptionKey = async () => {
|
||||||
const secretValue = (await client.getSecret("ENCRYPTION_KEY")).secretValue;
|
const secretValue = (await client.getSecret("ENCRYPTION_KEY")).secretValue;
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ import { IServerConfig, ServerConfig } from "../models/serverConfig";
|
|||||||
let serverConfig: IServerConfig;
|
let serverConfig: IServerConfig;
|
||||||
|
|
||||||
export const serverConfigInit = async () => {
|
export const serverConfigInit = async () => {
|
||||||
const cfg = await ServerConfig.findOne({});
|
const cfg = await ServerConfig.findOne({}).lean();
|
||||||
if (!cfg) {
|
if (!cfg) {
|
||||||
const cfg = new ServerConfig();
|
const cfg = new ServerConfig();
|
||||||
await cfg.save();
|
await cfg.save();
|
||||||
serverConfig = cfg;
|
serverConfig = cfg.toObject();
|
||||||
} else {
|
} else {
|
||||||
serverConfig = cfg;
|
serverConfig = cfg;
|
||||||
}
|
}
|
||||||
@@ -19,6 +19,6 @@ export const getServerConfig = () => serverConfig;
|
|||||||
export const updateServerConfig = async (data: Partial<IServerConfig>) => {
|
export const updateServerConfig = async (data: Partial<IServerConfig>) => {
|
||||||
const cfg = await ServerConfig.findByIdAndUpdate(serverConfig._id, data, { new: true });
|
const cfg = await ServerConfig.findByIdAndUpdate(serverConfig._id, data, { new: true });
|
||||||
if (!cfg) throw new Error("Failed to update server config");
|
if (!cfg) throw new Error("Failed to update server config");
|
||||||
serverConfig = cfg;
|
serverConfig = cfg.toObject();
|
||||||
return serverConfig;
|
return serverConfig;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import { getHttpsEnabled } from "../../config";
|
import { getHttpsEnabled, getIsMigrationMode } from "../../config";
|
||||||
import { getServerConfig, updateServerConfig as setServerConfig } from "../../config/serverConfig";
|
import { getServerConfig, updateServerConfig as setServerConfig } from "../../config/serverConfig";
|
||||||
import { initializeDefaultOrg, issueAuthTokens } from "../../helpers";
|
import { initializeDefaultOrg, issueAuthTokens } from "../../helpers";
|
||||||
import { validateRequest } from "../../helpers/validation";
|
import { validateRequest } from "../../helpers/validation";
|
||||||
@@ -8,9 +8,10 @@ import { TelemetryService } from "../../services";
|
|||||||
import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors";
|
import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors";
|
||||||
import * as reqValidator from "../../validation/admin";
|
import * as reqValidator from "../../validation/admin";
|
||||||
|
|
||||||
export const getServerConfigInfo = (_req: Request, res: Response) => {
|
export const getServerConfigInfo = async (_req: Request, res: Response) => {
|
||||||
const config = getServerConfig();
|
const config = getServerConfig();
|
||||||
return res.send({ config });
|
const isMigrationModeOn = await getIsMigrationMode();
|
||||||
|
return res.send({ config: { ...config, isMigrationModeOn } });
|
||||||
};
|
};
|
||||||
|
|
||||||
export const updateServerConfig = async (req: Request, res: Response) => {
|
export const updateServerConfig = async (req: Request, res: Response) => {
|
||||||
|
|||||||
+15
-2
@@ -83,6 +83,7 @@ import { healthCheck } from "./routes/status";
|
|||||||
import { RouteNotFoundError } from "./utils/errors";
|
import { RouteNotFoundError } from "./utils/errors";
|
||||||
import { requestErrorHandler } from "./middleware/requestErrorHandler";
|
import { requestErrorHandler } from "./middleware/requestErrorHandler";
|
||||||
import {
|
import {
|
||||||
|
getIsMigrationMode,
|
||||||
getMongoURL,
|
getMongoURL,
|
||||||
getNodeEnv,
|
getNodeEnv,
|
||||||
getPort,
|
getPort,
|
||||||
@@ -107,8 +108,8 @@ const main = async () => {
|
|||||||
|
|
||||||
const port = await getPort();
|
const port = await getPort();
|
||||||
|
|
||||||
// initializing the database connection + redis
|
// initializing the database connection + redis
|
||||||
await initRedis()
|
await initRedis();
|
||||||
await DatabaseService.initDatabase(await getMongoURL());
|
await DatabaseService.initDatabase(await getMongoURL());
|
||||||
const serverCfg = await serverConfigInit();
|
const serverCfg = await serverConfigInit();
|
||||||
await setup();
|
await setup();
|
||||||
@@ -198,6 +199,18 @@ const main = async () => {
|
|||||||
handler = nextApp.getRequestHandler();
|
handler = nextApp.getRequestHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.use((req, _res, next) => {
|
||||||
|
getIsMigrationMode()
|
||||||
|
.then((el) => {
|
||||||
|
if (el && req.method !== "GET") {
|
||||||
|
next(new Error("Migration mode"));
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
// (EE) routes
|
// (EE) routes
|
||||||
app.use("/api/v1/identities", v1IdentitiesRouter);
|
app.use("/api/v1/identities", v1IdentitiesRouter);
|
||||||
app.use("/api/v1/secret", eeSecretRouter);
|
app.use("/api/v1/secret", eeSecretRouter);
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 708 KiB |
@@ -1,4 +1,5 @@
|
|||||||
import { createContext, ReactNode, useContext, useEffect, useMemo } from "react";
|
import { createContext, ReactNode, useContext, useEffect, useMemo } from "react";
|
||||||
|
import Head from "next/head";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
import { ContentLoader } from "@app/components/v2/ContentLoader";
|
import { ContentLoader } from "@app/components/v2/ContentLoader";
|
||||||
@@ -27,11 +28,37 @@ export const ServerConfigProvider = ({ children }: Props): JSX.Element => {
|
|||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isLoading && data && !data.initialized) {
|
if (!isLoading && data && !data.initialized && !data.isMigrationModeOn) {
|
||||||
router.push("/admin/signup");
|
router.push("/admin/signup");
|
||||||
}
|
}
|
||||||
}, [isLoading, data]);
|
}, [isLoading, data]);
|
||||||
|
|
||||||
|
if (!isLoading && data?.isMigrationModeOn) {
|
||||||
|
return (
|
||||||
|
<div className="relative mx-auto flex h-screen w-full flex-col items-center justify-center space-y-8 bg-bunker-800 px-8 text-mineshaft-50 dark:[color-scheme:dark]">
|
||||||
|
<Head>
|
||||||
|
<title>Infisical Maintenance Mode</title>
|
||||||
|
<link rel='icon' href='/infisical.ico' />
|
||||||
|
</Head>
|
||||||
|
<img src="/images/maintenance.png" height={175} width={300} alt="maintenance mode" className="w-[40rem]"/>
|
||||||
|
<p className="mx-8 mb-4 flex justify-center bg-gradient-to-tr from-mineshaft-300 to-white bg-clip-text text-4xl font-bold text-transparent md:mx-16">
|
||||||
|
Scheduled Maintenance
|
||||||
|
</p>
|
||||||
|
<div className="mt-2 text-center text-lg text-bunker-300">
|
||||||
|
Infisical is undergoing planned maintenance. <br /> No action is required on your end — your applications will continue to fetch secrets.
|
||||||
|
<br /> If you have questions, please <a
|
||||||
|
className="text-bunker-300 underline underline-offset-4 decoration-primary-800 hover:decoration-primary-600 hover:text-mineshaft-100 duration-200"
|
||||||
|
href="https://infisical.com/slack"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
join our Slack community
|
||||||
|
</a>.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (isLoading || (!data?.initialized && router.pathname !== "/admin/signup")) {
|
if (isLoading || (!data?.initialized && router.pathname !== "/admin/signup")) {
|
||||||
return (
|
return (
|
||||||
<div className="bg-bunker-800">
|
<div className="bg-bunker-800">
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
export type TServerConfig = {
|
export type TServerConfig = {
|
||||||
initialized: boolean;
|
initialized: boolean;
|
||||||
allowSignUp: boolean;
|
allowSignUp: boolean;
|
||||||
|
isMigrationModeOn?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TCreateAdminUserDTO = {
|
export type TCreateAdminUserDTO = {
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ export const SignUpPage = () => {
|
|||||||
router.push("/login");
|
router.push("/login");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, []);
|
}, [config?.initialized]);
|
||||||
|
|
||||||
const { mutateAsync: createAdminUser } = useCreateAdminUser();
|
const { mutateAsync: createAdminUser } = useCreateAdminUser();
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ export const SignUpPage = () => {
|
|||||||
return <ContentLoader text="Redirecting to admin page..." />;
|
return <ContentLoader text="Redirecting to admin page..." />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex justify-center items-center">
|
<div className="flex items-center justify-center">
|
||||||
<AnimatePresence exitBeforeEnter>
|
<AnimatePresence exitBeforeEnter>
|
||||||
{step === SignupSteps.DetailsForm && (
|
{step === SignupSteps.DetailsForm && (
|
||||||
<motion.div
|
<motion.div
|
||||||
@@ -128,7 +128,7 @@ export const SignUpPage = () => {
|
|||||||
animate={{ opacity: 1, translateX: 0 }}
|
animate={{ opacity: 1, translateX: 0 }}
|
||||||
exit={{ opacity: 0, translateX: 30 }}
|
exit={{ opacity: 0, translateX: 30 }}
|
||||||
>
|
>
|
||||||
<div className="text-center flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4 text-center">
|
||||||
<img src="/images/gradientLogo.svg" height={90} width={120} alt="Infisical logo" />
|
<img src="/images/gradientLogo.svg" height={90} width={120} alt="Infisical logo" />
|
||||||
<div className="text-4xl">Welcome to Infisical</div>
|
<div className="text-4xl">Welcome to Infisical</div>
|
||||||
<div>Create your first Admin Account</div>
|
<div>Create your first Admin Account</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user