1
1
const inquirer = require("inquirer");
2
2
const { Command } = require("commander");
3
3
const Client = require("../client");
4
- const { sdkForConsole } = require("../sdks");
4
+ const { sdkForConsole, questionGetEndpoint } = require("../sdks");
5
5
const { globalConfig, localConfig } = require("../config");
6
- const { actionRunner, success, parseBool, commandDescriptions, error, parse, drawTable } = require("../parser");
6
+ const { actionRunner, success, parseBool, commandDescriptions, error, parse, log, drawTable } = require("../parser");
7
+ const ID = require("../id");
7
8
{% if sdk .test != " true" %}
8
- const { questionsLogin, questionsListFactors, questionsMfaChallenge } = require("../questions");
9
+ const { questionsLogin, questionsLogout, questionsListFactors, questionsMfaChallenge } = require("../questions");
9
10
const { accountUpdateMfaChallenge, accountCreateMfaChallenge, accountGet, accountCreateEmailPasswordSession, accountDeleteSession } = require("./account");
10
11
11
- const loginCommand = async () => {
12
- const answers = await inquirer.prompt(questionsLogin)
12
+ const DEFAULT_ENDPOINT = 'https://cloud.appwrite.io/v1';
13
13
14
- let client = await sdkForConsole(false);
14
+ const loginCommand = async ({ selfHosted, email, password, endpoint, mfa, code }) => {
15
+ const answers = email && password ? { email, password } : await inquirer.prompt(questionsLogin);
15
16
16
- await accountCreateEmailPasswordSession({
17
- email: answers.email,
18
- password: answers.password,
19
- parseOutput: false,
20
- sdk: client
21
- })
17
+ if (answers.method === 'select') {
18
+ const accountId = answers.accountId;
19
+
20
+ if (!globalConfig.getLoginIds().includes(accountId)) {
21
+ throw Error('Login ID not found');
22
+ }
23
+
24
+ globalConfig.setCurrentLogin(accountId);
25
+ success(`Current account is ${accountId}`);
26
+
27
+ return;
28
+ }
29
+
30
+ const oldCurrent = globalConfig.getCurrentLogin();
31
+ const id = ID.unique();
22
32
23
- client.setCookie(globalConfig.getCookie());
33
+ globalConfig.setCurrentLogin(id);
34
+ globalConfig.addLogin(id, {});
35
+ globalConfig.setEmail(answers.email);
36
+ globalConfig.setEndpoint(DEFAULT_ENDPOINT);
37
+
38
+ if (selfHosted) {
39
+ const selfHostedAnswers = endpoint ? { endpoint } : await inquirer.prompt(questionGetEndpoint);
40
+
41
+ globalConfig.setEndpoint(selfHostedAnswers.endpoint);
42
+ }
43
+
44
+ let client = await sdkForConsole(false);
24
45
25
46
let account;
26
47
27
48
try {
49
+ await accountCreateEmailPasswordSession({
50
+ email: answers.email,
51
+ password: answers.password,
52
+ parseOutput: false,
53
+ sdk: client
54
+ })
55
+
56
+ client.setCookie(globalConfig.getCookie());
57
+
28
58
account = await accountGet({
29
59
sdk: client,
30
60
parseOutput: false
31
61
});
32
- } catch(error) {
62
+ } catch (error) {
33
63
if (error.response === 'user_more_factors_required') {
34
- const { factor } = await inquirer.prompt(questionsListFactors);
64
+ const { factor } = mfa ? { factor: mfa } : await inquirer.prompt(questionsListFactors);
35
65
36
66
const challenge = await accountCreateMfaChallenge({
37
67
factor,
38
68
parseOutput: false,
39
69
sdk: client
40
70
});
41
71
42
- const { otp } = await inquirer.prompt(questionsMfaChallenge);
72
+ const { otp } = code ? { otp: code } : await inquirer.prompt(questionsMfaChallenge);
43
73
44
74
await accountUpdateMfaChallenge({
45
75
challengeId: challenge.$id,
@@ -53,6 +83,8 @@ const loginCommand = async () => {
53
83
parseOutput: false
54
84
});
55
85
} else {
86
+ globalConfig.removeLogin(id);
87
+ globalConfig.setCurrentLogin(oldCurrent);
56
88
throw error;
57
89
}
58
90
}
@@ -100,20 +132,21 @@ const whoami = new Command("whoami")
100
132
drawTable(data)
101
133
}));
102
134
103
-
104
135
const login = new Command("login")
105
136
.description(commandDescriptions['login'])
137
+ .option(`-sh, --self-hosted`, `Flag for enabling custom endpoint for self hosted instances`)
138
+ .option(`--email [email]`, `User email`)
139
+ .option(`--password [password]`, `User password`)
140
+ .option(`--endpoint [endpoint]`, `Appwrite endpoint for self hosted instances`)
141
+ .option(`--mfa [factor]`, `Multi-factor authentication login factor: totp, email, phone or recoveryCode`)
142
+ .option(`--code [code]`, `Multi-factor code`)
106
143
.configureHelp({
107
144
helpWidth: process.stdout.columns || 80
108
145
})
109
146
.action(actionRunner(loginCommand));
110
147
111
- const logout = new Command("logout")
112
- .description(commandDescriptions['logout'])
113
- .configureHelp({
114
- helpWidth: process.stdout.columns || 80
115
- })
116
- .action(actionRunner(async () => {
148
+ const singleLogout = async (accountId) => {
149
+ try {
117
150
let client = await sdkForConsole();
118
151
119
152
await accountDeleteSession({
@@ -122,8 +155,51 @@ const logout = new Command("logout")
122
155
sdk: client
123
156
})
124
157
125
- globalConfig.setCookie("");
126
- success()
158
+ globalConfig.removeLogin(accountId);
159
+ } catch (e) {
160
+ error('Unable to log out, removing locally saved session information')
161
+ }
162
+ globalConfig.removeLogin(accountId);
163
+ }
164
+
165
+ const logout = new Command("logout")
166
+ .description(commandDescriptions['logout'])
167
+ .configureHelp({
168
+ helpWidth: process.stdout.columns || 80
169
+ })
170
+ .action(actionRunner(async () => {
171
+ const logins = globalConfig.getLogins();
172
+ const current = globalConfig.getCurrentLogin();
173
+
174
+ if (current === '') {
175
+ return;
176
+ }
177
+ if (logins.length === 1) {
178
+ await singleLogout(current);
179
+ success();
180
+
181
+ return;
182
+ }
183
+
184
+ const answers = await inquirer.prompt(questionsLogout);
185
+
186
+ if (answers.accounts) {
187
+ for (let accountId of answers.accounts) {
188
+ globalConfig.setCurrentLogin(accountId);
189
+ await singleLogout(accountId);
190
+ }
191
+ }
192
+
193
+ const leftLogins = globalConfig.getLogins();
194
+
195
+ if (leftLogins.length > 0 && leftLogins.filter(login => login.id === current).length !== 1) {
196
+ const accountId = leftLogins[0].id;
197
+ globalConfig.setCurrentLogin(accountId);
198
+
199
+ success(`Current account is ${accountId}`);
200
+ }
201
+
202
+ success();
127
203
}));
128
204
{% endif %}
129
205
@@ -156,6 +232,7 @@ const client = new Command("client")
156
232
157
233
if (endpoint !== undefined) {
158
234
try {
235
+ const id = ID.unique();
159
236
let url = new URL(endpoint);
160
237
if (url.protocol !== "http:" && url.protocol !== "https:") {
161
238
throw new Error();
@@ -170,7 +247,8 @@ const client = new Command("client")
170
247
if (!response.version) {
171
248
throw new Error();
172
249
}
173
-
250
+ globalConfig.setCurrentLogin(id);
251
+ globalConfig.addLogin(id, {});
174
252
globalConfig.setEndpoint(endpoint);
175
253
} catch (_) {
176
254
throw new Error("Invalid endpoint or your Appwrite server is not running as expected.");
@@ -190,22 +268,45 @@ const client = new Command("client")
190
268
}
191
269
192
270
if (reset !== undefined) {
193
- globalConfig.setEndpoint("");
194
- globalConfig.setKey("");
195
- globalConfig.setCookie("");
196
- globalConfig.setSelfSigned("");
197
- localConfig.setProject("", "");
271
+ const logins = globalConfig.getLogins();
272
+
273
+ for (let accountId of logins.map(login => login.id)) {
274
+ globalConfig.setCurrentLogin(accountId);
275
+ await singleLogout(accountId);
276
+ }
198
277
}
199
278
200
279
success()
201
280
}));
202
281
282
+ const migrate = async () => {
283
+ if (!globalConfig.has('endpoint') || !globalConfig.has('cookie')) {
284
+ return;
285
+ }
286
+
287
+ const endpoint = globalConfig.get('endpoint');
288
+ const cookie = globalConfig.get('cookie');
289
+
290
+ const id = ID.unique();
291
+ const data = {
292
+ endpoint,
293
+ cookie,
294
+ email: 'legacy'
295
+ };
296
+
297
+ globalConfig.addLogin(id, data);
298
+ globalConfig.setCurrentLogin(id);
299
+ globalConfig.delete('endpoint');
300
+ globalConfig.delete('cookie');
301
+
302
+ }
203
303
module.exports = {
204
304
{% if sdk .test != " true" %}
205
305
loginCommand,
206
306
whoami,
207
307
login,
208
308
logout,
209
309
{% endif %}
310
+ migrate,
210
311
client
211
312
};
0 commit comments