UNPKG

studiocms

Version:

Astro Native CMS for AstroDB. Built from the ground up by the Astro community.

206 lines (205 loc) 7.71 kB
import { StudioCMSColorwayError, StudioCMSColorwayInfo } from "@withstudiocms/cli-kit/colors"; import { log, note, password, select, text } from "@withstudiocms/effect/clack"; import { eq } from "drizzle-orm"; import { Effect, runEffect } from "../../../../effect.js"; import { buildDebugLogger } from "../../../utils/logger.js"; import { libSQLDrizzleClient, Permissions, Users } from "../../../utils/useLibSQLDb.js"; import { getCheckers, hashPassword, verifyPasswordStrength } from "../../../utils/user-utils.js"; var UserFieldOption = /* @__PURE__ */ ((UserFieldOption2) => { UserFieldOption2["password"] = "password"; UserFieldOption2["username"] = "username"; UserFieldOption2["name"] = "name"; return UserFieldOption2; })(UserFieldOption || {}); const libsqlModifyUsers = Effect.fn(function* (context, debug, dryRun) { const [checker, debugLogger] = yield* Effect.all([getCheckers, buildDebugLogger(debug)]); const { ASTRO_DB_REMOTE_URL, ASTRO_DB_APP_TOKEN } = process.env; const [_drop, db] = yield* Effect.all([ debugLogger("Running libsqlUsers..."), libSQLDrizzleClient(ASTRO_DB_REMOTE_URL, ASTRO_DB_APP_TOKEN) ]); yield* debugLogger("Getting Users from DB..."); const [currentUsers, currentPermissions] = yield* db.execute( (tx) => tx.batch([tx.select().from(Users), tx.select().from(Permissions)]) ); if (currentUsers.length === 0) { yield* note("There are no users in the database.", "No Users Available"); yield* context.exit(0); } const allUsers = []; for (const user of currentUsers) { allUsers.push({ value: user.id, label: user.username, hint: currentPermissions.find((perm) => perm.user === user.id)?.rank }); } const userSelection = yield* select({ message: "Select a user to modify", options: allUsers }); if (typeof userSelection === "symbol") { return yield* context.pCancel(userSelection); } yield* note(`User ID Selected: ${userSelection}`); const action = yield* select({ message: "Which user field would you like to update?", options: [ { value: "password" /* password */, label: "Password" }, { value: "username" /* username */, label: "Username" }, { value: "name" /* name */, label: "Display Name" } ] }); switch (action) { case "name" /* name */: { const newDisplayName = yield* text({ message: "Enter new display name", placeholder: currentUsers.find((u) => u.id === userSelection)?.name || "John Doe", validate: (v) => v.trim().length === 0 ? "Display name cannot be empty" : void 0 }); if (typeof newDisplayName === "symbol") { return yield* context.pCancel(newDisplayName); } if (dryRun) { context.tasks.push({ title: `${StudioCMSColorwayInfo.bold("--dry-run")} ${context.chalk.dim("Skipping user modification")}`, task: async (message) => { message("Modifying user... (skipped)"); } }); } else { context.tasks.push({ title: context.chalk.dim("Modifying user..."), task: async (message) => { try { await runEffect( db.execute( (tx) => tx.update(Users).set({ name: newDisplayName }).where(eq(Users.id, userSelection)) ) ); message("User modified successfully"); } catch (e) { if (e instanceof Error) { await runEffect(log.error(StudioCMSColorwayError(`Error: ${e.message}`))); await runEffect(context.exit(1)); } else { await runEffect( log.error(StudioCMSColorwayError("Unknown Error: Unable to modify user.")) ); await runEffect(context.exit(1)); } } } }); } break; } case "username" /* username */: { const newUsername = yield* text({ message: "Enter new username", placeholder: currentUsers.find((u) => u.id === userSelection)?.username || "johndoe", validate: (user) => { const u = user.trim(); const isUser = currentUsers.find(({ username }) => username === u); if (isUser) return "Username is already in use, please try another one"; if (Effect.runSync(checker.username(u))) { return "Username should not be a commonly used unsafe username (admin, root, etc.)"; } return void 0; } }); if (typeof newUsername === "symbol") { return yield* context.pCancel(newUsername); } if (dryRun) { context.tasks.push({ title: `${StudioCMSColorwayInfo.bold("--dry-run")} ${context.chalk.dim("Skipping user modification")}`, task: async (message) => { message("Modifying user... (skipped)"); } }); } else { context.tasks.push({ title: context.chalk.dim("Modifying user..."), task: async (message) => { try { await runEffect( db.execute( (tx) => tx.update(Users).set({ username: newUsername }).where(eq(Users.id, userSelection)) ) ); message("User modified successfully"); } catch (e) { if (e instanceof Error) { await runEffect(log.error(StudioCMSColorwayError(`Error: ${e.message}`))); await runEffect(context.exit(1)); } else { await runEffect( log.error(StudioCMSColorwayError("Unknown Error: Unable to modify user.")) ); await runEffect(context.exit(1)); } } } }); } break; } case "password" /* password */: { const newPassword = yield* password({ message: `Enter the user's new password`, validate: (pass) => { const passCheck = Effect.runSync(verifyPasswordStrength(pass)); if (passCheck !== true) { return passCheck; } return void 0; } }); if (typeof newPassword === "symbol") { return yield* context.pCancel(newPassword); } if (dryRun) { context.tasks.push({ title: `${StudioCMSColorwayInfo.bold("--dry-run")} ${context.chalk.dim("Skipping user modification")}`, task: async (message) => { message("Modifying user... (skipped)"); } }); } else { context.tasks.push({ title: context.chalk.dim("Modifying user..."), task: async (message) => { try { const hashedPassword = await runEffect(hashPassword(newPassword)); await runEffect( db.execute( (tx) => tx.update(Users).set({ password: hashedPassword }).where(eq(Users.id, userSelection)) ) ); message("User modified successfully"); } catch (e) { if (e instanceof Error) { await runEffect(log.error(StudioCMSColorwayError(`Error: ${e.message}`))); await runEffect(context.exit(1)); } else { await runEffect( log.error(StudioCMSColorwayError("Unknown Error: Unable to modify user.")) ); await runEffect(context.exit(1)); } } } }); } break; } default: { return yield* context.pCancel(action); } } }); export { UserFieldOption, libsqlModifyUsers };