Skip to content

Commit

Permalink
Merge pull request #288 from desci-labs/collection-improvements
Browse files Browse the repository at this point in the history
Collection Improvements
  • Loading branch information
kadamidev authored Apr 18, 2024
2 parents 5dd4bdf + c74a2e4 commit 24fc5b4
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 3 deletions.
2 changes: 1 addition & 1 deletion desci-server/src/controllers/nodes/contributions/delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const deleteContributor = async (req: DeleteContributorRequest, res: Resp
const user = req.user;

if (!node || !user)
throw Error('Middleware not properly setup for addContributor controller, requires req.node and req.user');
throw Error('Middleware not properly setup for deleteContributor controller, requires req.node and req.user');

const { contributorId } = req.body;

Expand Down
106 changes: 106 additions & 0 deletions desci-server/src/controllers/nodes/sharedNodes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { IpldUrl, ResearchObjectV1Dpid } from '@desci-labs/desci-models';
import { User } from '@prisma/client';
import { Request, Response } from 'express';

import { prisma } from '../../client.js';
import { logger as parentLogger } from '../../logger.js';
import { PRIV_SHARE_CONTRIBUTION_PREFIX } from '../../services/Contributors.js';
import { getManifestFromNode } from '../../services/data/processing.js';
import { getIndexedResearchObjects } from '../../theGraph.js';

export type SharedNode = {
uuid: string;
manifestCid: string;
title?: string;
versions: number;
coverImageCid?: string | IpldUrl;
published?: boolean;
dpid?: ResearchObjectV1Dpid;
publishDate?: string;
shareKey: string;
};

export type ListSharedNodesRequest = Request<never, never> & {
user: User; // added by auth middleware
};

export type ListSharedNodesResBody =
| {
ok: boolean;
sharedNodes: SharedNode[];
}
| {
error: string;
};

export const listSharedNodes = async (req: ListSharedNodesRequest, res: Response<ListSharedNodesResBody>) => {
const user = req.user;

if (!user) throw Error('Middleware not properly setup for ListSharedNodes controller, requires req.user');

const logger = parentLogger.child({
module: 'PrivateShare::ListSharedNodesController',
body: req.body,
userId: user.id,
});

if (!user.email) {
logger.warn('User does not have an email, no nodes can be shared with the user.');
return res.status(500).json({ error: 'User does not have an email' });
}

try {
const privSharedNodes = await prisma.privateShare.findMany({
where: {
memo: `${PRIV_SHARE_CONTRIBUTION_PREFIX}${user.email}`,
},
include: {
node: true,
},
});

if (privSharedNodes?.length === 0) {
return res.status(200).json({ ok: true, sharedNodes: [] });
}

const nodeUuids = privSharedNodes.map((priv) => priv.node.uuid);
const { researchObjects } = await getIndexedResearchObjects(nodeUuids);
const publishedNodesMap = researchObjects.reduce((acc, ro) => {
// convert hex string to integer
const nodeUuidInt = Buffer.from(ro.id.substring(2), 'hex');
// convert integer to hex
const nodeUuid = nodeUuidInt.toString('base64url');
acc[nodeUuid] = ro;
}, {});

const filledSharedNodes = await Promise.all(
privSharedNodes.map(async (priv) => {
const { node } = priv;
const { manifest: latestManifest } = await getManifestFromNode(node);
const publishedEntry = publishedNodesMap[node.uuid];

return {
uuid: node.uuid,
manifestCid: node.manifestUrl,
title: latestManifest.title,
versions: publishedEntry?.versions.length,
coverImageCid: latestManifest.coverImage,
dpid: latestManifest.dpid,
publishDate: publishedEntry?.versions[0].time,
published: !!publishedEntry,
shareKey: priv.shareId,
};
}),
);

if (filledSharedNodes) {
logger.info({ totalSharedNodesFound: filledSharedNodes.length }, 'Shared nodes retrieved successfully');
return res.status(200).json({ ok: true, sharedNodes: filledSharedNodes });
}
} catch (e) {
logger.error({ e }, 'Failed to retrieve shared nodes for user');
return res.status(500).json({ error: 'Failed to retrieve shared nodes' });
}

return res.status(500).json({ error: 'Something went wrong' });
};
4 changes: 3 additions & 1 deletion desci-server/src/routes/v1/nodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { addContributor } from '../../controllers/nodes/contributions/create.js'
import { deleteContributor } from '../../controllers/nodes/contributions/delete.js';
import { getNodeContributions } from '../../controllers/nodes/contributions/getNodeContributions.js';
import { getUserContributions } from '../../controllers/nodes/contributions/getUserContributions.js';
import { getUserContributionsAuthed } from '../../controllers/nodes/contributions/getUserContributionsAuthed.js';
import { updateContributor } from '../../controllers/nodes/contributions/update.js';
import { verifyContribution } from '../../controllers/nodes/contributions/verify.js';
import { dispatchDocumentChange, getNodeDocument } from '../../controllers/nodes/documents.js';
Expand Down Expand Up @@ -32,12 +33,12 @@ import {
} from '../../controllers/nodes/index.js';
import { retrieveTitle } from '../../controllers/nodes/legacyManifestApi.js';
import { prepublish } from '../../controllers/nodes/prepublish.js';
import { listSharedNodes } from '../../controllers/nodes/sharedNodes.js';
import { thumbnails } from '../../controllers/nodes/thumbnails.js';
import { versionDetails } from '../../controllers/nodes/versionDetails.js';
import { asyncHander, attachUser, validate } from '../../internal.js';
import { ensureNodeAccess, ensureWriteNodeAccess } from '../../middleware/authorisation.js';
import { ensureUser } from '../../middleware/permissions.js';
import { getUserContributionsAuthed } from '../../controllers/nodes/contributions/getUserContributionsAuthed.js';

const router = Router();

Expand All @@ -60,6 +61,7 @@ router.get(
);
router.post('/terms', [ensureUser], consent);
router.get('/share/verify/:shareId', checkPrivateShareId);
router.get('/share', [ensureUser], listSharedNodes);
router.get('/share/:uuid', [ensureUser], getPrivateShare);
router.post('/share/:uuid', [ensureUser], createPrivateShare);
router.post('/revokeShare/:uuid', [ensureUser], revokePrivateShare);
Expand Down
2 changes: 1 addition & 1 deletion desci-server/src/services/Contributors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ export type AddNodeContributionParams = {
userId?: number;
};

const PRIV_SHARE_CONTRIBUTION_PREFIX = 'C-';
export const PRIV_SHARE_CONTRIBUTION_PREFIX = 'C-';

class ContributorService {
private logger = parentLogger.child({ module: 'Services::ContributorsService' });
Expand Down

0 comments on commit 24fc5b4

Please sign in to comment.