Skip to content

Commit

Permalink
Merge branch 'develop' into cover-page-api
Browse files Browse the repository at this point in the history
  • Loading branch information
hubsmoke authored Jun 6, 2024
2 parents 070d4ba + c1485ba commit 40963c7
Show file tree
Hide file tree
Showing 43 changed files with 748 additions and 132 deletions.
7 changes: 7 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,10 @@ DPID_URL_OVERRIDE=https://dev-beta.dpid.org
MUTE_PUBLISH_WORKER=false
# SingleNodeLockServce
MAX_LOCK_TIME=3600 # 1 hour

DOI_PREFIX=https://doi.org/10.62891

# Cross ref api
CROSSREF_API=https://api.crossref.org
CROSSREF_API_KEY=
CROSSREF_EMAIL=
9 changes: 8 additions & 1 deletion .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,11 @@ VSCODE_ACCESS_TOKEN=
NODES_MEDIA_SERVER_URL=http://host.docker.internal:5454

REPO_SERVICE_SECRET_KEY="m8sIy5BPygBcX3+ZmMVuAA10k6w59BSCZd+Z5+VLYm4="
REPO_SERVER_URL=http://host.docker.internal:5485
REPO_SERVER_URL=http://host.docker.internal:5485

DOI_PREFIX=https://doi.org/10.62891

# Cross ref api
CROSSREF_API=https://api.crossref.org
CROSSREF_API_KEY=
CROSSREF_EMAIL=
19 changes: 10 additions & 9 deletions .github/workflows/deploy-staging-services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ env:
CONTAINER_IMAGE_REPO: desci-repo-server
CONTAINER_IMAGE_MEDIA: nodes-media-server
CONTAINER_IMAGE_ISOLATED: desci-media-isolated
CONTAINER_IMAGE_PROXY: "reverse-proxy"
DOCKER_BUILDKIT: 1

