@@ -3,43 +3,69 @@ const { Command } = require("commander");
3
3
const Client = require("../client");
4
4
const { sdkForConsole } = 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 { accountUpdateMfaChallenge, accountCreateMfaChallenge, accountGet, accountCreateEmailPasswordSession, accountDeleteSession } = require("./account");
9
+ const { questionsLogin, questionsLogout, questionsListFactors, questionsMfaChallenge } = require("../questions");
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 ({ email, password, endpoint, mfa, code }) => {
15
+ const oldCurrent = globalConfig.getCurrentSession();
16
+ let configEndpoint = endpoint ?? DEFAULT_ENDPOINT;
15
17
16
- await accountCreateEmailPasswordSession({
17
- email: answers.email,
18
- password: answers.password,
19
- parseOutput: false,
20
- sdk: client
21
- })
18
+ const answers = email && password ? { email, password } : await inquirer.prompt(questionsLogin);
19
+
20
+ if (answers.method === 'select') {
21
+ const accountId = answers.accountId;
22
+
23
+ if (!globalConfig.getSessionIds().includes(accountId)) {
24
+ throw Error('Session ID not found');
25
+ }
26
+
27
+ globalConfig.setCurrentSession(accountId);
28
+ success(`Current account is ${accountId}`);
29
+
30
+ return;
31
+ }
32
+
33
+ const id = ID.unique();
22
34
23
- client.setCookie(globalConfig.getCookie());
35
+ globalConfig.addSession(id, {});
36
+ globalConfig.setCurrentSession(id);
37
+ globalConfig.setEndpoint(configEndpoint);
38
+ globalConfig.setEmail(answers.email);
39
+
40
+ let client = await sdkForConsole(false);
24
41
25
42
let account;
26
43
27
44
try {
45
+ await accountCreateEmailPasswordSession({
46
+ email: answers.email,
47
+ password: answers.password,
48
+ parseOutput: false,
49
+ sdk: client
50
+ })
51
+
52
+ client.setCookie(globalConfig.getCookie());
53
+
28
54
account = await accountGet({
29
55
sdk: client,
30
56
parseOutput: false
31
57
});
32
- } catch(error) {
58
+ } catch (error) {
33
59
if (error.response === 'user_more_factors_required') {
34
- const { factor } = await inquirer.prompt(questionsListFactors);
60
+ const { factor } = mfa ? { factor: mfa } : await inquirer.prompt(questionsListFactors);
35
61
36
62
const challenge = await accountCreateMfaChallenge({
37
63
factor,
38
64
parseOutput: false,
39
65
sdk: client
40
66
});
41
67
42
- const { otp } = await inquirer.prompt(questionsMfaChallenge);
68
+ const { otp } = code ? { otp: code } : await inquirer.prompt(questionsMfaChallenge);
43
69
44
70
await accountUpdateMfaChallenge({
45
71
challengeId: challenge.$id,
@@ -53,6 +79,8 @@ const loginCommand = async () => {
53
79
parseOutput: false
54
80
});
55
81
} else {
82
+ globalConfig.removeSession(id);
83
+ globalConfig.setCurrentSession(oldCurrent);
56
84
throw error;
57
85
}
58
86
}
@@ -88,7 +116,8 @@ const whoami = new Command("whoami")
88
116
'ID': account.$id,
89
117
'Name': account.name,
90
118
'Email': account.email,
91
- 'MFA enabled': account.mfa ? 'Yes' : 'No'
119
+ 'MFA enabled': account.mfa ? 'Yes' : 'No',
120
+ 'Endpoint': globalConfig.getEndpoint()
92
121
}
93
122
];
94
123
if (json) {
@@ -100,20 +129,20 @@ const whoami = new Command("whoami")
100
129
drawTable(data)
101
130
}));
102
131
103
-
104
132
const login = new Command("login")
105
133
.description(commandDescriptions['login'])
134
+ .option(`--email [email]`, `User email`)
135
+ .option(`--password [password]`, `User password`)
136
+ .option(`--endpoint [endpoint]`, `Appwrite endpoint for self hosted instances`)
137
+ .option(`--mfa [factor]`, `Multi-factor authentication login factor: totp, email, phone or recoveryCode`)
138
+ .option(`--code [code]`, `Multi-factor code`)
106
139
.configureHelp({
107
140
helpWidth: process.stdout.columns || 80
108
141
})
109
142
.action(actionRunner(loginCommand));
110
143
111
- const logout = new Command("logout")
112
- .description(commandDescriptions['logout'])
113
- .configureHelp({
114
- helpWidth: process.stdout.columns || 80
115
- })
116
- .action(actionRunner(async () => {
144
+ const deleteSession = async (accountId) => {
145
+ try {
117
146
let client = await sdkForConsole();
118
147
119
148
await accountDeleteSession({
@@ -122,8 +151,51 @@ const logout = new Command("logout")
122
151
sdk: client
123
152
})
124
153
125
- globalConfig.setCookie("");
126
- success()
154
+ globalConfig.removeSession(accountId);
155
+ } catch (e) {
156
+ error('Unable to log out, removing locally saved session information')
157
+ }
158
+ globalConfig.removeSession(accountId);
159
+ }
160
+
161
+ const logout = new Command("logout")
162
+ .description(commandDescriptions['logout'])
163
+ .configureHelp({
164
+ helpWidth: process.stdout.columns || 80
165
+ })
166
+ .action(actionRunner(async () => {
167
+ const sessions = globalConfig.getSessions();
168
+ const current = globalConfig.getCurrentSession();
169
+
170
+ if (current === '') {
171
+ return;
172
+ }
173
+ if (sessions.length === 1) {
174
+ await deleteSession(current);
175
+ success();
176
+
177
+ return;
178
+ }
179
+
180
+ const answers = await inquirer.prompt(questionsLogout);
181
+
182
+ if (answers.accounts) {
183
+ for (let accountId of answers.accounts) {
184
+ globalConfig.setCurrentSession(accountId);
185
+ await deleteSession(accountId);
186
+ }
187
+ }
188
+
189
+ const leftSessions = globalConfig.getSessions();
190
+
191
+ if (leftSessions.length > 0 && leftSessions.filter(session => session.id === current).length !== 1) {
192
+ const accountId = leftSessions[0].id;
193
+ globalConfig.setCurrentSession(accountId);
194
+
195
+ success(`Current account is ${accountId}`);
196
+ }
197
+
198
+ success();
127
199
}));
128
200
{% endif %}
129
201
@@ -156,6 +228,7 @@ const client = new Command("client")
156
228
157
229
if (endpoint !== undefined) {
158
230
try {
231
+ const id = ID.unique();
159
232
let url = new URL(endpoint);
160
233
if (url.protocol !== "http:" && url.protocol !== "https:") {
161
234
throw new Error();
@@ -170,7 +243,8 @@ const client = new Command("client")
170
243
if (!response.version) {
171
244
throw new Error();
172
245
}
173
-
246
+ globalConfig.setCurrentSession(id);
247
+ globalConfig.addSession(id, {});
174
248
globalConfig.setEndpoint(endpoint);
175
249
} catch (_) {
176
250
throw new Error("Invalid endpoint or your Appwrite server is not running as expected.");
@@ -190,22 +264,45 @@ const client = new Command("client")
190
264
}
191
265
192
266
if (reset !== undefined) {
193
- globalConfig.setEndpoint("");
194
- globalConfig.setKey("");
195
- globalConfig.setCookie("");
196
- globalConfig.setSelfSigned("");
197
- localConfig.setProject("", "");
267
+ const sessions = globalConfig.getSessions();
268
+
269
+ for (let accountId of sessions.map(session => session.id)) {
270
+ globalConfig.setCurrentSession(accountId);
271
+ await deleteSession(accountId);
272
+ }
198
273
}
199
274
200
275
success()
201
276
}));
202
277
278
+ const migrate = async () => {
279
+ if (!globalConfig.has('endpoint') || !globalConfig.has('cookie')) {
280
+ return;
281
+ }
282
+
283
+ const endpoint = globalConfig.get('endpoint');
284
+ const cookie = globalConfig.get('cookie');
285
+
286
+ const id = ID.unique();
287
+ const data = {
288
+ endpoint,
289
+ cookie,
290
+ email: 'legacy'
291
+ };
292
+
293
+ globalConfig.addSession(id, data);
294
+ globalConfig.setCurrentSession(id);
295
+ globalConfig.delete('endpoint');
296
+ globalConfig.delete('cookie');
297
+
298
+ }
203
299
module.exports = {
204
300
{% if sdk .test != " true" %}
205
301
loginCommand,
206
302
whoami,
207
303
login,
208
304
logout,
209
305
{% endif %}
306
+ migrate,
210
307
client
211
308
};
0 commit comments