diff --git a/README.md b/README.md index a3537d0..d2e0903 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Appwrite is an open-source backend as a service server that abstract and simplify complex and repetitive development tasks behind a very simple to use REST API. Appwrite aims to help you develop your apps faster and in a more secure way. Use the Android SDK to integrate your app with the Appwrite server to easily start interacting with all of Appwrite backend APIs and tools. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs) -![Appwrite](https://appwrite.io/images/github.png) +![Appwrite](https://github.com/appwrite/appwrite/raw/main/public/images/github.png) ## Installation @@ -38,7 +38,7 @@ repositories { Next, add the dependency to your project's `build.gradle(.kts)` file: ```groovy -implementation("io.appwrite:sdk-for-android:5.0.0-rc.6") +implementation("io.appwrite:sdk-for-android:5.0.0") ``` ### Maven @@ -49,7 +49,7 @@ Add this to your project's `pom.xml` file: io.appwrite sdk-for-android - 5.0.0-rc.6 + 5.0.0 ``` diff --git a/docs/examples/java/account/add-authenticator.md b/docs/examples/java/account/create-mfa-authenticator.md similarity index 94% rename from docs/examples/java/account/add-authenticator.md rename to docs/examples/java/account/create-mfa-authenticator.md index e81255d..cc64341 100644 --- a/docs/examples/java/account/add-authenticator.md +++ b/docs/examples/java/account/create-mfa-authenticator.md @@ -9,7 +9,7 @@ Client client = new Client(context) Account account = new Account(client); -account.addAuthenticator( +account.createMfaAuthenticator( AuthenticatorType.TOTP, // type new CoroutineCallback<>((result, error) -> { if (error != null) { diff --git a/docs/examples/java/account/create-challenge.md b/docs/examples/java/account/create-mfa-challenge.md similarity index 88% rename from docs/examples/java/account/create-challenge.md rename to docs/examples/java/account/create-mfa-challenge.md index 7a31920..a2c2aa4 100644 --- a/docs/examples/java/account/create-challenge.md +++ b/docs/examples/java/account/create-mfa-challenge.md @@ -9,8 +9,8 @@ Client client = new Client(context) Account account = new Account(client); -account.createChallenge( - AuthenticationFactor.TOTP, // factor +account.createMfaChallenge( + AuthenticationFactor.EMAIL, // factor new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); diff --git a/docs/examples/java/account/create-mfa-recovery-codes.md b/docs/examples/java/account/create-mfa-recovery-codes.md new file mode 100644 index 0000000..8ed8573 --- /dev/null +++ b/docs/examples/java/account/create-mfa-recovery-codes.md @@ -0,0 +1,18 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Account; + +Client client = new Client(context) + .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint + .setProject("5df5acd0d48c2"); // Your project ID + +Account account = new Account(client); + +account.createMfaRecoveryCodes(new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + Log.d("Appwrite", result.toString()); +})); diff --git a/docs/examples/java/account/verify-authenticator.md b/docs/examples/java/account/delete-mfa-authenticator.md similarity index 95% rename from docs/examples/java/account/verify-authenticator.md rename to docs/examples/java/account/delete-mfa-authenticator.md index c73ac43..e821930 100644 --- a/docs/examples/java/account/verify-authenticator.md +++ b/docs/examples/java/account/delete-mfa-authenticator.md @@ -9,7 +9,7 @@ Client client = new Client(context) Account account = new Account(client); -account.verifyAuthenticator( +account.deleteMfaAuthenticator( AuthenticatorType.TOTP, // type "", // otp new CoroutineCallback<>((result, error) -> { diff --git a/docs/examples/java/account/get-mfa-recovery-codes.md b/docs/examples/java/account/get-mfa-recovery-codes.md new file mode 100644 index 0000000..14e5023 --- /dev/null +++ b/docs/examples/java/account/get-mfa-recovery-codes.md @@ -0,0 +1,18 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Account; + +Client client = new Client(context) + .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint + .setProject("5df5acd0d48c2"); // Your project ID + +Account account = new Account(client); + +account.getMfaRecoveryCodes(new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + Log.d("Appwrite", result.toString()); +})); diff --git a/docs/examples/java/account/list-factors.md b/docs/examples/java/account/list-mfa-factors.md similarity index 86% rename from docs/examples/java/account/list-factors.md rename to docs/examples/java/account/list-mfa-factors.md index e2d92b5..e1a6fa6 100644 --- a/docs/examples/java/account/list-factors.md +++ b/docs/examples/java/account/list-mfa-factors.md @@ -8,7 +8,7 @@ Client client = new Client(context) Account account = new Account(client); -account.listFactors(new CoroutineCallback<>((result, error) -> { +account.listMfaFactors(new CoroutineCallback<>((result, error) -> { if (error != null) { error.printStackTrace(); return; diff --git a/docs/examples/java/account/delete-authenticator.md b/docs/examples/java/account/update-mfa-authenticator.md similarity index 95% rename from docs/examples/java/account/delete-authenticator.md rename to docs/examples/java/account/update-mfa-authenticator.md index c988cfa..44bb7f0 100644 --- a/docs/examples/java/account/delete-authenticator.md +++ b/docs/examples/java/account/update-mfa-authenticator.md @@ -9,7 +9,7 @@ Client client = new Client(context) Account account = new Account(client); -account.deleteAuthenticator( +account.updateMfaAuthenticator( AuthenticatorType.TOTP, // type "", // otp new CoroutineCallback<>((result, error) -> { diff --git a/docs/examples/java/account/update-challenge.md b/docs/examples/java/account/update-mfa-challenge.md similarity index 95% rename from docs/examples/java/account/update-challenge.md rename to docs/examples/java/account/update-mfa-challenge.md index b2953e3..e30c733 100644 --- a/docs/examples/java/account/update-challenge.md +++ b/docs/examples/java/account/update-mfa-challenge.md @@ -8,7 +8,7 @@ Client client = new Client(context) Account account = new Account(client); -account.updateChallenge( +account.updateMfaChallenge( "", // challengeId "", // otp new CoroutineCallback<>((result, error) -> { diff --git a/docs/examples/java/account/update-mfa-recovery-codes.md b/docs/examples/java/account/update-mfa-recovery-codes.md new file mode 100644 index 0000000..880d478 --- /dev/null +++ b/docs/examples/java/account/update-mfa-recovery-codes.md @@ -0,0 +1,18 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Account; + +Client client = new Client(context) + .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint + .setProject("5df5acd0d48c2"); // Your project ID + +Account account = new Account(client); + +account.updateMfaRecoveryCodes(new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + Log.d("Appwrite", result.toString()); +})); diff --git a/docs/examples/kotlin/account/add-authenticator.md b/docs/examples/kotlin/account/create-mfa-authenticator.md similarity index 89% rename from docs/examples/kotlin/account/add-authenticator.md rename to docs/examples/kotlin/account/create-mfa-authenticator.md index f96c175..f2ff748 100644 --- a/docs/examples/kotlin/account/add-authenticator.md +++ b/docs/examples/kotlin/account/create-mfa-authenticator.md @@ -9,6 +9,6 @@ val client = Client(context) val account = Account(client) -val result = account.addAuthenticator( +val result = account.createMfaAuthenticator( type = AuthenticatorType.TOTP, ) \ No newline at end of file diff --git a/docs/examples/kotlin/account/create-challenge.md b/docs/examples/kotlin/account/create-mfa-challenge.md similarity index 80% rename from docs/examples/kotlin/account/create-challenge.md rename to docs/examples/kotlin/account/create-mfa-challenge.md index 1018b96..d43aa39 100644 --- a/docs/examples/kotlin/account/create-challenge.md +++ b/docs/examples/kotlin/account/create-mfa-challenge.md @@ -9,6 +9,6 @@ val client = Client(context) val account = Account(client) -val result = account.createChallenge( - factor = AuthenticationFactor.TOTP, +val result = account.createMfaChallenge( + factor = AuthenticationFactor.EMAIL, ) \ No newline at end of file diff --git a/docs/examples/kotlin/account/create-mfa-recovery-codes.md b/docs/examples/kotlin/account/create-mfa-recovery-codes.md new file mode 100644 index 0000000..be25e74 --- /dev/null +++ b/docs/examples/kotlin/account/create-mfa-recovery-codes.md @@ -0,0 +1,11 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Account + +val client = Client(context) + .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint + .setProject("5df5acd0d48c2") // Your project ID + +val account = Account(client) + +val result = account.createMfaRecoveryCodes() diff --git a/docs/examples/kotlin/account/verify-authenticator.md b/docs/examples/kotlin/account/delete-mfa-authenticator.md similarity index 89% rename from docs/examples/kotlin/account/verify-authenticator.md rename to docs/examples/kotlin/account/delete-mfa-authenticator.md index 9c306d4..c07afd0 100644 --- a/docs/examples/kotlin/account/verify-authenticator.md +++ b/docs/examples/kotlin/account/delete-mfa-authenticator.md @@ -9,7 +9,7 @@ val client = Client(context) val account = Account(client) -val result = account.verifyAuthenticator( +val result = account.deleteMfaAuthenticator( type = AuthenticatorType.TOTP, otp = "", ) \ No newline at end of file diff --git a/docs/examples/kotlin/account/get-mfa-recovery-codes.md b/docs/examples/kotlin/account/get-mfa-recovery-codes.md new file mode 100644 index 0000000..4a1652c --- /dev/null +++ b/docs/examples/kotlin/account/get-mfa-recovery-codes.md @@ -0,0 +1,11 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Account + +val client = Client(context) + .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint + .setProject("5df5acd0d48c2") // Your project ID + +val account = Account(client) + +val result = account.getMfaRecoveryCodes() diff --git a/docs/examples/kotlin/account/list-factors.md b/docs/examples/kotlin/account/list-mfa-factors.md similarity index 88% rename from docs/examples/kotlin/account/list-factors.md rename to docs/examples/kotlin/account/list-mfa-factors.md index 05ba2b8..9f8572c 100644 --- a/docs/examples/kotlin/account/list-factors.md +++ b/docs/examples/kotlin/account/list-mfa-factors.md @@ -8,4 +8,4 @@ val client = Client(context) val account = Account(client) -val result = account.listFactors() +val result = account.listMfaFactors() diff --git a/docs/examples/kotlin/account/delete-authenticator.md b/docs/examples/kotlin/account/update-mfa-authenticator.md similarity index 89% rename from docs/examples/kotlin/account/delete-authenticator.md rename to docs/examples/kotlin/account/update-mfa-authenticator.md index bc532b8..8b19680 100644 --- a/docs/examples/kotlin/account/delete-authenticator.md +++ b/docs/examples/kotlin/account/update-mfa-authenticator.md @@ -9,7 +9,7 @@ val client = Client(context) val account = Account(client) -val result = account.deleteAuthenticator( +val result = account.updateMfaAuthenticator( type = AuthenticatorType.TOTP, otp = "", ) \ No newline at end of file diff --git a/docs/examples/kotlin/account/update-challenge.md b/docs/examples/kotlin/account/update-mfa-challenge.md similarity index 89% rename from docs/examples/kotlin/account/update-challenge.md rename to docs/examples/kotlin/account/update-mfa-challenge.md index 2a82bfb..fe4cb1e 100644 --- a/docs/examples/kotlin/account/update-challenge.md +++ b/docs/examples/kotlin/account/update-mfa-challenge.md @@ -8,7 +8,7 @@ val client = Client(context) val account = Account(client) -val result = account.updateChallenge( +val result = account.updateMfaChallenge( challengeId = "", otp = "", ) \ No newline at end of file diff --git a/docs/examples/kotlin/account/update-mfa-recovery-codes.md b/docs/examples/kotlin/account/update-mfa-recovery-codes.md new file mode 100644 index 0000000..f39b7c6 --- /dev/null +++ b/docs/examples/kotlin/account/update-mfa-recovery-codes.md @@ -0,0 +1,11 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Account + +val client = Client(context) + .setEndpoint("https://cloud.appwrite.io/v1") // Your API Endpoint + .setProject("5df5acd0d48c2") // Your project ID + +val account = Account(client) + +val result = account.updateMfaRecoveryCodes() diff --git a/library/src/main/java/io/appwrite/Client.kt b/library/src/main/java/io/appwrite/Client.kt index 68e4233..4eb2557 100644 --- a/library/src/main/java/io/appwrite/Client.kt +++ b/library/src/main/java/io/appwrite/Client.kt @@ -83,7 +83,7 @@ class Client @JvmOverloads constructor( "x-sdk-name" to "Android", "x-sdk-platform" to "client", "x-sdk-language" to "android", - "x-sdk-version" to "5.0.0-rc.6", + "x-sdk-version" to "5.0.0", "x-appwrite-response-format" to "1.5.0" ) config = mutableMapOf() diff --git a/library/src/main/java/io/appwrite/enums/AuthenticationFactor.kt b/library/src/main/java/io/appwrite/enums/AuthenticationFactor.kt index 7aca6e5..cf294ca 100644 --- a/library/src/main/java/io/appwrite/enums/AuthenticationFactor.kt +++ b/library/src/main/java/io/appwrite/enums/AuthenticationFactor.kt @@ -3,12 +3,14 @@ package io.appwrite.enums import com.google.gson.annotations.SerializedName enum class AuthenticationFactor(val value: String) { - @SerializedName("totp") - TOTP("totp"), + @SerializedName("email") + EMAIL("email"), @SerializedName("phone") PHONE("phone"), - @SerializedName("email") - EMAIL("email"); + @SerializedName("totp") + TOTP("totp"), + @SerializedName("recoverycode") + RECOVERYCODE("recoverycode"); override fun toString() = value } \ No newline at end of file diff --git a/library/src/main/java/io/appwrite/enums/Browser.kt b/library/src/main/java/io/appwrite/enums/Browser.kt index f71024a..9800111 100644 --- a/library/src/main/java/io/appwrite/enums/Browser.kt +++ b/library/src/main/java/io/appwrite/enums/Browser.kt @@ -6,11 +6,11 @@ enum class Browser(val value: String) { @SerializedName("aa") AVANT_BROWSER("aa"), @SerializedName("an") - ANDROID_WEB_VIEW_BETA("an"), + ANDROID_WEBVIEW_BETA("an"), @SerializedName("ch") GOOGLE_CHROME("ch"), @SerializedName("ci") - GOOGLE_CHROMEI_OS("ci"), + GOOGLE_CHROME_IOS("ci"), @SerializedName("cm") GOOGLE_CHROME_MOBILE("cm"), @SerializedName("cr") @@ -24,7 +24,7 @@ enum class Browser(val value: String) { @SerializedName("ps") MICROSOFT_EDGE("ps"), @SerializedName("oi") - MICROSOFT_EDGEI_OS("oi"), + MICROSOFT_EDGE_IOS("oi"), @SerializedName("om") OPERA_MINI("om"), @SerializedName("op") diff --git a/library/src/main/java/io/appwrite/enums/Flag.kt b/library/src/main/java/io/appwrite/enums/Flag.kt index af5889a..d389103 100644 --- a/library/src/main/java/io/appwrite/enums/Flag.kt +++ b/library/src/main/java/io/appwrite/enums/Flag.kt @@ -18,7 +18,7 @@ enum class Flag(val value: String) { @SerializedName("am") ARMENIA("am"), @SerializedName("ag") - ANTIGUAAND_BARBUDA("ag"), + ANTIGUA_AND_BARBUDA("ag"), @SerializedName("au") AUSTRALIA("au"), @SerializedName("at") @@ -42,7 +42,7 @@ enum class Flag(val value: String) { @SerializedName("bs") BAHAMAS("bs"), @SerializedName("ba") - BOSNIAAND_HERZEGOVINA("ba"), + BOSNIA_AND_HERZEGOVINA("ba"), @SerializedName("by") BELARUS("by"), @SerializedName("bz") @@ -70,13 +70,13 @@ enum class Flag(val value: String) { @SerializedName("cn") CHINA("cn"), @SerializedName("ci") - CTED_IVOIRE("ci"), + COTE_DIVOIRE("ci"), @SerializedName("cm") CAMEROON("cm"), @SerializedName("cd") - DEMOCRATIC_REPUBLICOFTHE_CONGO("cd"), + DEMOCRATIC_REPUBLIC_OF_THE_CONGO("cd"), @SerializedName("cg") - REPUBLICOFTHE_CONGO("cg"), + REPUBLIC_OF_THE_CONGO("cg"), @SerializedName("co") COLOMBIA("co"), @SerializedName("km") @@ -122,7 +122,7 @@ enum class Flag(val value: String) { @SerializedName("fr") FRANCE("fr"), @SerializedName("fm") - MICRONESIA_FEDERATED_STATESOF("fm"), + MICRONESIA_FEDERATED_STATES_OF("fm"), @SerializedName("ga") GABON("ga"), @SerializedName("gb") @@ -162,7 +162,7 @@ enum class Flag(val value: String) { @SerializedName("ie") IRELAND("ie"), @SerializedName("ir") - IRAN_ISLAMIC_REPUBLICOF("ir"), + IRAN_ISLAMIC_REPUBLIC_OF("ir"), @SerializedName("iq") IRAQ("iq"), @SerializedName("is") @@ -188,7 +188,7 @@ enum class Flag(val value: String) { @SerializedName("ki") KIRIBATI("ki"), @SerializedName("kn") - SAINT_KITTSAND_NEVIS("kn"), + SAINT_KITTS_AND_NEVIS("kn"), @SerializedName("kr") SOUTH_KOREA("kr"), @SerializedName("kw") @@ -322,7 +322,7 @@ enum class Flag(val value: String) { @SerializedName("ss") SOUTH_SUDAN("ss"), @SerializedName("st") - SAO_TOMEAND_PRINCIPE("st"), + SAO_TOME_AND_PRINCIPE("st"), @SerializedName("sr") SURINAME("sr"), @SerializedName("sk") @@ -352,7 +352,7 @@ enum class Flag(val value: String) { @SerializedName("to") TONGA("to"), @SerializedName("tt") - TRINIDADAND_TOBAGO("tt"), + TRINIDAD_AND_TOBAGO("tt"), @SerializedName("tn") TUNISIA("tn"), @SerializedName("tr") @@ -374,7 +374,7 @@ enum class Flag(val value: String) { @SerializedName("va") VATICAN_CITY("va"), @SerializedName("vc") - SAINT_VINCENTANDTHE_GRENADINES("vc"), + SAINT_VINCENT_AND_THE_GRENADINES("vc"), @SerializedName("ve") VENEZUELA("ve"), @SerializedName("vn") diff --git a/library/src/main/java/io/appwrite/enums/ImageGravity.kt b/library/src/main/java/io/appwrite/enums/ImageGravity.kt index 0e8325d..45f8d88 100644 --- a/library/src/main/java/io/appwrite/enums/ImageGravity.kt +++ b/library/src/main/java/io/appwrite/enums/ImageGravity.kt @@ -6,21 +6,21 @@ enum class ImageGravity(val value: String) { @SerializedName("center") CENTER("center"), @SerializedName("top-left") - TOPLEFT("top-left"), + TOP_LEFT("top-left"), @SerializedName("top") TOP("top"), @SerializedName("top-right") - TOPRIGHT("top-right"), + TOP_RIGHT("top-right"), @SerializedName("left") LEFT("left"), @SerializedName("right") RIGHT("right"), @SerializedName("bottom-left") - BOTTOMLEFT("bottom-left"), + BOTTOM_LEFT("bottom-left"), @SerializedName("bottom") BOTTOM("bottom"), @SerializedName("bottom-right") - BOTTOMRIGHT("bottom-right"); + BOTTOM_RIGHT("bottom-right"); override fun toString() = value } \ No newline at end of file diff --git a/library/src/main/java/io/appwrite/enums/OAuthProvider.kt b/library/src/main/java/io/appwrite/enums/OAuthProvider.kt index 2b96d63..dc1b9b3 100644 --- a/library/src/main/java/io/appwrite/enums/OAuthProvider.kt +++ b/library/src/main/java/io/appwrite/enums/OAuthProvider.kt @@ -50,7 +50,7 @@ enum class OAuthProvider(val value: String) { @SerializedName("paypal") PAYPAL("paypal"), @SerializedName("paypalSandbox") - PAYPAL_SANDBOX("paypalSandbox"), + PAYPALSANDBOX("paypalSandbox"), @SerializedName("podio") PODIO("podio"), @SerializedName("salesforce") @@ -64,7 +64,7 @@ enum class OAuthProvider(val value: String) { @SerializedName("tradeshift") TRADESHIFT("tradeshift"), @SerializedName("tradeshiftBox") - TRADESHIFT_BOX("tradeshiftBox"), + TRADESHIFTBOX("tradeshiftBox"), @SerializedName("twitch") TWITCH("twitch"), @SerializedName("wordpress") diff --git a/library/src/main/java/io/appwrite/models/MfaRecoveryCodes.kt b/library/src/main/java/io/appwrite/models/MfaRecoveryCodes.kt new file mode 100644 index 0000000..ad8bc45 --- /dev/null +++ b/library/src/main/java/io/appwrite/models/MfaRecoveryCodes.kt @@ -0,0 +1,30 @@ +package io.appwrite.models + +import com.google.gson.annotations.SerializedName +import io.appwrite.extensions.jsonCast + +/** + * MFA Recovery Codes + */ +data class MfaRecoveryCodes( + /** + * Recovery codes. + */ + @SerializedName("recoveryCodes") + val recoveryCodes: List, + +) { + fun toMap(): Map = mapOf( + "recoveryCodes" to recoveryCodes as Any, + ) + + companion object { + + @Suppress("UNCHECKED_CAST") + fun from( + map: Map, + ) = MfaRecoveryCodes( + recoveryCodes = map["recoveryCodes"] as List, + ) + } +} \ No newline at end of file diff --git a/library/src/main/java/io/appwrite/models/MfaType.kt b/library/src/main/java/io/appwrite/models/MfaType.kt index c3d8d53..9c784a9 100644 --- a/library/src/main/java/io/appwrite/models/MfaType.kt +++ b/library/src/main/java/io/appwrite/models/MfaType.kt @@ -7,12 +7,6 @@ import io.appwrite.extensions.jsonCast * MFAType */ data class MfaType( - /** - * Backup codes. - */ - @SerializedName("backups") - val backups: List, - /** * Secret token used for TOTP factor. */ @@ -27,7 +21,6 @@ data class MfaType( ) { fun toMap(): Map = mapOf( - "backups" to backups as Any, "secret" to secret as Any, "uri" to uri as Any, ) @@ -38,7 +31,6 @@ data class MfaType( fun from( map: Map, ) = MfaType( - backups = map["backups"] as List, secret = map["secret"] as String, uri = map["uri"] as String, ) diff --git a/library/src/main/java/io/appwrite/models/Session.kt b/library/src/main/java/io/appwrite/models/Session.kt index da71926..1eaed4d 100644 --- a/library/src/main/java/io/appwrite/models/Session.kt +++ b/library/src/main/java/io/appwrite/models/Session.kt @@ -169,6 +169,12 @@ data class Session( @SerializedName("secret") val secret: String, + /** + * Most recent date in ISO 8601 format when the session successfully passed MFA challenge. + */ + @SerializedName("mfaUpdatedAt") + val mfaUpdatedAt: String, + ) { fun toMap(): Map = mapOf( "\$id" to id as Any, @@ -198,6 +204,7 @@ data class Session( "current" to current as Any, "factors" to factors as Any, "secret" to secret as Any, + "mfaUpdatedAt" to mfaUpdatedAt as Any, ) companion object { @@ -233,6 +240,7 @@ data class Session( current = map["current"] as Boolean, factors = map["factors"] as List, secret = map["secret"] as String, + mfaUpdatedAt = map["mfaUpdatedAt"] as String, ) } } \ No newline at end of file diff --git a/library/src/main/java/io/appwrite/models/User.kt b/library/src/main/java/io/appwrite/models/User.kt index 4c776b9..095467a 100644 --- a/library/src/main/java/io/appwrite/models/User.kt +++ b/library/src/main/java/io/appwrite/models/User.kt @@ -103,12 +103,6 @@ data class User( @SerializedName("mfa") val mfa: Boolean, - /** - * TOTP status. - */ - @SerializedName("totp") - val totp: Boolean, - /** * User preferences as a key-value object */ @@ -145,7 +139,6 @@ data class User( "emailVerification" to emailVerification as Any, "phoneVerification" to phoneVerification as Any, "mfa" to mfa as Any, - "totp" to totp as Any, "prefs" to prefs.toMap() as Any, "targets" to targets.map { it.toMap() } as Any, "accessedAt" to accessedAt as Any, @@ -169,7 +162,6 @@ data class User( emailVerification: Boolean, phoneVerification: Boolean, mfa: Boolean, - totp: Boolean, prefs: Preferences>, targets: List, accessedAt: String, @@ -190,7 +182,6 @@ data class User( emailVerification, phoneVerification, mfa, - totp, prefs, targets, accessedAt, @@ -217,7 +208,6 @@ data class User( emailVerification = map["emailVerification"] as Boolean, phoneVerification = map["phoneVerification"] as Boolean, mfa = map["mfa"] as Boolean, - totp = map["totp"] as Boolean, prefs = Preferences.from(map = map["prefs"] as Map, nestedType), targets = (map["targets"] as List>).map { Target.from(map = it) }, accessedAt = map["accessedAt"] as String, diff --git a/library/src/main/java/io/appwrite/services/Account.kt b/library/src/main/java/io/appwrite/services/Account.kt index 0abdfd2..c4204c0 100644 --- a/library/src/main/java/io/appwrite/services/Account.kt +++ b/library/src/main/java/io/appwrite/services/Account.kt @@ -369,115 +369,18 @@ class Account(client: Client) : Service(client) { nestedType = classOf(), ) - /** - * Create 2FA Challenge - * - * - * - * @param factor Factor used for verification. - * @return [io.appwrite.models.MfaChallenge] - */ - suspend fun createChallenge( - factor: AuthenticationFactor, - ): io.appwrite.models.MfaChallenge { - val apiPath = "/account/mfa/challenge" - - val apiParams = mutableMapOf( - "factor" to factor, - ) - val apiHeaders = mutableMapOf( - "content-type" to "application/json", - ) - val converter: (Any) -> io.appwrite.models.MfaChallenge = { - @Suppress("UNCHECKED_CAST") - io.appwrite.models.MfaChallenge.from(map = it as Map) - } - return client.call( - "POST", - apiPath, - apiHeaders, - apiParams, - responseType = io.appwrite.models.MfaChallenge::class.java, - converter, - ) - } - - - /** - * Create MFA Challenge (confirmation) - * - * Complete the MFA challenge by providing the one-time password. - * - * @param challengeId ID of the challenge. - * @param otp Valid verification token. - * @return [Any] - */ - suspend fun updateChallenge( - challengeId: String, - otp: String, - ): Any { - val apiPath = "/account/mfa/challenge" - - val apiParams = mutableMapOf( - "challengeId" to challengeId, - "otp" to otp, - ) - val apiHeaders = mutableMapOf( - "content-type" to "application/json", - ) - return client.call( - "PUT", - apiPath, - apiHeaders, - apiParams, - responseType = Any::class.java, - ) - } - - - /** - * List Factors - * - * List the factors available on the account to be used as a MFA challange. - * - * @return [io.appwrite.models.MfaFactors] - */ - suspend fun listFactors( - ): io.appwrite.models.MfaFactors { - val apiPath = "/account/mfa/factors" - - val apiParams = mutableMapOf( - ) - val apiHeaders = mutableMapOf( - "content-type" to "application/json", - ) - val converter: (Any) -> io.appwrite.models.MfaFactors = { - @Suppress("UNCHECKED_CAST") - io.appwrite.models.MfaFactors.from(map = it as Map) - } - return client.call( - "GET", - apiPath, - apiHeaders, - apiParams, - responseType = io.appwrite.models.MfaFactors::class.java, - converter, - ) - } - - /** * Add Authenticator * * Add an authenticator app to be used as an MFA factor. Verify the authenticator using the [verify authenticator](/docs/references/cloud/client-web/account#verifyAuthenticator) method. * - * @param type Type of authenticator. + * @param type Type of authenticator. Must be `totp` * @return [io.appwrite.models.MfaType] */ - suspend fun addAuthenticator( + suspend fun createMfaAuthenticator( type: AuthenticatorType, ): io.appwrite.models.MfaType { - val apiPath = "/account/mfa/{type}" + val apiPath = "/account/mfa/authenticators/{type}" .replace("{type}", type.value) val apiParams = mutableMapOf( @@ -509,12 +412,12 @@ class Account(client: Client) : Service(client) { * @param otp Valid verification token. * @return [io.appwrite.models.User] */ - suspend fun verifyAuthenticator( + suspend fun updateMfaAuthenticator( type: AuthenticatorType, otp: String, nestedType: Class, ): io.appwrite.models.User { - val apiPath = "/account/mfa/{type}" + val apiPath = "/account/mfa/authenticators/{type}" .replace("{type}", type.value) val apiParams = mutableMapOf( @@ -547,10 +450,10 @@ class Account(client: Client) : Service(client) { * @return [io.appwrite.models.User] */ @Throws(AppwriteException::class) - suspend fun verifyAuthenticator( + suspend fun updateMfaAuthenticator( type: AuthenticatorType, otp: String, - ): io.appwrite.models.User> = verifyAuthenticator( + ): io.appwrite.models.User> = updateMfaAuthenticator( type, otp, nestedType = classOf(), @@ -565,12 +468,12 @@ class Account(client: Client) : Service(client) { * @param otp Valid verification token. * @return [io.appwrite.models.User] */ - suspend fun deleteAuthenticator( + suspend fun deleteMfaAuthenticator( type: AuthenticatorType, otp: String, nestedType: Class, ): io.appwrite.models.User { - val apiPath = "/account/mfa/{type}" + val apiPath = "/account/mfa/authenticators/{type}" .replace("{type}", type.value) val apiParams = mutableMapOf( @@ -603,15 +506,205 @@ class Account(client: Client) : Service(client) { * @return [io.appwrite.models.User] */ @Throws(AppwriteException::class) - suspend fun deleteAuthenticator( + suspend fun deleteMfaAuthenticator( type: AuthenticatorType, otp: String, - ): io.appwrite.models.User> = deleteAuthenticator( + ): io.appwrite.models.User> = deleteMfaAuthenticator( type, otp, nestedType = classOf(), ) + /** + * Create 2FA Challenge + * + * Begin the process of MFA verification after sign-in. Finish the flow with [updateMfaChallenge](/docs/references/cloud/client-web/account#updateMfaChallenge) method. + * + * @param factor Factor used for verification. Must be one of following: `email`, `phone`, `totp`, `recoveryCode`. + * @return [io.appwrite.models.MfaChallenge] + */ + suspend fun createMfaChallenge( + factor: AuthenticationFactor, + ): io.appwrite.models.MfaChallenge { + val apiPath = "/account/mfa/challenge" + + val apiParams = mutableMapOf( + "factor" to factor, + ) + val apiHeaders = mutableMapOf( + "content-type" to "application/json", + ) + val converter: (Any) -> io.appwrite.models.MfaChallenge = { + @Suppress("UNCHECKED_CAST") + io.appwrite.models.MfaChallenge.from(map = it as Map) + } + return client.call( + "POST", + apiPath, + apiHeaders, + apiParams, + responseType = io.appwrite.models.MfaChallenge::class.java, + converter, + ) + } + + + /** + * Create MFA Challenge (confirmation) + * + * Complete the MFA challenge by providing the one-time password. Finish the process of MFA verification by providing the one-time password. To begin the flow, use [createMfaChallenge](/docs/references/cloud/client-web/account#createMfaChallenge) method. + * + * @param challengeId ID of the challenge. + * @param otp Valid verification token. + * @return [Any] + */ + suspend fun updateMfaChallenge( + challengeId: String, + otp: String, + ): Any { + val apiPath = "/account/mfa/challenge" + + val apiParams = mutableMapOf( + "challengeId" to challengeId, + "otp" to otp, + ) + val apiHeaders = mutableMapOf( + "content-type" to "application/json", + ) + return client.call( + "PUT", + apiPath, + apiHeaders, + apiParams, + responseType = Any::class.java, + ) + } + + + /** + * List Factors + * + * List the factors available on the account to be used as a MFA challange. + * + * @return [io.appwrite.models.MfaFactors] + */ + suspend fun listMfaFactors( + ): io.appwrite.models.MfaFactors { + val apiPath = "/account/mfa/factors" + + val apiParams = mutableMapOf( + ) + val apiHeaders = mutableMapOf( + "content-type" to "application/json", + ) + val converter: (Any) -> io.appwrite.models.MfaFactors = { + @Suppress("UNCHECKED_CAST") + io.appwrite.models.MfaFactors.from(map = it as Map) + } + return client.call( + "GET", + apiPath, + apiHeaders, + apiParams, + responseType = io.appwrite.models.MfaFactors::class.java, + converter, + ) + } + + + /** + * Get MFA Recovery Codes + * + * Get recovery codes that can be used as backup for MFA flow. Before getting codes, they must be generated using [createMfaRecoveryCodes](/docs/references/cloud/client-web/account#createMfaRecoveryCodes) method. An OTP challenge is required to read recovery codes. + * + * @return [io.appwrite.models.MfaRecoveryCodes] + */ + suspend fun getMfaRecoveryCodes( + ): io.appwrite.models.MfaRecoveryCodes { + val apiPath = "/account/mfa/recovery-codes" + + val apiParams = mutableMapOf( + ) + val apiHeaders = mutableMapOf( + "content-type" to "application/json", + ) + val converter: (Any) -> io.appwrite.models.MfaRecoveryCodes = { + @Suppress("UNCHECKED_CAST") + io.appwrite.models.MfaRecoveryCodes.from(map = it as Map) + } + return client.call( + "GET", + apiPath, + apiHeaders, + apiParams, + responseType = io.appwrite.models.MfaRecoveryCodes::class.java, + converter, + ) + } + + + /** + * Create MFA Recovery Codes + * + * Generate recovery codes as backup for MFA flow. It's recommended to generate and show then immediately after user successfully adds their authehticator. Recovery codes can be used as a MFA verification type in [createMfaChallenge](/docs/references/cloud/client-web/account#createMfaChallenge) method. + * + * @return [io.appwrite.models.MfaRecoveryCodes] + */ + suspend fun createMfaRecoveryCodes( + ): io.appwrite.models.MfaRecoveryCodes { + val apiPath = "/account/mfa/recovery-codes" + + val apiParams = mutableMapOf( + ) + val apiHeaders = mutableMapOf( + "content-type" to "application/json", + ) + val converter: (Any) -> io.appwrite.models.MfaRecoveryCodes = { + @Suppress("UNCHECKED_CAST") + io.appwrite.models.MfaRecoveryCodes.from(map = it as Map) + } + return client.call( + "POST", + apiPath, + apiHeaders, + apiParams, + responseType = io.appwrite.models.MfaRecoveryCodes::class.java, + converter, + ) + } + + + /** + * Regenerate MFA Recovery Codes + * + * Regenerate recovery codes that can be used as backup for MFA flow. Before regenerating codes, they must be first generated using [createMfaRecoveryCodes](/docs/references/cloud/client-web/account#createMfaRecoveryCodes) method. An OTP challenge is required to regenreate recovery codes. + * + * @return [io.appwrite.models.MfaRecoveryCodes] + */ + suspend fun updateMfaRecoveryCodes( + ): io.appwrite.models.MfaRecoveryCodes { + val apiPath = "/account/mfa/recovery-codes" + + val apiParams = mutableMapOf( + ) + val apiHeaders = mutableMapOf( + "content-type" to "application/json", + ) + val converter: (Any) -> io.appwrite.models.MfaRecoveryCodes = { + @Suppress("UNCHECKED_CAST") + io.appwrite.models.MfaRecoveryCodes.from(map = it as Map) + } + return client.call( + "PATCH", + apiPath, + apiHeaders, + apiParams, + responseType = io.appwrite.models.MfaRecoveryCodes::class.java, + converter, + ) + } + + /** * Update name * @@ -1290,9 +1383,9 @@ class Account(client: Client) : Service(client) { /** - * Update (or renew) session + * Update session * - * Extend session's expiry to increase it's lifespan. Extending a session is useful when session length is short such as 5 minutes. + * Use this endpoint to extend a session's length. Extending a session is useful when session expiry is short. If the session was created using an OAuth provider, this endpoint refreshes the access token from the provider. * * @param sessionId Session ID. Use the string 'current' to update the current device session. * @return [io.appwrite.models.Session]