add create account/blog functions

This commit is contained in:
sam 2023-07-20 19:15:07 +02:00
parent fec3c33310
commit cad4c59d51
Signed by: sam
GPG key ID: B4EF20DDE721CAA1
6 changed files with 367 additions and 7 deletions

29
src/db/account.ts Normal file
View file

@ -0,0 +1,29 @@
import { ulid } from "ulid";
import { hash } from "argon2";
import { Account } from "./entities/account.js";
import MercuryDataSource from "./index.js";
const missingAuthData = new Error("missing auth data for local user");
/** Creates a new account. */
export async function createAccount(
username: string,
host: string | null,
auth: { email: string; password: string } | null
) {
if (auth && (!auth.email || !auth.password)) throw missingAuthData;
const account = new Account();
account.id = ulid();
account.username = username;
account.host = host;
if (auth) {
account.email = auth.email;
account.password = await hash(auth.password);
}
await MercuryDataSource.getRepository(Account).save(account);
return account;
}

27
src/db/blog.ts Normal file
View file

@ -0,0 +1,27 @@
import { ulid } from "ulid";
import { Account } from "./entities/account.js";
import { Blog } from "./entities/blog.js";
import { generateKeyPair } from "./util/rsa.js";
import MercuryDataSource from "./index.js";
export const notLocalAccount = new Error("account is not local");
/** Create a local blog. Throws an error if the given account is not a local account. */
export async function createLocalBlog(account: Account, name: string) {
if (account.host) throw notLocalAccount;
const keyPair = await generateKeyPair();
const blog = new Blog();
blog.id = ulid();
blog.username = name;
blog.host = account.host;
blog.account = account;
blog.publicKey = keyPair.publicKey;
blog.privateKey = keyPair.privateKey;
await MercuryDataSource.getRepository(Blog).save(blog);
return blog;
}

20
src/db/util/rsa.ts Normal file
View file

@ -0,0 +1,20 @@
import * as crypto from "node:crypto";
import * as util from "node:util";
const generate = util.promisify(crypto.generateKeyPair);
export async function generateKeyPair() {
return await generate("rsa", {
modulusLength: 2048,
publicKeyEncoding: {
type: "spki",
format: "pem",
},
privateKeyEncoding: {
type: "pkcs8",
format: "pem",
cipher: undefined,
passphrase: undefined,
},
});
}

17
src/seed.ts Normal file
View file

@ -0,0 +1,17 @@
import MercuryDataSource from "./db/index.js";
import { createAccount } from "./db/account.js";
import { createLocalBlog } from "./db/blog.js";
import log from "./log.js";
// This just creates a single local user (that can't log in) called "testington", and one blog called "testington".
// This is not usable for anything more than testing a handful of endpoints, TODO: expand this
async function seed() {
await MercuryDataSource.initialize();
const account = await createAccount("testington", null, null);
const blog = await createLocalBlog(account, "testington");
log.info("Created account %s with blog %s", account.id, blog.id);
}
seed();