studiocms
Version:
Astro Native CMS for AstroDB. Built from the ground up by the Astro community.
206 lines (205 loc) • 7.71 kB
JavaScript
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
};