Skip to content

Commit 6b9dd7e

Browse files
author
Ajit Kumar
committed
fix(plugin page, plugin update/publish, contributors should be array of {name,role,github})
1 parent 1e53c80 commit 6b9dd7e

File tree

2 files changed

+122
-147
lines changed

2 files changed

+122
-147
lines changed

client/pages/publishPlugin/index.js

+32-33
Original file line numberDiff line numberDiff line change
@@ -15,45 +15,32 @@ export default async function PublishPlugin({ mode = 'publish', id }) {
1515
return null;
1616
}
1717

18+
/** @type {object} */
19+
const plugin = id ? await fetch(`/api/plugin/${id}`).then((res) => res.json()) : null;
1820
const jsZip = new JSZip();
19-
const license = Reactive();
20-
const keywords = Reactive();
21-
const pluginId = Reactive();
2221
const errorText = Reactive();
2322
const updateType = Reactive();
24-
const pluginName = Reactive();
2523
const successText = Reactive();
26-
const pluginPrice = Reactive();
27-
const contributors = Reactive();
28-
const pluginAuthor = Reactive();
29-
const pluginVersion = Reactive();
30-
const minVersionCode = Reactive();
31-
const pluginDescription = Reactive();
24+
const pluginId = Reactive(plugin?.id);
25+
const pluginName = Reactive(plugin?.name);
26+
const license = Reactive(plugin?.license);
27+
const pluginVersion = Reactive(plugin?.version);
28+
const pluginPrice = Reactive(+plugin?.price ? `INR ${plugin.price}` : 'Free');
29+
const keywords = Reactive(plugin?.keywords && json(plugin.keywords)?.join(', '));
30+
const contributors = Reactive(
31+
plugin?.contributors &&
32+
json(plugin.contributors)
33+
?.map((contributor) => contributor.name)
34+
.join(', '),
35+
);
36+
const pluginAuthor = Reactive(plugin?.author || user.name);
37+
const minVersionCode = Reactive(plugin?.minVersionCode);
3238
const buttonText = Reactive(capitalize(mode));
3339

3440
const submitButton = Ref();
3541
const changelogsInput = Ref();
3642
const method = mode === 'publish' ? 'post' : 'put';
37-
const pluginIcon = <img style={{ height: '120px', width: '120px' }} src='#' alt='Plugin icon' />;
38-
39-
let plugin;
40-
if (id) {
41-
plugin = await fetch(`/api/plugin/${id}`).then((res) => res.json());
42-
pluginId.value = plugin.id;
43-
pluginName.value = plugin.name;
44-
pluginVersion.value = plugin.version;
45-
pluginAuthor.value = plugin.author;
46-
pluginDescription.value = plugin.description;
47-
minVersionCode.value = plugin.minVersionCode;
48-
49-
if (+plugin.price) {
50-
pluginPrice.value = `INR ${plugin.price}`;
51-
} else {
52-
pluginPrice.value = 'Free';
53-
}
54-
55-
pluginIcon.src = `/plugin-icon/${plugin.id}`;
56-
}
43+
const pluginIcon = <img style={{ height: '120px', width: '120px' }} src={plugin?.icon || '#'} alt='Plugin icon' />;
5744

