Creating replication documents when needed
This commit is contained in:
parent
b7dd6aa15a
commit
d6538843d2
|
@ -19,6 +19,8 @@ import { isFunction } from 'lodash';
|
||||||
import { userId } from '~/lib/user-id';
|
import { userId } from '~/lib/user-id';
|
||||||
import { userExists } from '~/lib/user-exists';
|
import { userExists } from '~/lib/user-exists';
|
||||||
import { update } from '~/lib/update';
|
import { update } from '~/lib/update';
|
||||||
|
import { replicationDocument } from '~/lib/replication-document';
|
||||||
|
import { get } from '~/lib/get';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
values?: () => any;
|
values?: () => any;
|
||||||
|
@ -114,6 +116,10 @@ const User: Component<Props> = (props) => {
|
||||||
database,
|
database,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const currentUserId = userId(data('username'), data('database'));
|
||||||
|
const credentials = adminCredentials();
|
||||||
|
const adminUser = credentials?.username || '';
|
||||||
|
|
||||||
for (let i = 0; i < updatedSubscriptions.length; i++) {
|
for (let i = 0; i < updatedSubscriptions.length; i++) {
|
||||||
let subscription = updatedSubscriptions[i];
|
let subscription = updatedSubscriptions[i];
|
||||||
if (!isIn(subscription.username, previousSubscriptions())) {
|
if (!isIn(subscription.username, previousSubscriptions())) {
|
||||||
|
@ -122,6 +128,24 @@ const User: Component<Props> = (props) => {
|
||||||
addSubscriptionFactory(subscription.username),
|
addSubscriptionFactory(subscription.username),
|
||||||
defaultUserDocument
|
defaultUserDocument
|
||||||
);
|
);
|
||||||
|
const otherUserId = userId(subscription.username, data('database'));
|
||||||
|
const otherUserPassword = (await get(otherUserId)).password;
|
||||||
|
let repDocument = replicationDocument(
|
||||||
|
currentUserId,
|
||||||
|
data('password'),
|
||||||
|
otherUserId,
|
||||||
|
otherUserPassword,
|
||||||
|
adminUser
|
||||||
|
);
|
||||||
|
await put(repDocument._id, repDocument, false, '_replicator');
|
||||||
|
repDocument = replicationDocument(
|
||||||
|
otherUserId,
|
||||||
|
otherUserPassword,
|
||||||
|
currentUserId,
|
||||||
|
data('password'),
|
||||||
|
adminUser
|
||||||
|
);
|
||||||
|
await put(repDocument._id, repDocument, false, '_replicator');
|
||||||
console.log({
|
console.log({
|
||||||
caller: 'User / submitHandler / new subscription',
|
caller: 'User / submitHandler / new subscription',
|
||||||
username: subscription.username,
|
username: subscription.username,
|
||||||
|
@ -139,6 +163,7 @@ const User: Component<Props> = (props) => {
|
||||||
removeSubscriptionFactory(subscription.username),
|
removeSubscriptionFactory(subscription.username),
|
||||||
defaultUserDocument
|
defaultUserDocument
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log({
|
console.log({
|
||||||
caller: 'User / submitHandler / deleted subscription',
|
caller: 'User / submitHandler / deleted subscription',
|
||||||
username: subscription.username,
|
username: subscription.username,
|
||||||
|
@ -269,7 +294,7 @@ const User: Component<Props> = (props) => {
|
||||||
<Progress.Root
|
<Progress.Root
|
||||||
value={progress()}
|
value={progress()}
|
||||||
minValue={0}
|
minValue={0}
|
||||||
maxValue={10}
|
maxValue={3}
|
||||||
getValueLabel={({ value, max }) =>
|
getValueLabel={({ value, max }) =>
|
||||||
`${value} of ${max} tasks completed`
|
`${value} of ${max} tasks completed`
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
import { toHex } from './to-hex';
|
||||||
|
|
||||||
|
export const getDbUrlForUser = (user: { username: string; hostname: string }) =>
|
||||||
|
`https://${user.hostname}/userdb-${toHex(user.username)}`;
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { parseUserId } from './user-id';
|
||||||
|
import { getDbUrlForUser } from './get-db-url-for-user';
|
||||||
|
|
||||||
|
export const replicationDocument = (
|
||||||
|
userFromId: string,
|
||||||
|
userFromPassword: string,
|
||||||
|
userToId: string,
|
||||||
|
userToPassword: string,
|
||||||
|
adminUser: string
|
||||||
|
) => {
|
||||||
|
const userFrom = parseUserId(userFromId);
|
||||||
|
const userTo = parseUserId(userToId);
|
||||||
|
|
||||||
|
const document = {
|
||||||
|
_id: `${userFromId}=>${userToId}`,
|
||||||
|
user_ctx: {
|
||||||
|
name: adminUser,
|
||||||
|
roles: ['_admin', '_reader', '_writer'],
|
||||||
|
},
|
||||||
|
source: {
|
||||||
|
url: getDbUrlForUser(userFrom),
|
||||||
|
auth: {
|
||||||
|
basic: {
|
||||||
|
username: userFrom.username,
|
||||||
|
password: userFromPassword,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
target: {
|
||||||
|
url: getDbUrlForUser(userTo),
|
||||||
|
auth: {
|
||||||
|
basic: {
|
||||||
|
username: userTo.username,
|
||||||
|
password: userToPassword,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
selector: {
|
||||||
|
to: {
|
||||||
|
$elemMatch: {
|
||||||
|
$eq: userToId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
create_target: false,
|
||||||
|
continuous: true,
|
||||||
|
owner: adminUser,
|
||||||
|
};
|
||||||
|
|
||||||
|
return document;
|
||||||
|
};
|
|
@ -0,0 +1,24 @@
|
||||||
|
import { get } from './get';
|
||||||
|
import { put } from './put';
|
||||||
|
|
||||||
|
export const update = async (
|
||||||
|
id: string,
|
||||||
|
updater: (doc: any) => any,
|
||||||
|
defaultDocument: any,
|
||||||
|
db = 'dyomedea_users'
|
||||||
|
) => {
|
||||||
|
const previous = await get(id, db);
|
||||||
|
|
||||||
|
const newDocument = updater(previous || defaultDocument);
|
||||||
|
|
||||||
|
console.log({
|
||||||
|
caller: 'update',
|
||||||
|
id,
|
||||||
|
defaultDocument,
|
||||||
|
db,
|
||||||
|
previous,
|
||||||
|
newDocument,
|
||||||
|
});
|
||||||
|
|
||||||
|
return await put(id, newDocument, false, db);
|
||||||
|
};
|
|
@ -0,0 +1,30 @@
|
||||||
|
import { adminCredentials } from '~/components/credentials';
|
||||||
|
import { headersWithAuth } from './headers-with-auth';
|
||||||
|
|
||||||
|
export const userExists = async (username: string) => {
|
||||||
|
const credentials = adminCredentials();
|
||||||
|
if (!credentials) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const { database } = credentials;
|
||||||
|
|
||||||
|
const headers = headersWithAuth();
|
||||||
|
if (!headers) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
`${database}/_users/org.couchdb.user:${username}`,
|
||||||
|
{
|
||||||
|
method: 'HEAD',
|
||||||
|
mode: 'cors',
|
||||||
|
headers,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return response.status === 200;
|
||||||
|
} catch (error) {
|
||||||
|
console.error({ caller: 'userExists', error });
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue