Skip to content

Commit

Permalink
Merge pull request #532 from felipecrs/verify-pat
Browse files Browse the repository at this point in the history
Add verify-pat command
  • Loading branch information
joaomoreno committed Feb 3, 2021
2 parents 7d96666 + 5ba4c62 commit 9f33d50
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 7 deletions.
18 changes: 16 additions & 2 deletions src/main.ts
Expand Up @@ -5,7 +5,7 @@ import { packageCommand, ls } from './package';
import { publish, unpublish } from './publish';
import { show } from './show';
import { search } from './search';
import { listPublishers, deletePublisher, loginPublisher, logoutPublisher } from './store';
import { listPublishers, deletePublisher, loginPublisher, logoutPublisher, verifyPat } from './store';
import { getLatestVersion } from './npm';
import { CancellationToken, log } from './util';
import * as semver from 'semver';
Expand Down Expand Up @@ -110,7 +110,11 @@ module.exports = function (argv: string[]): void {
program
.command('publish [<version>]')
.description('Publishes an extension')
.option('-p, --pat <token>', 'Personal Access Token', process.env['VSCE_PAT'])
.option(
'-p, --pat <token>',
'Personal Access Token (defaults to VSCE_PAT environment variable)',
process.env['VSCE_PAT']
)
.option('-m, --message <commit message>', 'Commit message used when calling `npm version`.')
.option('--packagePath [path]', 'Publish the VSIX package located at the specified path.')
.option(
Expand Down Expand Up @@ -176,6 +180,16 @@ module.exports = function (argv: string[]): void {
.description('Remove a publisher from the known publishers list')
.action(name => main(logoutPublisher(name)));

program
.command('verify-pat [<publisher>]')
.option(
'-p, --pat <token>',
'Personal Access Token (defaults to VSCE_PAT environment variable)',
process.env['VSCE_PAT']
)
.description('Verify if the Personal Access Token has publish rights for the publisher.')
.action((name, { pat }) => main(verifyPat(pat, name)));

program
.command('show <extensionid>')
.option('--json', 'Output data in json format', false)
Expand Down
36 changes: 31 additions & 5 deletions src/store.ts
Expand Up @@ -4,6 +4,7 @@ import { home } from 'osenv';
import { read, getGalleryAPI, getSecurityRolesAPI, log } from './util';
import { validatePublisher } from './validation';
import * as denodeify from 'denodeify';
import { readManifest } from './package';

const readFile = denodeify<string, string, string>(fs.readFile);
const writeFile = denodeify<string, string, object, void>(fs.writeFile as any);
Expand Down Expand Up @@ -53,14 +54,39 @@ function removePublisherFromStore(store: IStore, publisherName: string): Promise
return save(store);
}

export async function verifyPat(pat: string, publisherName?: string): Promise<void> {
if (!pat) {
throw new Error('The Personal Access Token is mandatory.');
}

if (!publisherName) {
try {
publisherName = (await readManifest()).publisher;
} catch (error) {
throw new Error(
'Can not read the publisher name. Either supply it as argument or run vsce from the extension folder. Additional information:\n\n' +
error
);
}
}

try {
// If the caller of the `getRoleAssignments` API has any of the roles
// (Creator, Owner, Contributor, Reader) on the publisher, we get a 200,
// otherwise we get a 403.
const api = await getSecurityRolesAPI(pat);
await api.getRoleAssignments('gallery.publisher', publisherName);
} catch (error) {
throw new Error('The Personal Access Token verification has failed. Additional information:\n\n' + error);
}

console.log(`The Personal Access Token verification succeeded for the publisher '${publisherName}'.`);
}

async function requestPAT(store: IStore, publisherName: string): Promise<IPublisher> {
const pat = await read(`Personal Access Token for publisher '${publisherName}':`, { silent: true, replace: '*' });

// If the caller of the `getRoleAssignments` API has any of the roles
// (Creator, Owner, Contributor, Reader) on the publisher, we get a 200,
// otherwise we get a 403.
const api = await getSecurityRolesAPI(pat);
await api.getRoleAssignments('gallery.publisher', publisherName);
await verifyPat(pat, publisherName);

return await addPublisherToStore(store, { name: publisherName, pat });
}
Expand Down

0 comments on commit 9f33d50

Please sign in to comment.