diff --git a/netlify/functions/users/users.mts b/netlify/functions/users/users.mts index 84993cf..c5ece37 100644 --- a/netlify/functions/users/users.mts +++ b/netlify/functions/users/users.mts @@ -7,6 +7,7 @@ const authToken = Buffer.from(auth).toString('base64'); function buildOptions(req: Request) { if (req.method == 'OPTIONS') { + const origin = req.headers['origin']; return new Response( new Blob(), { @@ -26,19 +27,17 @@ function buildOptions(req: Request) { type Params = { username: string, - password: string + password: string, + db: string } -async function checkIfDbExists(params: Params) { - console.log("Checking if DB exists"); - - if (!params.username || !params.password) { - throw new Error('No share key provided'); - } +async function checkDB(auth: string, db: string) { try { console.log('Checking for DB'); - const exist = await axios.head(baseurl + params.username); - if (exist) { + const exist = await axios.head(baseurl + db, + {headers: {'Authorization': 'Basic ' + auth}}); + if (exist && exist.status == 200) { + console.log("DB Found"); return true; } } catch (err) { @@ -48,11 +47,38 @@ async function checkIfDbExists(params: Params) { return false; } +enum Access { + DENIED, + MISSING, + ALLOWED, +} + +function getUserToken(params: Params) { + const userAuth = params.username + ':' + params.password; + return Buffer.from(userAuth).toString('base64'); +} + +async function checkIfDbExists(params: Params): Promise { + console.log("Checking if DB exists"); + if (!params.username || !params.password || !params.db) { + throw new Error('No share key provided'); + } + + if (await checkDB(getUserToken(params), params.db)) { + return Access.ALLOWED; + } + if (await checkDB(authToken, params.db)) { + return Access.DENIED; + } + return Access.MISSING; + +} + async function createDB(params: Params) { console.log("Creating DB"); const response = await axios.put( - baseurl + params.username, + baseurl + params.db, {}, { headers: { @@ -67,6 +93,24 @@ async function createDB(params: Params) { } async function createUser(params: Params) { + try { + console.log("Checking for User"); + const userResponse = await axios.head( + baseurl + '_users/org.couchdb.user:' + params.username, + { + headers: { + 'Authorization': 'Basic ' + getUserToken(params), + 'Content-Type': 'application/json', + 'Accept': 'application/json' + } + }); + if (userResponse.status == 200) { + console.log("User Found"); + return userResponse; + } + } catch (err) { + console.log("User Missing"); + } console.log("Creating User"); const userResponse = await axios.put( baseurl + '_users/org.couchdb.user:' + params.username, @@ -88,7 +132,7 @@ async function createUser(params: Params) { async function authorizeUser(params: Params) { console.log("Authorizing User"); return await axios.put( - baseurl + params.username + '/_security', + baseurl + params.db + '/_security', {admins: {names: [], roles: []}, members: {names: [params.username], roles: []}}, { headers: { @@ -101,7 +145,7 @@ async function authorizeUser(params: Params) { export default async (req: Request, context: Context) => { console.log(req.method); - const origin = req.headers['origin']; + const options = buildOptions(req); if (options) { return options; @@ -110,23 +154,36 @@ export default async (req: Request, context: Context) => { try { const params = JSON.parse(await req.text()); console.log(params); - const exists = await checkIfDbExists(params); - if (exists) { - return new Response("OK"); - } - const createDbResponse = await createDB(params); - if (createDbResponse.status != 201) { - throw new Error('Could not create DB'); - } const createUserResponse = await createUser(params); - if (createUserResponse.status != 201) { + console.log(createUserResponse.status); + if (createUserResponse.status != 201 && createUserResponse.status != 200) { throw new Error('Could not create User'); } + + const exists = await checkIfDbExists(params); + switch (exists) { + case Access.ALLOWED: + return new Response("OK"); + case Access.DENIED: + if (exists == Access.DENIED) { + return new Response("Denied", {status: 401}); + } + case Access.MISSING: + if (exists == Access.MISSING) { + const createDbResponse = await createDB(params); + if (createDbResponse.status != 201) { + throw new Error('Could not create DB'); + } + } + + } + + const authorizeUserResponse = await authorizeUser(params); if (authorizeUserResponse.status != 200) { throw new Error('could not authorize user'); } - + const origin = req.headers['origin']; return new Response( "OK", { diff --git a/src/integration/pouchdbPersistenceManager.ts b/src/integration/pouchdbPersistenceManager.ts index 632342f..249d487 100644 --- a/src/integration/pouchdbPersistenceManager.ts +++ b/src/integration/pouchdbPersistenceManager.ts @@ -217,7 +217,7 @@ export class PouchdbPersistenceManager implements IPersistenceManager { if (dbs.data.indexOf(syncTarget) == -1) { console.log('sync target missing'); const buildTarget = await axios.post('https://deepdiagram.com/.netlify/functions/users', - {username: syncTarget, password: 'password'}); + {username: syncTarget, password: 'password', db: syncTarget}); if (buildTarget.status != 200) { console.log(buildTarget.statusText); return;