diff --git a/account/src/lib/couch-db.ts b/account/src/lib/couch-db.ts index 4c53e66..6889c6c 100644 --- a/account/src/lib/couch-db.ts +++ b/account/src/lib/couch-db.ts @@ -63,6 +63,14 @@ export async function deleteLingdocsUser(uuid: T.UUID): Promise { await usersDb.destroy(user._id as string, user._rev as string); } +export async function deleteCouchDbAuthUser(uuid: T.UUID): Promise { + const authUsers = nano.db.use("_users"); + const user = await authUsers.find({ selector: { name: uuid }}); + if (!user.docs.length) return; + const u = user.docs[0]; + await authUsers.destroy(u._id, u._rev); +} + // TODO: TO MAKE THIS SAFER, PASS IN JUST THE UPDATING FIELDS!! // TODO: take out the updated object - do just an ID, and then use the toUpdate safe thing export async function updateLingdocsUser(uuid: T.UUID, toUpdate: @@ -103,8 +111,19 @@ export async function updateLingdocsUser(uuid: T.UUID, toUpdate: }); } -export async function createWordlistDatabase(uuid: T.UUID): Promise<{ name: T.WordlistDbName, password: T.UserDbPassword }> { +export async function addCouchDbAuthUser(uuid: T.UUID): Promise<{ password: T.UserDbPassword }> { const password = generateWordlistDbPassword(); + const usersDb = nano.db.use("_users"); + const authUser: T.CouchDbAuthUser = { + name: uuid, + password, + }; + await usersDb.insert(authUser); + return { password }; +} + +export async function createWordlistDatabase(uuid: T.UUID, password: T.UserDbPassword): Promise<{ name: T.WordlistDbName, password: T.UserDbPassword }> { + const name = getWordlistDbName(uuid); // create wordlist database for user await nano.db.create(name); diff --git a/account/src/routers/api-router.ts b/account/src/routers/api-router.ts index 338ff39..4376367 100644 --- a/account/src/routers/api-router.ts +++ b/account/src/routers/api-router.ts @@ -5,6 +5,8 @@ import { updateLingdocsUser, createWordlistDatabase, deleteWordlistDatabase, + addCouchDbAuthUser, + deleteCouchDbAuthUser, } from "../lib/couch-db"; import { getHash, @@ -116,7 +118,11 @@ apiRouter.put("/user/upgrade", async (req, res, next) => { res.send(alreadyUpgraded); return; } - const { name, password } = await createWordlistDatabase(userId); + // add user to couchdb authentication db + const { password } = await addCouchDbAuthUser(userId); + // create user db + const { name } = await createWordlistDatabase(userId, password); + // update LingdocsUser const u = await updateLingdocsUser(userId, { level: "student", wordlistDbName: name, userDbPassword: password }); const upgraded: T.UpgradeUserResponse = { ok: true, @@ -135,8 +141,9 @@ apiRouter.put("/user/upgrade", async (req, res, next) => { apiRouter.delete("/user", async (req, res, next) => { try { if (!req.user) throw new Error("user not found"); - await deleteWordlistDatabase(req.user.userId), - await deleteLingdocsUser(req.user.userId), + await deleteWordlistDatabase(req.user.userId); + await deleteCouchDbAuthUser(req.user.userId); + await deleteLingdocsUser(req.user.userId); sendResponse(res, { ok: true, message: "user deleted" }); } catch (e) { next(e); diff --git a/website/src/lib/account-types.ts b/website/src/lib/account-types.ts index 1a5e8d4..3ab17c7 100644 --- a/website/src/lib/account-types.ts +++ b/website/src/lib/account-types.ts @@ -43,6 +43,11 @@ export type LingdocsUser = { } ) & import("nano").MaybeDocument; +export type CouchDbAuthUser = { + name: UUID, + password: UserDbPassword, +} & import("nano").MaybeDocument; + export type UpgradeUserResponse = { ok: false, error: "incorrect password",