jobs:
Expand Down Expand Up @@ -294,23 +295,23 @@ jobs:
run: |
# Build and tag the image
docker build \
-t $CONTAINER_IMAGE-staging:latest \
-t $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE-staging \
./$CONTAINER_IMAGE
-t $CONTAINER_IMAGE_PROXY-staging:latest \
-t $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE_PROXY-staging \
./$CONTAINER_IMAGE_PROXY
- name: Push (STAGING)
run: |
# Push image to AWS ECR
aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
docker tag $CONTAINER_IMAGE-staging:latest $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE-staging:${{ github.sha }}
docker tag $CONTAINER_IMAGE-staging:latest $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE-staging:latest
docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE-staging:${{ github.sha }}
docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE-staging:latest
docker tag $CONTAINER_IMAGE_PROXY-staging:latest $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE_PROXY-staging:${{ github.sha }}
docker tag $CONTAINER_IMAGE_PROXY-staging:latest $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE_PROXY-staging:latest
docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE_PROXY-staging:${{ github.sha }}
docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE_PROXY-staging:latest
- name: Deploy to EKS (STAGING)
run: | # defaults to latest kubectl binary version
kubectl apply -f $CONTAINER_IMAGE/deployment.yaml
kubectl set image deployment/reverse-proxy-staging reverse-proxy-staging=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE-staging:${{ github.sha }} --record
kubectl apply -f $CONTAINER_IMAGE_PROXY/deployment.yaml
kubectl set image deployment/reverse-proxy-staging reverse-proxy-staging=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$CONTAINER_IMAGE_PROXY-staging:${{ github.sha }} --record
- name: Verify EKS Deployment (STAGING)
run: |
Expand Down
2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"explorer.compactFolders": false,
"files.exclude": {
"**/node_modules/**": true
"**/node_modules/**": false
},
"editor.formatOnSave": true, // Tell VSCode to format files on save
"editor.defaultFormatter": "esbenp.prettier-vscode",
Expand Down
5 changes: 5 additions & 0 deletions desci-server/kubernetes/deployment_dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ spec:
export SESSION_KEY={{ .Data.SESSION_KEY }}
export COOKIE_DOMAIN={{ .Data.COOKIE_DOMAIN }}
export ORCID_API_DOMAIN={{ .Data.ORCID_API_DOMAIN }}
export DPID_URL_OVERRIDE={{ .Data.DPID_URL_OVERRIDE }}
export ORCID_CLIENT_ID={{ .Data.ORCID_CLIENT_ID }}
export ORCID_CLIENT_SECRET={{ .Data.ORCID_CLIENT_SECRET }}
export ARWEAVE_ENABLED=0
Expand Down Expand Up @@ -78,6 +79,10 @@ spec:
export IPFS_READ_ONLY_GATEWAY_SERVER_URL={{ .Data.IPFS_READ_ONLY_GATEWAY_SERVER_URL }}
export ETHEREUM_RPC_URL={{ .Data.ETHEREUM_RPC_URL }}
export GOOGLE_CLIENT_ID={{ .Data.GOOGLE_CLIENT_ID }}
export DOI_PREFIX={{ .Data.DOI_PREFIX }}
export CROSSREF_API={{ .Data.CROSSREF_API }}
export CROSSREF_API_KEY={{ .Data.CROSSREF_API_KEY }}
export CROSSREF_EMAIL={{ .Data.CROSSREF_EMAIL }}
export DEBUG_TEST=0;
echo "appfinish";
{{- end -}}
Expand Down
5 changes: 5 additions & 0 deletions desci-server/kubernetes/deployment_prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ spec:
export ORCID_API_DOMAIN={{ .Data.ORCID_API_DOMAIN }}
export ORCID_CLIENT_ID={{ .Data.ORCID_CLIENT_ID }}
export ORCID_CLIENT_SECRET={{ .Data.ORCID_CLIENT_SECRET }}
export DPID_URL_OVERRIDE={{ .Data.DPID_URL_OVERRIDE }}
export ARWEAVE_ENABLED=0
export ARWEAVE_HOST=
export ARWEAVE_PORT=1984
Expand Down Expand Up @@ -78,6 +79,10 @@ spec:
export IPFS_READ_ONLY_GATEWAY_SERVER_URL={{ .Data.IPFS_READ_ONLY_GATEWAY_SERVER_URL }}
export ETHEREUM_RPC_URL={{ .Data.ETHEREUM_RPC_URL }}
export GOOGLE_CLIENT_ID={{ .Data.GOOGLE_CLIENT_ID }}
export DOI_PREFIX={{ .Data.DOI_PREFIX }}
export CROSSREF_API={{ .Data.CROSSREF_API }}
export CROSSREF_API_KEY={{ .Data.CROSSREF_API_KEY }}
export CROSSREF_EMAIL={{ .Data.CROSSREF_EMAIL }}
export IGNORE_LINE=0;
export DEBUG_TEST=0;
echo "appfinish";
Expand Down
5 changes: 5 additions & 0 deletions desci-server/kubernetes/deployment_staging.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ spec:
export ORCID_API_DOMAIN={{ .Data.ORCID_API_DOMAIN }}
export ORCID_CLIENT_ID={{ .Data.ORCID_CLIENT_ID }}
export ORCID_CLIENT_SECRET={{ .Data.ORCID_CLIENT_SECRET }}
export DPID_URL_OVERRIDE={{ .Data.DPID_URL_OVERRIDE }}
export ARWEAVE_ENABLED=0
export ARWEAVE_HOST=
export ARWEAVE_PORT=1984
Expand Down Expand Up @@ -90,6 +91,10 @@ spec:
export IPFS_READ_ONLY_GATEWAY_SERVER_URL={{ .Data.IPFS_READ_ONLY_GATEWAY_SERVER_URL }}
export ETHEREUM_RPC_URL={{ .Data.ETHEREUM_RPC_URL }}
export GOOGLE_CLIENT_ID={{ .Data.GOOGLE_CLIENT_ID }}
export DOI_PREFIX={{ .Data.DOI_PREFIX }}
export CROSSREF_API={{ .Data.CROSSREF_API }}
export CROSSREF_API_KEY={{ .Data.CROSSREF_API_KEY }}
export CROSSREF_EMAIL={{ .Data.CROSSREF_EMAIL }}
export DEBUG_TEST=0;
echo "appfinish";
{{- end -}}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-- CreateTable
CREATE TABLE "DoiRecord" (
"id" SERIAL NOT NULL,
"doi" TEXT NOT NULL,
"dpid" TEXT NOT NULL,
"uuid" TEXT NOT NULL,
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMP(3) NOT NULL,

CONSTRAINT "DoiRecord_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE UNIQUE INDEX "DoiRecord_doi_key" ON "DoiRecord"("doi");

-- CreateIndex
CREATE UNIQUE INDEX "DoiRecord_dpid_key" ON "DoiRecord"("dpid");

-- AddForeignKey
ALTER TABLE "DoiRecord" ADD CONSTRAINT "DoiRecord_uuid_fkey" FOREIGN KEY ("uuid") REFERENCES "Node"("uuid") ON DELETE RESTRICT ON UPDATE CASCADE;
11 changes: 11 additions & 0 deletions desci-server/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ model Node {
OrcidPutCodes OrcidPutCodes[]
DistributionPdfs DistributionPdfs[]
PdfPreviews PdfPreviews[]
DoiRecord DoiRecord[]
@@index([ownerId])
@@index([uuid])
Expand Down Expand Up @@ -833,6 +834,16 @@ model OrcidPutCodes {
@@unique([orcid, uuid, reference])
}

model DoiRecord {
id Int @id @default(autoincrement())
doi String @unique
dpid String @unique
uuid String
node Node @relation(fields: [uuid], references: [uuid])
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}

enum ORCIDRecord {
WORK
QUALIFICATION
Expand Down
20 changes: 0 additions & 20 deletions desci-server/src/controllers/attestations/verification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,10 @@ import { NextFunction, Request, Response } from 'express';
import _ from 'lodash';

import {
AuthFailureResponse,
BadRequestError,
ForbiddenError,
NotFoundError,
RequestWithUser,
SuccessMessageResponse,
SuccessResponse,
attestationService,
communityService,
ensureUuidEndsWithDot,
prisma,
} from '../../internal.js';
Expand Down Expand Up @@ -130,18 +125,3 @@ export const getAttestationVerifications = async (req: Request, res: Response, n

return new SuccessResponse(data).send(res);
};

export const canVerifyClaim = async (req: RequestWithUser, res: Response) => {
const logger = parentLogger.child({
module: 'ATTESTATIONS::canVerify',
});
const userId = req.user.id;
const claimId = parseInt(req.params.claimId);

const claim = await attestationService.findClaimById(claimId);
const isMember = await communityService.findMemberByUserId(claim.desciCommunityId, userId);

logger.info({ userId: req.user.id, claimId, community: claim.desciCommunityId }, 'Claim Verification check');
if (!isMember) new SuccessResponse({ ok: false }).send(res);
else new SuccessResponse({ ok: true }).send(res);
};
34 changes: 21 additions & 13 deletions desci-server/src/controllers/communities/feed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,13 @@ export const getCommunityFeed = async (req: Request, res: Response, next: NextFu
});

let data = await Promise.all(nodes.map(resolveLatestNode));
data = data.sort((c1, c2) => {
const key1 = c1.engagements.verifications + c1.engagements.annotations + c1.engagements.reactions;
const key2 = c2.engagements.verifications + c2.engagements.annotations + c2.engagements.reactions;
return key2 - key1;
});
data = data
.sort((c1, c2) => {
const key1 = c1.engagements.verifications + c1.engagements.annotations + c1.engagements.reactions;
const key2 = c2.engagements.verifications + c2.engagements.annotations + c2.engagements.reactions;
return key2 - key1;
})
.reverse();
return new SuccessResponse(data).send(res);
};

Expand Down Expand Up @@ -85,15 +87,21 @@ export const getAllFeeds = async (req: Request, res: Response, next: NextFunctio
* or
* fallback to last submission/attestation claim date
*/
data = data.sort((entryA, entryB) => {
const key1 = entryA.engagements.verifications + entryA.engagements.annotations + entryA.engagements.reactions;
const key2 = entryB.engagements.verifications + entryB.engagements.annotations + entryB.engagements.reactions;
if (key1 !== key2) return key2 - key1;
data = data
.sort((entryA, entryB) => {
const key1 = entryA.engagements.verifications + entryA.engagements.annotations + entryA.engagements.reactions;
const key2 = entryB.engagements.verifications + entryB.engagements.annotations + entryB.engagements.reactions;
if (key1 !== key2) return key2 - key1;

const entryALastClaimedAt = new Date(entryA.NodeAttestation[entryA.NodeAttestation.length - 1].claimedAt).getTime();
const entryBlastClaimedAt = new Date(entryB.NodeAttestation[entryB.NodeAttestation.length - 1].claimedAt).getTime();
return entryBlastClaimedAt - entryALastClaimedAt;
});
const entryALastClaimedAt = new Date(
entryA.NodeAttestation[entryA.NodeAttestation.length - 1].claimedAt,
).getTime();
const entryBlastClaimedAt = new Date(
entryB.NodeAttestation[entryB.NodeAttestation.length - 1].claimedAt,
).getTime();
return entryBlastClaimedAt - entryALastClaimedAt;
})
.reverse();

return new SuccessResponse(data).send(res);
};
18 changes: 18 additions & 0 deletions desci-server/src/controllers/communities/guard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Response } from 'express';