5845
return (
5946
<section id='publish-plugin'>
@@ -165,7 +152,6 @@ export default async function PublishPlugin({ mode = 'publish', id }) {
165152
pluginName.value = '';
166153
pluginVersion.value = '';
167154
pluginAuthor.value = '';
168-
pluginDescription.value = '';
169155
pluginPrice.value = '';
170156
pluginIcon.src = '#';
171157
minVersionCode.value = '';
@@ -199,15 +185,21 @@ export default async function PublishPlugin({ mode = 'publish', id }) {
199185
}
200186

201187
if (manifest.contributors) {
202-
contributors.value = manifest.contributors.join(', ');
188+
contributors.value = manifest.contributors.map((contributor) => contributor.name).join(', ');
189+
} else {
190+
contributors.value = '';
203191
}
204192

205193
if (manifest.keywords) {
206194
keywords.value = manifest.keywords.join(', ');
195+
} else {
196+
keywords.value = '';
207197
}
208198

209199
if (manifest.license) {
210200
license.value = manifest.license;
201+
} else {
202+
license.value = '';
211203
}
212204

213205
if (manifest.author?.name) {
@@ -229,7 +221,6 @@ export default async function PublishPlugin({ mode = 'publish', id }) {
229221
pluginId.value = manifest.id;
230222
pluginName.value = manifest.name;
231223
pluginVersion.value = manifest.version;
232-
pluginDescription.value = manifest.description;
233224
minVersionCode.value = manifest.minVersionCode || -1;
234225
pluginIcon.src = `data:image/png;base64,${icon}`;
235226

@@ -295,3 +286,11 @@ function getUpdateType(newV, oldV) {
295286

296287
return null;
297288
}
289+
290+
function json(string) {
291+
try {
292+
return JSON.parse(string);
293+
} catch (_error) {
294+
return null;
295+
}
296+
}

server/apis/plugin.js

+90-114
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,6 @@ router.post('/', async (req, res) => {
362362
return;
363363
}
364364

365-
let { license, contributors, changelogs, keywords } = req.body;
366365
const { pluginJson, icon, readme, changelogsFile } = await exploreZip(pluginZip.data);
367366

368367
const pluginId = pluginJson.id.toLowerCase();
@@ -387,16 +386,7 @@ router.post('/', async (req, res) => {
387386
return;
388387
}
389388

390-
const {
391-
name,
392-
price,
393-
version,
394-
minVersionCode,
395-
license: licenseFromPlugin,
396-
keywords: keywordsFromPlugin,
397-
changelogs: changelogsFromPlugin,
398-
contributors: contributorsFromPlugin,
399-
} = pluginJson;
389+
const { name, price, version, minVersionCode } = pluginJson;
400390

401391
if (!VERSION_REGEX.test(version)) {
402392
res.status(400).send({ error: 'Invalid version number, version should be in the format x.x.x' });
@@ -417,66 +407,41 @@ router.post('/', async (req, res) => {
417407
await registerSKU(name, pluginId, price);
418408
}
419409

420-
if (!license && licenseFromPlugin) {
421-
if (!validLicenses.includes(licenseFromPlugin)) {
422-
res.status(400).send({ error: 'Invalid license' });
423-
return;
424-
}
425-
426-
license = licenseFromPlugin;
410+
const { changelogs } = req.body;
411+
if (!pluginJson.changelogs && (changelogsFile || changelogs)) {
412+
pluginJson.changelogs = changelogsFile || changelogs;
427413
}
428414

429-
if (!keywords && keywordsFromPlugin) {
430-
if (Array.isArray(keywordsFromPlugin)) {
431-
const invalidKeywords = keywordsFromPlugin.filter((keyword) => typeof keyword !== 'string');
432-
if (invalidKeywords.length) {
433-
res.status(400).send({ error: 'Keywords should be an array of strings' });
434-
return;
435-
}
415+
validatePluginData(pluginJson);
436416

437-
keywords = keywordsFromPlugin.join(', ');
438-
}
417+
const insert = [
418+
[Plugin.ID, pluginId],
419+
[Plugin.NAME, name],
420+
[Plugin.PRICE, price],
421+
[Plugin.VERSION, version],
422+
[Plugin.USER_ID, user.id],
423+
[Plugin.DESCRIPTION, readme],
424+
[Plugin.SKU, getPluginSKU(pluginId)],
425+
[Plugin.MIN_VERSION_CODE, minVersionCode],
426+
];
439427

440-
keywords = keywordsFromPlugin;
428+
if (pluginJson.license) {
429+
insert.push([Plugin.LICENSE, pluginJson.license]);
441430
}
442431

443-
if (!contributors && contributorsFromPlugin) {
444-
if (Array.isArray(contributorsFromPlugin)) {
445-
const invalidContributors = contributorsFromPlugin.filter((contributor) => typeof contributor !== 'string');
446-
if (invalidContributors.length) {
447-
res.status(400).send({ error: 'Contributors should be an array of strings' });
448-
return;
449-
}
450-
451-
contributors = contributorsFromPlugin.join(', ');
452-
}
453-
454-
contributors = contributorsFromPlugin;
432+
if (pluginJson.contributors) {
433+
insert.push([Plugin.CONTRIBUTORS, JSON.stringify(pluginJson.contributors)]);
455434
}
456435

457-
if (!changelogs && (changelogsFromPlugin || changelogsFile)) {
458-
if (changelogsFromPlugin && typeof changelogsFromPlugin !== 'string') {
459-
res.status(400).send({ error: 'Changelogs should be a string' });
460-
return;
461-
}
436+
if (pluginJson.keywords) {
437+
insert.push([Plugin.KEYWORDS, JSON.stringify(pluginJson.keywords)]);
438+
}
462439

463-
changelogs = changelogsFromPlugin || changelogsFile;
440+
if (pluginJson.changelogs) {
441+
insert.push([Plugin.CHANGELOGS, pluginJson.changelogs]);
464442
}
465443

466-
await Plugin.insert(
467-
[Plugin.ID, pluginId],
468-
[Plugin.SKU, getPluginSKU(pluginId)],
469-
[Plugin.NAME, name],
470-
[Plugin.PRICE, price],
471-
[Plugin.VERSION, version],
472-
[Plugin.USER_ID, user.id],
473-
[Plugin.DESCRIPTION, readme],
474-
[Plugin.LICENSE, license],
475-
[Plugin.CONTRIBUTORS, contributors],
476-
[Plugin.CHANGELOGS, changelogs || changelogsFile || changelogsFromPlugin],
477-
[Plugin.KEYWORDS, keywords],
478-
[Plugin.MIN_VERSION_CODE, minVersionCode],
479-
);
444+
await Plugin.insert(...insert);
480445

481446
savePlugin(pluginId, pluginZip, icon);
482447
res.send({ message: 'Plugin uploaded successfully' });
@@ -513,7 +478,6 @@ router.put('/', async (req, res) => {
513478
return;
514479
}
515480

516-
let { license, contributors, changelogs, keywords } = req.body;
517481
const { pluginJson, icon, readme, changelogs: changelogsFile } = await exploreZip(pluginZip.data);
518482

519483
const errorMessage = validatePlugin(pluginJson, icon, readme);
@@ -522,16 +486,7 @@ router.put('/', async (req, res) => {
522486
return;
523487
}
524488

525-
const {
526-
name,
527-
price,
528-
version,
529-
id: pluginId,
530-
license: licenseFromPlugin,
531-
keywords: keywordsFromPlugin,
532-
changelogs: changelogsFromPlugin,
533-
contributors: contributorsFromPlugin,
534-
} = pluginJson;
489+
const { name, price, version, id: pluginId } = pluginJson;
535490

536491
if (!VERSION_REGEX.test(version)) {
537492
res.status(400).send({ error: 'Invalid version number, version should be in the format x.x.x' });
@@ -544,59 +499,30 @@ router.put('/', async (req, res) => {
544499
return;
545500
}
546501

547-
if (!license && licenseFromPlugin) {
548-
if (!validLicenses.includes(licenseFromPlugin)) {
549-
res.status(400).send({ error: 'Invalid license' });
550-
return;
551-
}
552-
553-
license = licenseFromPlugin;
502+
const { changelogs } = req.body;
503+
if (!pluginJson.changelogs && (changelogsFile || changelogs)) {
504+
pluginJson.changelogs = changelogsFile || changelogs;
554505
}
555506

556-
if (!keywords && keywordsFromPlugin) {
557-
if (Array.isArray(keywordsFromPlugin)) {
558-
const invalidKeywords = keywordsFromPlugin.filter((keyword) => typeof keyword !== 'string');
559-
if (invalidKeywords.length) {
560-
res.status(400).send({ error: 'Keywords should be an array of strings' });
561-
return;
562-
}
507+
validatePluginData(pluginJson);
563508

564-
keywords = keywordsFromPlugin.join(', ');
565-
}
509+
const updates = [[Plugin.DESCRIPTION, readme]];
566510

567-
keywords = keywordsFromPlugin;
511+
if (pluginJson.license) {
512+
updates.push([Plugin.LICENSE, pluginJson.license]);
568513
}
569514

570-
if (!contributors && contributorsFromPlugin) {
571-
if (Array.isArray(contributorsFromPlugin)) {
572-
const invalidContributors = contributorsFromPlugin.filter((contributor) => typeof contributor !== 'string');
573-
if (invalidContributors.length) {
574-
res.status(400).send({ error: 'Contributors should be an array of strings' });
575-
return;
576-
}
577-
578-
contributors = contributorsFromPlugin.join(', ');
579-
}
580-
581-
contributors = contributorsFromPlugin;
515+
if (pluginJson.contributors) {
516+
updates.push([Plugin.CONTRIBUTORS, JSON.stringify(pluginJson.contributors)]);
582517
}
583518

584-
if (!changelogs && (changelogsFromPlugin || changelogsFile)) {
585-
if (changelogsFromPlugin && typeof changelogsFromPlugin !== 'string') {
586-
res.status(400).send({ error: 'Changelogs should be a string' });
587-
return;
588-
}
589-
590-
changelogs = changelogsFromPlugin || changelogsFile;
519+
if (pluginJson.keywords) {
520+
updates.push([Plugin.KEYWORDS, JSON.stringify(pluginJson.keywords)]);
591521
}
592522

593-
const updates = [
594-
[Plugin.DESCRIPTION, readme],
595-
[Plugin.LICENSE, license],
596-
[Plugin.CONTRIBUTORS, contributors],
597-
[Plugin.CHANGELOGS, changelogs],
598-
[Plugin.KEYWORDS, keywords],
599-
];
523+
if (pluginJson.changelogs) {
524+
updates.push([Plugin.CHANGELOGS, pluginJson.changelogs]);
525+
}
600526

601527
if (version !== row.version) {
602528
if (!isVersionGreater(version, row.version)) {
@@ -845,4 +771,54 @@ function isVersionGreater(newV, oldV) {
845771
return false;
846772
}
847773

774+
/**
775+
* Validate plugin data
776+
* @param {object} arg
777+
* @param {string} arg.license
778+
* @param {object[]} arg.contributors
779+
* @param {string[]} arg.keywords
780+
* @param {string} arg.changelogs
781+
*/
782+
function validatePluginData({ license, contributors, keywords, changelogs }) {
783+
if (license && !validLicenses.includes(license)) {
784+
throw new Error('Invalid license');
785+
}
786+
787+
if (contributors) {
788+
const error = new Error('Contributors should be an array of {name, role, github}');
789+
if (!Array.isArray(contributors)) {
790+
throw error;
791+
}
792+
793+
const invalidContributors = contributors.filter((contributor) => {
794+
for (const key in contributor) {
795+
if (!['role', 'github', 'name'].includes(key)) {
796+
return true;
797+
}
798+
}
799+
return false;
800+
});
801+
802+
if (invalidContributors.length) {
803+
throw error;
804+
}
805+
}
806+
807+
if (keywords) {
808+
const error = new Error('Keywords should be an array of string');
809+
if (!Array.isArray(keywords)) {
810+
throw error;
811+
}
812+
813+
const invalidKeywords = keywords.filter((keyword) => typeof keyword !== 'string');
814+
if (invalidKeywords.length) {
815+
throw error;
816+
}
817+
}
818+
819+
if (changelogs && typeof changelogs !== 'string') {
820+
throw new Error('Changelogs should be a string');
821+
}
822+
}
823+
848824
module.exports = router;

0 commit comments

Comments
 (0)