CLI sqlite migratior

This commit is contained in:
hgw 2023-12-03 02:09:53 +00:00
parent 72fabd5346
commit 42e08dec93
Signed by: hgw
SSH Key Fingerprint: SHA256:diG7RVYHjd3aDYkZWHYcBJbImu+6zfptuUP+3k/wol4
3 changed files with 99 additions and 16 deletions

View File

@ -112,7 +112,11 @@ class ClientManager {
if (client) { if (client) {
client.quit(true); client.quit(true);
this.clients = _.without(this.clients, client); this.clients = _.without(this.clients, client);
log.info(`User ${colors.bold(name)} disconnected and removed.`); log.info(
`User ${colors.bold(
name
)} disconnected and removed.`
);
} }
}); });
}, },
@ -197,7 +201,8 @@ class ClientManager {
if ( if (
userFolderStat && userFolderStat &&
userFileStat && userFileStat &&
(userFolderStat.uid !== userFileStat.uid || userFolderStat.gid !== userFileStat.gid) (userFolderStat.uid !== userFileStat.uid ||
userFolderStat.gid !== userFileStat.gid)
) { ) {
log.warn( log.warn(
`User ${colors.green( `User ${colors.green(
@ -227,7 +232,10 @@ class ClientManager {
networks: client.networks.map((n) => n.export()), networks: client.networks.map((n) => n.export()),
}); });
const newUser = JSON.stringify(json, null, "\t"); const newUser = JSON.stringify(json, null, "\t");
const newHash = crypto.createHash("sha256").update(newUser).digest("hex"); const newHash = crypto
.createHash("sha256")
.update(newUser)
.digest("hex");
return { newUser, newHash }; return { newUser, newHash };
} }
@ -254,7 +262,9 @@ class ClientManager {
return callback ? callback() : true; return callback ? callback() : true;
} catch (e: any) { } catch (e: any) {
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
log.error(`Failed to update user ${colors.green(client.name)} (${e})`); log.error(
`Failed to update user ${colors.green(client.name)} (${e})`
);
if (callback) { if (callback) {
callback(e); callback(e);
@ -266,7 +276,9 @@ class ClientManager {
const userPath = Config.getUserConfigPath(name); const userPath = Config.getUserConfigPath(name);
if (!fs.existsSync(userPath)) { if (!fs.existsSync(userPath)) {
log.error(`Tried to remove non-existing user ${colors.green(name)}.`); log.error(
`Tried to remove non-existing user ${colors.green(name)}.`
);
return false; return false;
} }
@ -275,7 +287,7 @@ class ClientManager {
return true; return true;
} }
private readUserConfig(name: string) { readUserConfig(name: string) {
const userPath = Config.getUserConfigPath(name); const userPath = Config.getUserConfigPath(name);
if (!fs.existsSync(userPath)) { if (!fs.existsSync(userPath)) {

View File

@ -42,6 +42,7 @@ program.addCommand(require("./install").default);
program.addCommand(require("./uninstall").default); program.addCommand(require("./uninstall").default);
program.addCommand(require("./upgrade").default); program.addCommand(require("./upgrade").default);
program.addCommand(require("./outdated").default); program.addCommand(require("./outdated").default);
program.addCommand(require("./storage").default);
if (!Config.values.public) { if (!Config.values.public) {
require("./users").default.forEach((command: Command) => { require("./users").default.forEach((command: Command) => {
@ -99,7 +100,9 @@ function verifyFileOwner() {
); );
} }
const configStat = fs.statSync(path.join(Config.getHomePath(), "config.js")); const configStat = fs.statSync(
path.join(Config.getHomePath(), "config.js")
);
if (configStat && configStat.uid !== uid) { if (configStat && configStat.uid !== uid) {
log.warn( log.warn(

View File

@ -0,0 +1,68 @@
import log from "../log";
import { Command } from "commander";
import ClientManager from "../clientManager";
import Utils from "./utils";
import SqliteMessageStorage from "../plugins/messageStorage/sqlite";
const program = new Command("storage").description(
"various utilities related to the message storage"
);
program
.command("migrate")
.argument("[user]", "migrate a specific user only, all if not provided")
.description("Migrate message storage where needed")
.on("--help", Utils.extraHelp)
.action(function (user) {
runMigrations(user).catch((err) => {
log.error(err.toString());
process.exit(1);
});
});
async function runMigrations(user: string) {
const manager = new ClientManager();
const users = manager.getUsers();
if (user) {
if (!users.includes(user)) {
throw new Error(`invalid user ${user}`);
}
return migrateUser(manager, user);
}
for (const name of users) {
await migrateUser(manager, name);
// if any migration fails we blow up,
// chances are the rest won't complete either
}
}
// runs sqlite migrations for a user, which must exist
async function migrateUser(manager: ClientManager, user: string) {
log.info("handling user", user);
if (!isUserLogEnabled(manager, user)) {
log.info("logging disabled for user", user, ". Skipping");
return;
}
const sqlite = new SqliteMessageStorage(user);
await sqlite.enable(); // enable runs migrations
await sqlite.close();
log.info("user", user, "migrated successfully");
}
function isUserLogEnabled(manager: ClientManager, user: string): boolean {
const conf = manager.readUserConfig(user);
if (!conf) {
log.error("Could not open user configuration of", user);
return false;
}
return conf.log;
}
export default program;