import { SuccessResponse, communityService, logger } from '../../internal.js';
import { RequestWithUser } from '../../middleware/authorisation.js';

export const checkMemberGuard = async (req: RequestWithUser, res: Response) => {
const log = logger.child({
module: 'ATTESTATIONS::MemberGuard',
});
const userId = req.user.id;
const communityId = parseInt(req.params.communityId);

log.info({ userId: req.user.id, community: communityId }, 'Community Member Guard check');
const isMember = await communityService.findMemberByUserId(communityId, userId);

if (!isMember) new SuccessResponse({ ok: false }).send(res);
else new SuccessResponse({ ok: true }).send(res);
};
1 change: 1 addition & 0 deletions desci-server/src/controllers/communities/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from './radar.js';
export * from './list.js';
export * from './types.js';
export * from './util.js';
export * from './guard.js';
27 changes: 27 additions & 0 deletions desci-server/src/controllers/doi/check.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { NextFunction, Request, Response } from 'express';

import { DoiError } from '../../core/doi/error.js';
import { BadRequestError, SuccessResponse, doiService, logger } from '../../internal.js';

export const checkMintability = async (req: Request, res: Response, _next: NextFunction) => {
const { uuid } = req.params;
if (!uuid) throw new BadRequestError();
try {
await doiService.checkMintability(uuid);
new SuccessResponse(true).send(res);
} catch (err) {
logger.error(err, 'module:: checkMintability');
if (!(err instanceof DoiError)) {
// TODO: Sentry error reporting
}
new SuccessResponse(false).send(res);
}
};

