From 4b3f4aacda8041ebd2ec61009c6e07b9808f8456 Mon Sep 17 00:00:00 2001 From: Vitor Hugo Schwaab Date: Thu, 21 Nov 2024 01:45:32 +0100 Subject: [PATCH] chore: create backup module This commit introduces a new cross-platform backup module to the project with support for iOS, Web, and Android. Additionally, it enables JavaScript multiplatform support in existing `kalium/network-model` and `kalium/data` projects. --- backup/README.md | 57 ++++++++++++++++ backup/build.gradle.kts | 115 +++++++++++++++++++++++++++++++++ data/build.gradle.kts | 7 +- network-model/build.gradle.kts | 2 +- 4 files changed, 176 insertions(+), 5 deletions(-) create mode 100644 backup/README.md create mode 100644 backup/build.gradle.kts diff --git a/backup/README.md b/backup/README.md new file mode 100644 index 00000000000..ecc16d0105c --- /dev/null +++ b/backup/README.md @@ -0,0 +1,57 @@ +# Cross-platform Backup + +This module implements the Wire Cross-platform Backup solution. +Its purpose is to create a common implementation to be used by iOS, Web, and Android. + +## Capabilities + +> [!TIP] +> The backup blob/file will be referred in this document as **backup artifact**, or simply +> **artifact**. +> The clients (iOS, Web, and Android) will be referred as **callers**. + +### Creation of backup artifact + +The library should be able to transform data like messages, conversations, users into an artifact, +_i.e._ create a backup file. + +### Restoration of original data + +It should also be able to revert this process, _i.e._ read a backup artifact and understand all of +its contents, allowing the caller to get access to the original data. + +### Optional Encryption + +The artifact may _(or may not)_ be Encrypted. Clients using this library can provide an optional +passphrase to encrypt and decrypt the artifact. + +### Optional UserID verification + +When creating an artifact, callers need to provide a qualified user ID. This qualified user ID will +be stored within the artifact. +When restoring the original data, the library _can_ compare the user ID in the artifact with a user +ID provided by the caller. This may not be wanted in all features, _e.g._ in case of chat history +sharing across different users. + +### Peak into artifact + +Clients can ask the library if a piece of data is an actual cross-platform artifact. +The library should respond yes/no, and provide more details in case of a positive answer: is it +encrypted? Was it created by the same user that is restoring the artifact? + +-------- + +# Development + +Using Kotlin Multiplatform, it should at least be available for iOS, JS (with TypeScript types), +Android, and JVM. + +### Building + +Before we can automate the deployment of this library, we can manually generate and send library +artifacts (not backup artifacts) using the following Gradle tasks: + +- iOS: `./gradlew :backup:assembleBackupDebugXCFramework` +- Web: `./gradlew :backup:jsBrowserDevelopmentLibraryDistribution` + +**Output:** the results will be in `backup/build` directory. iOS needs the whole `backup.xcframework` directory, Web/JS needs the whole directory that contains `package.json` diff --git a/backup/build.gradle.kts b/backup/build.gradle.kts new file mode 100644 index 00000000000..72b8b96de01 --- /dev/null +++ b/backup/build.gradle.kts @@ -0,0 +1,115 @@ +import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework + +/* + * Wire + * Copyright (C) 2024 Wire Swiss GmbH + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see http://www.gnu.org/licenses/. + */ +plugins { + id(libs.plugins.android.library.get().pluginId) + id(libs.plugins.kotlin.multiplatform.get().pluginId) + alias(libs.plugins.kotlin.serialization) + alias(libs.plugins.ksp) + id(libs.plugins.kalium.library.get().pluginId) +} + +kaliumLibrary { + multiplatform { enableJs.set(true) } +} + +@Suppress("UnusedPrivateProperty") +kotlin { + val xcf = XCFramework() + val appleTargets = listOf(iosX64(), iosArm64(), iosSimulatorArm64(), macosArm64(), macosX64()) + appleTargets.forEach { + it.binaries.framework { + baseName = "backup" + xcf.add(this) + } + } + js { + browser() + binaries.library() + generateTypeScriptDefinitions() + } + sourceSets { + val commonMain by getting { + dependencies { + implementation(project(":data")) + implementation(project(":protobuf")) + implementation(libs.pbandk.runtime.common) + + implementation(libs.coroutines.core) + implementation(libs.ktxDateTime) + implementation(libs.ktxSerialization) + + implementation(libs.okio.core) + + // Libsodium + implementation(libs.libsodiumBindingsMP) + } + } + val commonTest by getting { + dependencies { + implementation(libs.coroutines.test) + implementation(libs.okio.test) + } + } + + val nonJsMain by creating { + dependsOn(commonMain) + } + val nonJsTest by creating { + dependsOn(commonTest) + } + val androidMain by getting { + dependsOn(nonJsMain) + } + val jvmMain by getting { + dependsOn(nonJsMain) + } + + val iosX64Main by getting { + dependsOn(nonJsMain) + dependencies { + implementation(libs.pbandk.runtime.iosX64) + } + } + val iosArm64Main by getting { + dependsOn(nonJsMain) + dependencies { + implementation(libs.pbandk.runtime.iosArm64) + } + } + val iosSimulatorArm64Main by getting { + dependsOn(nonJsMain) + dependencies { + implementation(libs.pbandk.runtime.iosSimulatorArm64) + } + } + val macosX64Main by getting { + dependsOn(nonJsMain) + dependencies { + implementation(libs.pbandk.runtime.macX64) + } + } + val macosArm64Main by getting { + dependsOn(nonJsMain) + dependencies { + implementation(libs.pbandk.runtime.macArm64) + } + } + } +} diff --git a/data/build.gradle.kts b/data/build.gradle.kts index 11e58a18b0c..e16faaae75d 100644 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -24,13 +24,12 @@ plugins { } kaliumLibrary { - multiplatform { - enableJs.set(false) - } + multiplatform { } } + +@Suppress("UnusedPrivateProperty") kotlin { sourceSets { - @Suppress("UnusedPrivateProperty") val commonMain by getting { dependencies { implementation(project(":network-model")) diff --git a/network-model/build.gradle.kts b/network-model/build.gradle.kts index 4f2eb1c7497..ae1abd96807 100644 --- a/network-model/build.gradle.kts +++ b/network-model/build.gradle.kts @@ -25,7 +25,7 @@ plugins { kaliumLibrary { multiplatform { - enableJs.set(false) + enableJs.set(true) } }