Implement CLI commands and admin API endpoints

- Add bootstrap command with direct DB access for initial setup
- Implement auth login/logout/status CLI commands
- Implement user create/confirm-email CLI commands
- Implement org create/list/add-site CLI commands
- Add admin.orgs.* and admin.users.* API endpoints
- Add password hashing utility with scrypt
- Add token hashing and authentication utility
- Add superuser runtime checks for admin endpoints
- Wrap multi-step operations in transactions
- Fix config file permissions (0o600) for security
- Remove token display from status command
- Add return statements to void handlers
- Add reviq CLI command to devenv

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
RevIQ
2026-01-09 15:30:10 +08:00
parent 30ee35b25c
commit 410b937f9f
20 changed files with 1267 additions and 85 deletions

View File

@@ -1,15 +1,46 @@
import type { LocalContext } from "../../context.js";
import { buildCommand } from "@stricli/core";
import { createApiClient } from "../../utils/api-client.js";
function confirmEmail(this: LocalContext): void {
console.log("User confirm-email command - Not implemented");
console.log("This command will confirm a user's email address");
interface ConfirmEmailFlags {
email: string;
}
async function confirmEmail(
this: LocalContext,
flags: ConfirmEmailFlags,
): Promise<void> {
try {
const client = await createApiClient();
await client.call("admin.users.confirmEmail", {
email: flags.email,
});
console.log(`Confirmed email for: ${flags.email}`);
} catch (error) {
console.error(
"Error:",
error instanceof Error ? error.message : String(error),
);
this.process.exit(1);
}
}
export const confirmEmailCommand = buildCommand({
func: confirmEmail,
parameters: {},
parameters: {
flags: {
email: {
kind: "parsed",
parse: String,
brief: "Email address to confirm",
},
},
},
docs: {
brief: "Confirm user email",
fullDescription:
"Confirms a user's email address via the admin API. This is useful for development when email sending is not configured.",
},
});

View File

@@ -1,15 +1,72 @@
import type { LocalContext } from "../../context.js";
import { buildCommand } from "@stricli/core";
import { createApiClient } from "../../utils/api-client.js";
function create(this: LocalContext): void {
console.log("User create command - Not implemented");
console.log("This command will create a new user account");
interface CreateUserFlags {
email: string;
name?: string;
org?: string;
role?: string;
}
async function create(
this: LocalContext,
flags: CreateUserFlags,
): Promise<void> {
try {
const client = await createApiClient();
await client.call("admin.users.create", {
email: flags.email,
name: flags.name,
orgSlug: flags.org,
orgRole: flags.role,
});
console.log(`Created user: ${flags.email}`);
if (flags.org) {
console.log(`Added to org: ${flags.org} as ${flags.role ?? "member"}`);
}
} catch (error) {
console.error(
"Error:",
error instanceof Error ? error.message : String(error),
);
this.process.exit(1);
}
}
export const createCommand = buildCommand({
func: create,
parameters: {},
parameters: {
flags: {
email: {
kind: "parsed",
parse: String,
brief: "Email address for the new user",
},
name: {
kind: "parsed",
parse: String,
brief: "Display name for the user",
optional: true,
},
org: {
kind: "parsed",
parse: String,
brief: "Org slug to add the user to",
optional: true,
},
role: {
kind: "parsed",
parse: String,
brief: "Role in the org (owner, admin, member)",
optional: true,
},
},
},
docs: {
brief: "Create a new user",
fullDescription: "Creates a new user account via the admin API.",
},
});