UNPKG

8.65 kBJavaScriptView Raw
1"use strict";
2var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 if (k2 === undefined) k2 = k;
4 Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5}) : (function(o, m, k, k2) {
6 if (k2 === undefined) k2 = k;
7 o[k2] = m[k];
8}));
9var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10 Object.defineProperty(o, "default", { enumerable: true, value: v });
11}) : function(o, v) {
12 o["default"] = v;
13});
14var __importStar = (this && this.__importStar) || function (mod) {
15 if (mod && mod.__esModule) return mod;
16 var result = {};
17 if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18 __setModuleDefault(result, mod);
19 return result;
20};
21Object.defineProperty(exports, "__esModule", { value: true });
22exports.listPublishers = exports.deletePublisher = exports.logoutPublisher = exports.loginPublisher = exports.getPublisher = exports.verifyPat = exports.KeytarStore = exports.FileStore = void 0;
23const fs = __importStar(require("fs"));
24const path = __importStar(require("path"));
25const os_1 = require("os");
26const util_1 = require("./util");
27const validation_1 = require("./validation");
28const package_1 = require("./package");
29class FileStore {
30 constructor(path, publishers) {
31 this.path = path;
32 this.publishers = publishers;
33 }
34 static async open(path = FileStore.DefaultPath) {
35 try {
36 const rawStore = await fs.promises.readFile(path, 'utf8');
37 return new FileStore(path, JSON.parse(rawStore).publishers);
38 }
39 catch (err) {
40 if (err.code === 'ENOENT') {
41 return new FileStore(path, []);
42 }
43 else if (/SyntaxError/.test(err)) {
44 throw new Error(`Error parsing file store: ${path}`);
45 }
46 throw err;
47 }
48 }
49 get size() {
50 return this.publishers.length;
51 }
52 async save() {
53 await fs.promises.writeFile(this.path, JSON.stringify({ publishers: this.publishers }), { mode: '0600' });
54 }
55 async deleteStore() {
56 try {
57 await fs.promises.unlink(this.path);
58 }
59 catch {
60 // noop
61 }
62 }
63 get(name) {
64 return this.publishers.filter(p => p.name === name)[0];
65 }
66 async add(publisher) {
67 this.publishers = [...this.publishers.filter(p => p.name !== publisher.name), publisher];
68 await this.save();
69 }
70 async delete(name) {
71 this.publishers = this.publishers.filter(p => p.name !== name);
72 await this.save();
73 }
74 [Symbol.iterator]() {
75 return this.publishers[Symbol.iterator]();
76 }
77}
78exports.FileStore = FileStore;
79FileStore.DefaultPath = path.join((0, os_1.homedir)(), '.vsce');
80class KeytarStore {
81 constructor(keytar, serviceName, publishers) {
82 this.keytar = keytar;
83 this.serviceName = serviceName;
84 this.publishers = publishers;
85 }
86 static async open(serviceName = 'vscode-vsce') {
87 const keytar = await Promise.resolve().then(() => __importStar(require('keytar')));
88 const creds = await keytar.findCredentials(serviceName);
89 return new KeytarStore(keytar, serviceName, creds.map(({ account, password }) => ({ name: account, pat: password })));
90 }
91 get size() {
92 return this.publishers.length;
93 }
94 get(name) {
95 return this.publishers.filter(p => p.name === name)[0];
96 }
97 async add(publisher) {
98 this.publishers = [...this.publishers.filter(p => p.name !== publisher.name), publisher];
99 await this.keytar.setPassword(this.serviceName, publisher.name, publisher.pat);
100 }
101 async delete(name) {
102 this.publishers = this.publishers.filter(p => p.name !== name);
103 await this.keytar.deletePassword(this.serviceName, name);
104 }
105 [Symbol.iterator]() {
106 return this.publishers[Symbol.iterator]();
107 }
108}
109exports.KeytarStore = KeytarStore;
110async function verifyPat(pat, publisherName) {
111 if (!pat) {
112 throw new Error('The Personal Access Token is mandatory.');
113 }
114 if (!publisherName) {
115 try {
116 publisherName = (await (0, package_1.readManifest)()).publisher;
117 }
118 catch (error) {
119 throw new Error(`Can not read the publisher's name. Either supply it as an argument or run vsce from the extension folder. Additional information:\n\n${error}`);
120 }
121 }
122 try {
123 // If the caller of the `getRoleAssignments` API has any of the roles
124 // (Creator, Owner, Contributor, Reader) on the publisher, we get a 200,
125 // otherwise we get a 403.
126 const api = await (0, util_1.getSecurityRolesAPI)(pat);
127 await api.getRoleAssignments('gallery.publisher', publisherName);
128 }
129 catch (error) {
130 throw new Error('The Personal Access Token verification has failed. Additional information:\n\n' + error);
131 }
132 console.log(`The Personal Access Token verification succeeded for the publisher '${publisherName}'.`);
133}
134exports.verifyPat = verifyPat;
135async function requestPAT(publisherName) {
136 console.log('https://marketplace.visualstudio.com/manage/publishers/');
137 const pat = await (0, util_1.read)(`Personal Access Token for publisher '${publisherName}':`, { silent: true, replace: '*' });
138 await verifyPat(pat, publisherName);
139 return pat;
140}
141async function openDefaultStore() {
142 if (/^file$/i.test(process.env['VSCE_STORE'] ?? '')) {
143 return await FileStore.open();
144 }
145 let keytarStore;
146 try {
147 keytarStore = await KeytarStore.open();
148 }
149 catch (err) {
150 const store = await FileStore.open();
151 util_1.log.warn(`Failed to open credential store. Falling back to storing secrets clear-text in: ${store.path}`);
152 return store;
153 }
154 const fileStore = await FileStore.open();
155 // migrate from file store
156 if (fileStore.size) {
157 for (const publisher of fileStore) {
158 await keytarStore.add(publisher);
159 }
160 await fileStore.deleteStore();
161 util_1.log.info(`Migrated ${fileStore.size} publishers to system credential manager. Deleted local store '${fileStore.path}'.`);
162 }
163 return keytarStore;
164}
165async function getPublisher(publisherName) {
166 (0, validation_1.validatePublisher)(publisherName);
167 const store = await openDefaultStore();
168 let publisher = store.get(publisherName);
169 if (publisher) {
170 return publisher;
171 }
172 const pat = await requestPAT(publisherName);
173 publisher = { name: publisherName, pat };
174 await store.add(publisher);
175 return publisher;
176}
177exports.getPublisher = getPublisher;
178async function loginPublisher(publisherName) {
179 (0, validation_1.validatePublisher)(publisherName);
180 const store = await openDefaultStore();
181 let publisher = store.get(publisherName);
182 if (publisher) {
183 console.log(`Publisher '${publisherName}' is already known`);
184 const answer = await (0, util_1.read)('Do you want to overwrite its PAT? [y/N] ');
185 if (!/^y$/i.test(answer)) {
186 throw new Error('Aborted');
187 }
188 }
189 const pat = await requestPAT(publisherName);
190 publisher = { name: publisherName, pat };
191 await store.add(publisher);
192 return publisher;
193}
194exports.loginPublisher = loginPublisher;
195async function logoutPublisher(publisherName) {
196 (0, validation_1.validatePublisher)(publisherName);
197 const store = await openDefaultStore();
198 const publisher = store.get(publisherName);
199 if (!publisher) {
200 throw new Error(`Unknown publisher '${publisherName}'`);
201 }
202 await store.delete(publisherName);
203}
204exports.logoutPublisher = logoutPublisher;
205async function deletePublisher(publisherName) {
206 const publisher = await getPublisher(publisherName);
207 const answer = await (0, util_1.read)(`This will FOREVER delete '${publisherName}'! Are you sure? [y/N] `);
208 if (!/^y$/i.test(answer)) {
209 throw new Error('Aborted');
210 }
211 const api = await (0, util_1.getGalleryAPI)(publisher.pat);
212 await api.deletePublisher(publisherName);
213 const store = await openDefaultStore();
214 await store.delete(publisherName);
215 util_1.log.done(`Deleted publisher '${publisherName}'.`);
216}
217exports.deletePublisher = deletePublisher;
218async function listPublishers() {
219 const store = await openDefaultStore();
220 for (const publisher of store) {
221 console.log(publisher.name);
222 }
223}
224exports.listPublishers = listPublishers;
225//# sourceMappingURL=store.js.map
\No newline at end of file