Added upsert for new users.

This commit is contained in:
Michael Mainguy 2023-11-06 09:44:32 -06:00
parent 8460470eb7
commit f51b5d9e7c
2 changed files with 80 additions and 23 deletions

View File

@ -7,6 +7,7 @@ const authToken = Buffer.from(auth).toString('base64');
function buildOptions(req: Request) { function buildOptions(req: Request) {
if (req.method == 'OPTIONS') { if (req.method == 'OPTIONS') {
const origin = req.headers['origin'];
return new Response( return new Response(
new Blob(), new Blob(),
{ {
@ -26,19 +27,17 @@ function buildOptions(req: Request) {
type Params = { type Params = {
username: string, username: string,
password: string password: string,
db: string
} }
async function checkIfDbExists(params: Params) { async function checkDB(auth: string, db: string) {
console.log("Checking if DB exists");
if (!params.username || !params.password) {
throw new Error('No share key provided');
}
try { try {
console.log('Checking for DB'); console.log('Checking for DB');
const exist = await axios.head(baseurl + params.username); const exist = await axios.head(baseurl + db,
if (exist) { {headers: {'Authorization': 'Basic ' + auth}});
if (exist && exist.status == 200) {
console.log("DB Found");
return true; return true;
} }
} catch (err) { } catch (err) {
@ -48,11 +47,38 @@ async function checkIfDbExists(params: Params) {
return false; 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<Access> {
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) { async function createDB(params: Params) {
console.log("Creating DB"); console.log("Creating DB");
const response = await axios.put( const response = await axios.put(
baseurl + params.username, baseurl + params.db,
{}, {},
{ {
headers: { headers: {
@ -67,6 +93,24 @@ async function createDB(params: Params) {
} }
async function createUser(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"); console.log("Creating User");
const userResponse = await axios.put( const userResponse = await axios.put(
baseurl + '_users/org.couchdb.user:' + params.username, baseurl + '_users/org.couchdb.user:' + params.username,
@ -88,7 +132,7 @@ async function createUser(params: Params) {
async function authorizeUser(params: Params) { async function authorizeUser(params: Params) {
console.log("Authorizing User"); console.log("Authorizing User");
return await axios.put( return await axios.put(
baseurl + params.username + '/_security', baseurl + params.db + '/_security',
{admins: {names: [], roles: []}, members: {names: [params.username], roles: []}}, {admins: {names: [], roles: []}, members: {names: [params.username], roles: []}},
{ {
headers: { headers: {
@ -101,7 +145,7 @@ async function authorizeUser(params: Params) {
export default async (req: Request, context: Context) => { export default async (req: Request, context: Context) => {
console.log(req.method); console.log(req.method);
const origin = req.headers['origin'];
const options = buildOptions(req); const options = buildOptions(req);
if (options) { if (options) {
return options; return options;
@ -110,23 +154,36 @@ export default async (req: Request, context: Context) => {
try { try {
const params = JSON.parse(await req.text()); const params = JSON.parse(await req.text());
console.log(params); 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); 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'); 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); const authorizeUserResponse = await authorizeUser(params);
if (authorizeUserResponse.status != 200) { if (authorizeUserResponse.status != 200) {
throw new Error('could not authorize user'); throw new Error('could not authorize user');
} }
const origin = req.headers['origin'];
return new Response( return new Response(
"OK", "OK",
{ {

View File

@ -217,7 +217,7 @@ export class PouchdbPersistenceManager implements IPersistenceManager {
if (dbs.data.indexOf(syncTarget) == -1) { if (dbs.data.indexOf(syncTarget) == -1) {
console.log('sync target missing'); console.log('sync target missing');
const buildTarget = await axios.post('https://deepdiagram.com/.netlify/functions/users', 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) { if (buildTarget.status != 200) {
console.log(buildTarget.statusText); console.log(buildTarget.statusText);
return; return;