Make Cobble a local install: setup flow, bots-first admin, settings
Local, password-only auth: - No public pages; everything outside /admin and /auth redirects in - First run (no users) sends every page to /auth/signup, which creates the super admin (user #1) once and then locks - Login is email/username + password; removed the emailed-code flow, /auth/sso and email password reset - Google login kept for existing accounts only, never creates them - seed-super-admin now requires SEED_SUPER_ADMIN_PASSWORD Bots-first admin: - /admin and closed sections (people, logs, backups) redirect to /admin/bots; only bots and settings are live (AdminSections) - Removed the old admin layout; every /admin page uses the bots rail - Coordinator bot created at signup/seed and by /admin/bots (ensureCoordinatorBot), which redirects to its chat - bots.system_prompt (markdown) with a default coordinator prompt - seed-bots reuses the existing coordinator Settings: - Sub pages general (default), profile, change-password, listed in the rail with a back link; unknown settings paths redirect to general - Redesigned settings UI: pane header, grouped rows, sticky save bar - General: System/Light/Dark theme, saved per device Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
+48
-18
@@ -1,20 +1,49 @@
|
||||
import type { BunextPageServerFn } from "@moduletrace/bunext/types";
|
||||
import type { PagePropsType } from "../types";
|
||||
import userAuth from "../functions/backend/auth/user-auth";
|
||||
import grabLoginMethod from "../functions/backend/auth/grab-login-method";
|
||||
import grabHasUsers from "../functions/backend/auth/grab-has-users";
|
||||
import isAdminSectionPath from "../utils/is-admin-section-path";
|
||||
import { AdminHomePath } from "../dict/admin-sections-dict";
|
||||
import isUnknownSettingsPath from "../utils/is-unknown-settings-path";
|
||||
import { SettingsDefaultPath } from "../dict/settings-pages-dict";
|
||||
|
||||
/**
|
||||
* Routing for a local install. There are no public pages:
|
||||
* - no account yet: everything goes to `/auth/signup` (super admin setup)
|
||||
* - signup after setup: back to `/auth/login` (or the bots if logged in)
|
||||
* - anything outside the live admin sections and `/auth`: `/admin/bots`
|
||||
* - an unknown `/admin/settings/*` page: `/admin/settings/general`
|
||||
* - `/admin/*` logged out: `/auth/login`
|
||||
* - `/auth/*` logged in (except logout): `/admin/bots`
|
||||
*/
|
||||
const server: BunextPageServerFn<PagePropsType> = async ({ req, url }) => {
|
||||
const { user, user_types } = await userAuth({ req });
|
||||
const is_admin_page =
|
||||
url.pathname.startsWith("/admin") || url.pathname.startsWith("/auth");
|
||||
const is_signup_page = url.pathname.startsWith("/auth/signup");
|
||||
const has_users = await grabHasUsers();
|
||||
|
||||
if (!has_users && !is_signup_page) {
|
||||
return redirect({ destination: "/auth/signup" });
|
||||
}
|
||||
|
||||
if (has_users && is_signup_page) {
|
||||
return redirect({
|
||||
destination: user?.logged_in_status ? AdminHomePath : "/auth/login",
|
||||
});
|
||||
}
|
||||
|
||||
if (url.pathname.startsWith("/admin") && !user?.logged_in_status) {
|
||||
return {
|
||||
redirect: {
|
||||
destination: "/auth/login",
|
||||
permanent: false,
|
||||
},
|
||||
};
|
||||
return redirect({ destination: "/auth/login" });
|
||||
}
|
||||
|
||||
if (
|
||||
!isAdminSectionPath({ pathname: url.pathname }) &&
|
||||
!url.pathname.startsWith("/auth")
|
||||
) {
|
||||
return redirect({ destination: AdminHomePath });
|
||||
}
|
||||
|
||||
if (isUnknownSettingsPath({ pathname: url.pathname })) {
|
||||
return redirect({ destination: SettingsDefaultPath });
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -22,19 +51,13 @@ const server: BunextPageServerFn<PagePropsType> = async ({ req, url }) => {
|
||||
!url.pathname.match(/logout/) &&
|
||||
user?.logged_in_status
|
||||
) {
|
||||
return {
|
||||
redirect: {
|
||||
destination: "/admin",
|
||||
permanent: false,
|
||||
},
|
||||
};
|
||||
return redirect({ destination: AdminHomePath });
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
environment: process.env.NODE_ENV,
|
||||
envs: {
|
||||
AUTH_LOGIN_METHOD: grabLoginMethod(),
|
||||
GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID || "",
|
||||
R2_PUBLIC_DOMAIN: process.env.R2_PUBLIC_DOMAIN || "",
|
||||
PAYSTACK_PUBLIC_KEY: process.env.PAYSTACK_PUBLIC_KEY || "",
|
||||
@@ -42,9 +65,16 @@ const server: BunextPageServerFn<PagePropsType> = async ({ req, url }) => {
|
||||
user,
|
||||
user_types,
|
||||
},
|
||||
cache_page: is_admin_page ? false : true,
|
||||
cache_expiry: 360,
|
||||
};
|
||||
};
|
||||
|
||||
function redirect({ destination }: { destination: string }) {
|
||||
return {
|
||||
redirect: {
|
||||
destination,
|
||||
permanent: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default server;
|
||||
|
||||
Reference in New Issue
Block a user