Sub-Store/backend/src/restful/subscriptions.js

212 lines
5.7 KiB
JavaScript

import {
NetworkError,
InternalServerError,
ResourceNotFoundError,
RequestInvalidError,
} from './errors';
import { deleteByName, findByName, updateByName } from '@/utils/database';
import { SUBS_KEY, COLLECTIONS_KEY, ARTIFACTS_KEY } from '@/constants';
import { getFlowHeaders, parseFlowHeaders } from '@/utils/flow';
import { success, failed } from './response';
import $ from '@/core/app';
if (!$.read(SUBS_KEY)) $.write({}, SUBS_KEY);
export default function register($app) {
$app.get('/api/sub/flow/:name', getFlowInfo);
$app.route('/api/sub/:name')
.get(getSubscription)
.patch(updateSubscription)
.delete(deleteSubscription);
$app.route('/api/subs')
.get(getAllSubscriptions)
.post(createSubscription)
.put(replaceSubscriptions);
}
// subscriptions API
async function getFlowInfo(req, res) {
let { name } = req.params;
name = decodeURIComponent(name);
const allSubs = $.read(SUBS_KEY);
const sub = findByName(allSubs, name);
if (!sub) {
failed(
res,
new ResourceNotFoundError(
'RESOURCE_NOT_FOUND',
`Subscription ${name} does not exist!`,
),
404,
);
return;
}
if (sub.source === 'local') {
failed(
res,
new RequestInvalidError(
'NO_FLOW_INFO',
'N/A',
`Local subscription ${name} has no flow information!`,
),
);
return;
}
try {
const flowHeaders = await getFlowHeaders(sub.url);
if (!flowHeaders) {
failed(
res,
new InternalServerError(
'NO_FLOW_INFO',
'No flow info',
`Failed to fetch flow headers`,
),
);
return;
}
success(res, parseFlowHeaders(flowHeaders));
} catch (err) {
failed(
res,
new NetworkError(
`URL_NOT_ACCESSIBLE`,
`The URL for subscription ${name} is inaccessible.`,
),
);
}
}
function createSubscription(req, res) {
const sub = req.body;
$.info(`正在创建订阅: ${sub.name}`);
if (/\//.test(sub.name)) {
failed(
res,
new RequestInvalidError(
'INVALID_NAME',
`Subscription ${sub.name} is invalid`,
),
);
return;
}
const allSubs = $.read(SUBS_KEY);
if (findByName(allSubs, sub.name)) {
failed(
res,
new RequestInvalidError(
'DUPLICATE_KEY',
`Subscription ${sub.name} already exists.`,
),
);
return;
}
allSubs.push(sub);
$.write(allSubs, SUBS_KEY);
success(res, sub, 201);
}
function getSubscription(req, res) {
let { name } = req.params;
name = decodeURIComponent(name);
const allSubs = $.read(SUBS_KEY);
const sub = findByName(allSubs, name);
if (sub) {
success(res, sub);
} else {
failed(
res,
new ResourceNotFoundError(
`SUBSCRIPTION_NOT_FOUND`,
`Subscription ${name} does not exist`,
404,
),
);
}
}
function updateSubscription(req, res) {
let { name } = req.params;
name = decodeURIComponent(name); // the original name
let sub = req.body;
const allSubs = $.read(SUBS_KEY);
const oldSub = findByName(allSubs, name);
if (oldSub) {
const newSub = {
...oldSub,
...sub,
};
$.info(`正在更新订阅: ${name}`);
// allow users to update the subscription name
if (name !== sub.name) {
// update all collections refer to this name
const allCols = $.read(COLLECTIONS_KEY) || [];
for (const collection of allCols) {
const idx = collection.subscriptions.indexOf(name);
if (idx !== -1) {
collection.subscriptions[idx] = sub.name;
}
}
// update all artifacts referring this subscription
const allArtifacts = $.read(ARTIFACTS_KEY) || [];
for (const artifact of allArtifacts) {
if (
artifact.type === 'subscription' &&
artifact.source == name
) {
artifact.source = sub.name;
}
}
$.write(allCols, COLLECTIONS_KEY);
$.write(allArtifacts, ARTIFACTS_KEY);
}
updateByName(allSubs, name, newSub);
$.write(allSubs, SUBS_KEY);
success(res, newSub);
} else {
failed(
res,
new ResourceNotFoundError(
'RESOURCE_NOT_FOUND',
`Subscription ${name} does not exist!`,
),
404,
);
}
}
function deleteSubscription(req, res) {
let { name } = req.params;
name = decodeURIComponent(name);
$.info(`删除订阅:${name}...`);
// delete from subscriptions
let allSubs = $.read(SUBS_KEY);
deleteByName(allSubs, name);
$.write(allSubs, SUBS_KEY);
// delete from collections
const allCols = $.read(COLLECTIONS_KEY);
for (const collection of allCols) {
collection.subscriptions = collection.subscriptions.filter(
(s) => s !== name,
);
}
$.write(allCols, COLLECTIONS_KEY);
success(res);
}
function getAllSubscriptions(req, res) {
const allSubs = $.read(SUBS_KEY);
success(res, allSubs);
}
function replaceSubscriptions(req, res) {
const allSubs = req.body;
$.write(allSubs, SUBS_KEY);
success(res);
}