Skip to content

Commit 908cd72

Browse files
Merge pull request #125 from appwrite/dev
fix: mfa
2 parents a0e8f72 + 795b3f1 commit 908cd72

File tree

9 files changed

+127
-35
lines changed

9 files changed

+127
-35
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Once the installation is complete, you can verify the install using
2929

3030
```sh
3131
$ appwrite -v
32-
5.0.2
32+
5.0.3
3333
```
3434

3535
### Install using prebuilt binaries
@@ -60,7 +60,7 @@ $ scoop install https://raw.githubusercontent.com/appwrite/sdk-for-cli/master/sc
6060
Once the installation completes, you can verify your install using
6161
```
6262
$ appwrite -v
63-
5.0.2
63+
5.0.3
6464
```
6565

6666
## Getting Started

install.ps1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
# You can use "View source" of this page to see the full script.
1414

1515
# REPO
16-
$GITHUB_x64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/5.0.2/appwrite-cli-win-x64.exe"
17-
$GITHUB_arm64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/5.0.2/appwrite-cli-win-arm64.exe"
16+
$GITHUB_x64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/5.0.3/appwrite-cli-win-x64.exe"
17+
$GITHUB_arm64_URL = "https://github.com/appwrite/sdk-for-cli/releases/download/5.0.3/appwrite-cli-win-arm64.exe"
1818

1919
$APPWRITE_BINARY_NAME = "appwrite.exe"
2020

install.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ printSuccess() {
9797
downloadBinary() {
9898
echo "[2/4] Downloading executable for $OS ($ARCH) ..."
9999

100-
GITHUB_LATEST_VERSION="5.0.2"
100+
GITHUB_LATEST_VERSION="5.0.3"
101101
GITHUB_FILE="appwrite-cli-${OS}-${ARCH}"
102102
GITHUB_URL="https://github.com/$GITHUB_REPOSITORY_NAME/releases/download/$GITHUB_LATEST_VERSION/$GITHUB_FILE"
103103

lib/client.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ class Client {
1515
'x-sdk-name': 'Command Line',
1616
'x-sdk-platform': 'console',
1717
'x-sdk-language': 'cli',
18-
'x-sdk-version': '5.0.2',
19-
'user-agent' : `AppwriteCLI/5.0.2 (${os.type()} ${os.version()}; ${os.arch()})`,
18+
'x-sdk-version': '5.0.3',
19+
'user-agent' : `AppwriteCLI/5.0.3 (${os.type()} ${os.version()}; ${os.arch()})`,
2020
'X-Appwrite-Response-Format' : '1.5.0',
2121
};
2222
}

lib/commands/generic.js

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ const Client = require("../client");
44
const { sdkForConsole } = require("../sdks");
55
const { globalConfig, localConfig } = require("../config");
66
const { actionRunner, success, parseBool, commandDescriptions, log, parse } = require("../parser");
7-
const { questionsLogin } = require("../questions");
8-
const { accountCreateEmailPasswordSession, accountDeleteSession } = require("./account");
7+
const { questionsLogin, questionsListFactors, questionsMfaChallenge } = require("../questions");
8+
const { accountUpdateMfaChallenge, accountCreateMfaChallenge, accountGet, accountCreateEmailPasswordSession, accountDeleteSession } = require("./account");
99

1010
const login = new Command("login")
1111
.description(commandDescriptions['login'])
@@ -24,7 +24,44 @@ const login = new Command("login")
2424
sdk: client
2525
})
2626

27-
success()
27+
client.setCookie(globalConfig.getCookie());
28+
29+
let account;
30+
31+
try {
32+
account = await accountGet({
33+
sdk: client,
34+
parseOutput: false
35+
});
36+
} catch(error) {
37+
if (error.response === 'user_more_factors_required') {
38+
const { factor } = await inquirer.prompt(questionsListFactors);
39+
40+
const challenge = await accountCreateMfaChallenge({
41+
factor,
42+
parseOutput: false,
43+
sdk: client
44+
});
45+
46+
const { otp } = await inquirer.prompt(questionsMfaChallenge);
47+
48+
await accountUpdateMfaChallenge({
49+
challengeId: challenge.$id,
50+
otp,
51+
parseOutput: false,
52+
sdk: client
53+
});
54+
55+
account = await accountGet({
56+
sdk: client,
57+
parseOutput: false
58+
});
59+
} else {
60+
throw error;
61+
}
62+
}
63+
64+
success("Signed in as user with ID: " + account.$id);
2865
}));
2966

3067
const logout = new Command("logout")

