Replacing URLs by user ids in origins

This commit is contained in:
Eric van der Vlist 2023-03-04 16:07:22 +01:00
parent f07bf07c3f
commit c8644c8817
3 changed files with 92 additions and 43 deletions

View File

@ -4,6 +4,7 @@ import indexeddb from 'pouchdb-adapter-indexeddb';
import { sleep, until } from '../lib/async-wait';
import { isEqual } from 'lodash';
import { dbUrlToUserId } from '../lib/user-id';
PouchDB.plugin(indexeddb);
@ -109,53 +110,64 @@ export const watchDbLegacy = async () => {
const findDocumentsWithoutOrigin = async () => {
const allDocs = await db.allDocs({ include_docs: true });
return allDocs.rows
.filter((row: any) => !row.doc.origin)
.filter(
(row: any) =>
!row.doc.origin || !row.doc.origin.match(/^@([^>]+)>(.+)$/)
)
.map((row: any) => row.doc._id);
};
const updateDocumentsWithoutOrigin = async () => {
const documentsWithoutOrigin = await findDocumentsWithoutOrigin();
console.log({
caller: 'watchDbLegacy / addOrigin',
remoteUrl: state().remoteUrl,
nbDocumentsWithoutOrigin: documentsWithoutOrigin.length,
});
for (const docId of documentsWithoutOrigin) {
while (true) {
await sleep(100);
const doc = await db.get(docId);
console.log({
caller: 'watchDbLegacy / addOrigin',
remoteUrl: state().remoteUrl,
docId,
doc,
});
try {
db.put({ ...doc, origin: dbUrlToUserId(state().remoteUrl) });
break;
} catch (error) {
if (error.name === 'conflict') {
console.log({
caller: 'watchDbLegacy / addOrigin',
docId,
doc,
error,
});
} else {
console.error({
caller: 'watchDbLegacy / addOrigin',
docId,
doc,
error,
});
break;
}
}
}
}
};
if (!!state().remoteUrl) {
await updateDocumentsWithoutOrigin();
}
createEffect(async () => {
if (!!state().remoteUrl && remoteUrl() !== state().remoteUrl) {
setRemoteUrl(state().remoteUrl);
// Check documents and update without origin
const documentsWithoutOrigin = await findDocumentsWithoutOrigin();
console.log({
caller: 'watchDbLegacy / addOrigin',
remoteUrl: remoteUrl(),
nbDocumentsWithoutOrigin: documentsWithoutOrigin.length,
});
for (const docId of documentsWithoutOrigin) {
while (true) {
await sleep(100);
const doc = await db.get(docId);
console.log({
caller: 'watchDbLegacy / addOrigin',
remoteUrl: remoteUrl(),
docId,
doc,
});
try {
db.put({ ...doc, origin: remoteUrl() });
break;
} catch (error) {
if (error.name === 'conflict') {
console.log({
caller: 'watchDbLegacy / addOrigin',
docId,
doc,
error,
});
} else {
console.error({
caller: 'watchDbLegacy / addOrigin',
docId,
doc,
error,
});
break;
}
}
}
}
await updateDocumentsWithoutOrigin();
}
});

View File

@ -7,6 +7,7 @@ import { state } from '../db-admin/health-legacy';
import { lat2tile, lon2tile, rectanglesIntersect } from '../lib/geo';
import { findStartTime } from '../lib/gpx';
import getUri, { intToGpxId, intToTrkptId } from '../lib/ids';
import { dbUrlToUserId } from '../lib/user-id';
import { get, getDocsByType, getFamily, put, putAll } from './lib';
export const emptyGpx: Gpx = {
@ -127,7 +128,7 @@ const prune = (
_id: getUri(key, subId),
type: key,
to,
origin: state().remoteUrl,
origin: dbUrlToUserId(state().remoteUrl),
doc: subObjects[index],
});
prune(subId, subObjects[index], previousIds, {}, docs, to);
@ -202,14 +203,14 @@ export const pruneAndSaveImportedGpx = async (params: any) => {
{
_id: getUri('gpx', gpxId),
type: 'gpx',
origin: state().remoteUrl,
origin: dbUrlToUserId(state().remoteUrl),
doc: gpx,
// a new GPX isn't to...
},
{
_id: getUri('extensions', gpxId),
type: 'extensions',
origin: state().remoteUrl,
origin: dbUrlToUserId(state().remoteUrl),
doc: {},
},
];

36
src/lib/user-id.ts Normal file
View File

@ -0,0 +1,36 @@
export const userId = (params: { username: string; database: string }) => {
const { username, database } = params;
const dbUrl = new URL(database);
return `@${username}>${dbUrl.hostname}`;
};
export const parseUserId = (id: string) => {
const matches = id.match(/^@([^>]+)>(.+)$/);
if (!matches) {
return null;
}
return { username: matches[1], database: matches[2] };
};
function hex2a(hex: string) {
var str = '';
for (var i = 0; i < hex.length; i += 2) {
var v = parseInt(hex.substr(i, 2), 16);
if (v) str += String.fromCharCode(v);
}
return str;
}
export const parseDbUrl = (urlString: string) => {
origin;
const url = new URL(urlString);
const match = url.pathname.match(/\/userdb-(.*)\//);
if (!match || match.length < 2) {
return { username: '', database: url.hostname };
}
const [_, encodedUser] = match;
return { username: hex2a(encodedUser), database: urlString };
};
export const dbUrlToUserId = (urlString: string) =>
userId(parseDbUrl(urlString));