export const getDoi = async (req: Request, res: Response, next: NextFunction) => {
const { identifier } = req.params;
if (!identifier) throw new BadRequestError();

const doi = await doiService.getDoiByDpidOrUuid(identifier);
new SuccessResponse(doi).send(res);
};
2 changes: 2 additions & 0 deletions desci-server/src/controllers/doi/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './check.js';
export * from './mint.js';
11 changes: 11 additions & 0 deletions desci-server/src/controllers/doi/mint.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Request, Response, NextFunction } from 'express';

import { BadRequestError, SuccessResponse, doiService, ensureUuidEndsWithDot } from '../../internal.js';

export const mintDoi = async (req: Request, res: Response, next: NextFunction) => {
const { uuid } = req.params;
if (!uuid) throw new BadRequestError();
const sanitizedUuid = ensureUuidEndsWithDot(uuid);
const doi = await doiService.mintDoi(sanitizedUuid);
new SuccessResponse(doi).send(res);
};
4 changes: 2 additions & 2 deletions desci-server/src/controllers/nodes/prepublish.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ResearchObjectV1 } from '@desci-labs/desci-models';
import { NodeVersion } from '@prisma/client';
import { Response } from 'express';
import { NextFunction, Response } from 'express';

import { prisma } from '../../client.js';
import { logger as parentLogger } from '../../logger.js';
Expand Down Expand Up @@ -30,7 +30,7 @@ export interface PrepublishErrorResponse {
/**
* DAGifies the drafts current DB tree state, adds the structure to IPFS (No Files Pinned, Folders staged), and updates the manifest data bucket CID.
*/
export const prepublish = async (req: RequestWithNode, res: Response<PrepublishResponse>) => {
export const prepublish = async (req: RequestWithNode, res: Response, _next: NextFunction) => {
const owner = req.user;
const node = req.node;
const { uuid } = req.body;
Expand Down
13 changes: 12 additions & 1 deletion desci-server/src/core/ApiError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
InternalErrorResponse,
NotFoundResponse,
} from './ApiResponse.js';
import { DoiError, DoiErrorType } from './doi/error.js';

export enum ApiErrorType {
BAD_REQUEST = 'BadRequestError',
Expand Down Expand Up @@ -46,7 +47,7 @@ export abstract class ApiError extends Error {
}
}

public static transform(err: Error, res): Response {
public static transform(err: Error, res: Response): Response {
if (err instanceof AttestationError) {
switch (err.type) {
case AttestationErrorType.DUPLICATE:
Expand All @@ -60,6 +61,16 @@ export abstract class ApiError extends Error {
default:
return new InternalErrorResponse(err.message).send(res);
}
} else if (err instanceof DoiError) {
switch (err.type) {
case DoiErrorType.BAD_METADATA:
case DoiErrorType.NO_MANUSCRIPT:
case DoiErrorType.INCOMPLETE_ATTESTATIONS:
case DoiErrorType.DUPLICATE_MINT:
return new BadRequestResponse(err.message, err).send(res);
default:
return new InternalErrorResponse(err.message).send(res);
}
}
return new InternalErrorResponse(err.message).send(res);
}
Expand Down
Loading

0 comments on commit 40963c7

Please sign in to comment.