lib/commands/messaging.js

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,9 +1032,9 @@ const messagingUpdateMailgunProvider = async ({ providerId, name, apiKey, domain
10321032
* @typedef {Object} MessagingCreateMsg91ProviderRequestParams
10331033
* @property {string} providerId Provider ID. Choose a custom ID or generate a random ID with 'ID.unique()'. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.
10341034
* @property {string} name Provider name.
1035-
* @property {string} templateId Msg91 template ID
1036-
* @property {string} senderId Msg91 sender ID.
1037-
* @property {string} authKey Msg91 auth key.
1035+
* @property {string} from Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.
1036+
* @property {string} senderId Msg91 Sender ID.
1037+
* @property {string} authKey Msg91 Auth Key.
10381038
* @property {boolean} enabled Set as enabled.
10391039
* @property {boolean} parseOutput
10401040
* @property {libClient | undefined} sdk
@@ -1043,7 +1043,7 @@ const messagingUpdateMailgunProvider = async ({ providerId, name, apiKey, domain
10431043
/**
10441044
* @param {MessagingCreateMsg91ProviderRequestParams} params
10451045
*/
1046-
const messagingCreateMsg91Provider = async ({ providerId, name, templateId, senderId, authKey, enabled, parseOutput = true, sdk = undefined}) => {
1046+
const messagingCreateMsg91Provider = async ({ providerId, name, from, senderId, authKey, enabled, parseOutput = true, sdk = undefined}) => {
10471047
let client = !sdk ? await sdkForProject() : sdk;
10481048
let apiPath = '/messaging/providers/msg91';
10491049
let payload = {};
@@ -1053,8 +1053,8 @@ const messagingCreateMsg91Provider = async ({ providerId, name, templateId, send
10531053
if (typeof name !== 'undefined') {
10541054
payload['name'] = name;
10551055
}
1056-
if (typeof templateId !== 'undefined') {
1057-
payload['templateId'] = templateId;
1056+
if (typeof from !== 'undefined') {
1057+
payload['from'] = from;
10581058
}
10591059
if (typeof senderId !== 'undefined') {
10601060
payload['senderId'] = senderId;
@@ -1085,17 +1085,17 @@ const messagingCreateMsg91Provider = async ({ providerId, name, templateId, send
10851085
* @property {string} providerId Provider ID.
10861086
* @property {string} name Provider name.
10871087
* @property {boolean} enabled Set as enabled.
1088-
* @property {string} templateId Msg91 template ID.
1089-
* @property {string} senderId Msg91 sender ID.
1090-
* @property {string} authKey Msg91 auth key.
1088+
* @property {string} senderId Msg91 Sender ID.
1089+
* @property {string} authKey Msg91 Auth Key.
1090+
* @property {string} from Sender number.
10911091
* @property {boolean} parseOutput
10921092
* @property {libClient | undefined} sdk
10931093
*/
10941094

10951095
/**
10961096
* @param {MessagingUpdateMsg91ProviderRequestParams} params
10971097
*/
1098-
const messagingUpdateMsg91Provider = async ({ providerId, name, enabled, templateId, senderId, authKey, parseOutput = true, sdk = undefined}) => {
1098+
const messagingUpdateMsg91Provider = async ({ providerId, name, enabled, senderId, authKey, from, parseOutput = true, sdk = undefined}) => {
10991099
let client = !sdk ? await sdkForProject() : sdk;
11001100
let apiPath = '/messaging/providers/msg91/{providerId}'.replace('{providerId}', providerId);
11011101
let payload = {};
@@ -1105,15 +1105,15 @@ const messagingUpdateMsg91Provider = async ({ providerId, name, enabled, templat
11051105
if (typeof enabled !== 'undefined') {
11061106
payload['enabled'] = enabled;
11071107
}
1108-
if (typeof templateId !== 'undefined') {
1109-
payload['templateId'] = templateId;
1110-
}
11111108
if (typeof senderId !== 'undefined') {
11121109
payload['senderId'] = senderId;
11131110
}
11141111
if (typeof authKey !== 'undefined') {
11151112
payload['authKey'] = authKey;
11161113
}
1114+
if (typeof from !== 'undefined') {
1115+
payload['from'] = from;
1116+
}
11171117

11181118
let response = undefined;
11191119

@@ -2497,9 +2497,9 @@ messaging
24972497
.description(`Create a new MSG91 provider.`)
24982498
.requiredOption(`--providerId <providerId>`, `Provider ID. Choose a custom ID or generate a random ID with 'ID.unique()'. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.`)
24992499
.requiredOption(`--name <name>`, `Provider name.`)
2500-
.option(`--templateId <templateId>`, `Msg91 template ID`)
2501-
.option(`--senderId <senderId>`, `Msg91 sender ID.`)
2502-
.option(`--authKey <authKey>`, `Msg91 auth key.`)
2500+
.option(`--from <from>`, `Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.`)
2501+
.option(`--senderId <senderId>`, `Msg91 Sender ID.`)
2502+
.option(`--authKey <authKey>`, `Msg91 Auth Key.`)
25032503
.option(`--enabled <enabled>`, `Set as enabled.`, parseBool)
25042504
.action(actionRunner(messagingCreateMsg91Provider))
25052505

@@ -2509,9 +2509,9 @@ messaging
25092509
.requiredOption(`--providerId <providerId>`, `Provider ID.`)
25102510
.option(`--name <name>`, `Provider name.`)
25112511
.option(`--enabled <enabled>`, `Set as enabled.`, parseBool)
2512-
.option(`--templateId <templateId>`, `Msg91 template ID.`)
2513-
.option(`--senderId <senderId>`, `Msg91 sender ID.`)
2514-
.option(`--authKey <authKey>`, `Msg91 auth key.`)
2512+
.option(`--senderId <senderId>`, `Msg91 Sender ID.`)
2513+
.option(`--authKey <authKey>`, `Msg91 Auth Key.`)
2514+
.option(`--from <from>`, `Sender number.`)
25152515
.action(actionRunner(messagingUpdateMsg91Provider))
25162516

25172517
messaging

lib/questions.js

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
const { localConfig } = require('./config');
22
const { projectsList } = require('./commands/projects');
33
const { functionsListRuntimes } = require('./commands/functions');
4+
const { accountListMfaFactors } = require("./commands/account");
5+
const { sdkForConsole } = require("./sdks");
6+
47
const { databasesList } = require('./commands/databases');
58
const JSONbig = require("json-bigint")({ storeAsString: false });
69

@@ -387,7 +390,57 @@ const questionsDeployTeams = [
387390
name: "override",
388391
message: 'Are you sure you want to override this team? This can lead to loss of data! Type "YES" to confirm.'
389392
},
390-
]
393+
];
394+
395+
const questionsListFactors = [
396+
{
397+
type: "list",
398+
name: "factor",
399+
message: "Your account is protected by multiple factors. Which factor would you like to use to authenticate?",
400+
choices: async () => {
401+
let client = await sdkForConsole(false);
402+
const factors = await accountListMfaFactors({
403+
sdk: client,
404+
parseOutput: false
405+
});
406+
407+
const choices = [
408+
{
409+
name: `TOTP (Time-based One-time Password)`,
410+
value: 'totp'
411+
},
412+
{
413+
name: `E-mail`,
414+
value: 'email'
415+
},
416+
{
417+
name: `Phone (SMS)`,
418+
value: 'phone'
419+
},
420+
{
421+
name: `Recovery code`,
422+
value: 'recoveryCode'
423+
}
424+
].filter((ch) => factors[ch.value] === true);
425+
426+
return choices;
427+
}
428+
}
429+
];
430+
431+
const questionsMfaChallenge = [
432+
{
433+
type: "input",
434+
name: "otp",
435+
message: "Enter OTP",
436+
validate(value) {
437+
if (!value) {
438+
return "Please enter OTP";
439+
}
440+
return true;
441+
},
442+
}
443+
];
391444

392445
module.exports = {
393446
questionsInitProject,
@@ -398,5 +451,7 @@ module.exports = {
398451
questionsDeployCollections,
399452
questionsDeployBuckets,
400453
questionsDeployTeams,
401-
questionsGetEntrypoint
454+
questionsGetEntrypoint,
455+
questionsListFactors,
456+
questionsMfaChallenge
402457
};

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "appwrite-cli",
33
"homepage": "https://appwrite.io/support",
44
"description": "Appwrite is an open-source self-hosted backend server that abstract and simplify complex and repetitive development tasks behind a very simple REST API",
5-
"version": "5.0.2",
5+
"version": "5.0.3",
66
"license": "BSD-3-Clause",
77
"main": "index.js",
88
"bin": {

scoop/appwrite.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
{
22
"$schema": "https://raw.githubusercontent.com/ScoopInstaller/Scoop/master/schema.json",
3-
"version": "5.0.2",
3+
"version": "5.0.3",
44
"description": "The Appwrite CLI is a command-line application that allows you to interact with Appwrite and perform server-side tasks using your terminal.",
55
"homepage": "https://github.com/appwrite/sdk-for-cli",
66
"license": "BSD-3-Clause",
77
"architecture": {
88
"64bit": {
9-
"url": "https://github.com/appwrite/sdk-for-cli/releases/download/5.0.2/appwrite-cli-win-x64.exe",
9+
"url": "https://github.com/appwrite/sdk-for-cli/releases/download/5.0.3/appwrite-cli-win-x64.exe",
1010
"bin": [
1111
[
1212
"appwrite-cli-win-x64.exe",
@@ -15,7 +15,7 @@
1515
]
1616
},
1717
"arm64": {
18-
"url": "https://github.com/appwrite/sdk-for-cli/releases/download/5.0.2/appwrite-cli-win-arm64.exe",
18+
"url": "https://github.com/appwrite/sdk-for-cli/releases/download/5.0.3/appwrite-cli-win-arm64.exe",
1919
"bin": [
2020
[
2121
"appwrite-cli-win-arm64.exe",

0 commit comments

Comments
 (0)