admin passwordHash import support
This commit is contained in:
parent
8f540164df
commit
d767346345
2 changed files with 35 additions and 7 deletions
19
README.md
19
README.md
|
|
@ -336,7 +336,7 @@ Secrets/credentials in the config file can reference environment variables using
|
||||||
|
|
||||||
##### Admin Setup (Automated)
|
##### Admin Setup (Automated)
|
||||||
|
|
||||||
- **Example:**
|
- **Example (new instance):**
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"admin": {
|
"admin": {
|
||||||
|
|
@ -346,11 +346,26 @@ Secrets/credentials in the config file can reference environment variables using
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- **Example (migration from another instance):**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"admin": {
|
||||||
|
"username": "admin",
|
||||||
|
"passwordHash": "$argon2id$v=19$m=19456,t=2,p=1$...",
|
||||||
|
"recoveryKey": "${RECOVERY_KEY}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
- **Fields:**
|
- **Fields:**
|
||||||
- `username`: Admin username to create on first startup
|
- `username`: Admin username to create on first startup
|
||||||
- `password`: Admin password (can use `${ENV_VAR}`)
|
- `password`: Admin password for new instances (can use `${ENV_VAR}`)
|
||||||
|
- `passwordHash`: Pre-hashed password for migration (exported from another instance)
|
||||||
- `recoveryKey`: Optional recovery key (can use `${ENV_VAR}`) - if provided, the UI prompt to download recovery key will be skipped
|
- `recoveryKey`: Optional recovery key (can use `${ENV_VAR}`) - if provided, the UI prompt to download recovery key will be skipped
|
||||||
|
|
||||||
|
> **Note:** Use either `password` OR `passwordHash`, not both. The `passwordHash` option is useful when migrating from another Zerobyte instance using an exported config with `includePasswordHash=true`.
|
||||||
|
|
||||||
**On first startup, Zerobyte will automatically create the admin user from the config file.**
|
**On first startup, Zerobyte will automatically create the admin user from the config file.**
|
||||||
|
|
||||||
> **⚠️ About the Recovery Key**
|
> **⚠️ About the Recovery Key**
|
||||||
|
|
|
||||||
|
|
@ -176,17 +176,30 @@ export const startup = async () => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { authService } = await import("../auth/auth.service");
|
const { authService } = await import("../auth/auth.service");
|
||||||
if (configFileAdmin && configFileAdmin.username && configFileAdmin.password) {
|
if (configFileAdmin && configFileAdmin.username && (configFileAdmin.password || configFileAdmin.passwordHash)) {
|
||||||
const hasUsers = await authService.hasUsers();
|
const hasUsers = await authService.hasUsers();
|
||||||
if (!hasUsers) {
|
if (!hasUsers) {
|
||||||
const { user } = await authService.register(configFileAdmin.username, configFileAdmin.password);
|
let userId: number;
|
||||||
logger.info(`Admin user '${configFileAdmin.username}' created from config.`);
|
if (configFileAdmin.passwordHash) {
|
||||||
|
// Import with existing password hash (migration from another instance)
|
||||||
|
const [user] = await db.insert(usersTable).values({
|
||||||
|
username: configFileAdmin.username,
|
||||||
|
passwordHash: configFileAdmin.passwordHash,
|
||||||
|
}).returning();
|
||||||
|
userId = user.id;
|
||||||
|
logger.info(`Admin user '${configFileAdmin.username}' imported with password hash from config.`);
|
||||||
|
} else {
|
||||||
|
// Create new user with plaintext password
|
||||||
|
const { user } = await authService.register(configFileAdmin.username, configFileAdmin.password);
|
||||||
|
userId = user.id;
|
||||||
|
logger.info(`Admin user '${configFileAdmin.username}' created from config.`);
|
||||||
|
}
|
||||||
if (configFileAdmin.recoveryKey) {
|
if (configFileAdmin.recoveryKey) {
|
||||||
await db.update(usersTable).set({ hasDownloadedResticPassword: true }).where(eq(usersTable.id, user.id));
|
await db.update(usersTable).set({ hasDownloadedResticPassword: true }).where(eq(usersTable.id, userId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.warn("Admin config missing required fields (username, password). Skipping automated admin setup.");
|
logger.warn("Admin config missing required fields (username, password or passwordHash). Skipping automated admin setup.");
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const e = err instanceof Error ? err : new Error(String(err));
|
const e = err instanceof Error ? err : new Error(String(err));
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue