From 6c296c134899ec12cd991065946af63e6fe9050e Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Fri, 17 Aug 2018 19:23:29 -0300 Subject: [PATCH] Proof-of-Concept Headless Client --- briar-headless/build.gradle | 41 +++++++++ .../account/HeadlessAccountManager.java | 19 ++++ .../account/HeadlessAccountModule.java | 18 ++++ .../briar/headless/BriarHeadlessApp.java | 21 +++++ .../briar/headless/ForumController.java | 39 ++++++++ .../headless/HeadlessDatabaseConfig.java | 32 +++++++ .../briar/headless/HeadlessModule.java | 90 +++++++++++++++++++ .../org/briarproject/briar/headless/Main.java | 12 +++ .../briarproject/briar/headless/Router.java | 46 ++++++++++ briar-headless/witness.gradle | 47 ++++++++++ settings.gradle | 1 + update-dependency-pinning.sh | 1 + 12 files changed, 367 insertions(+) create mode 100644 briar-headless/build.gradle create mode 100644 briar-headless/src/main/java/org/briarproject/bramble/account/HeadlessAccountManager.java create mode 100644 briar-headless/src/main/java/org/briarproject/bramble/account/HeadlessAccountModule.java create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/BriarHeadlessApp.java create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/ForumController.java create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessDatabaseConfig.java create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessModule.java create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/Main.java create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/Router.java create mode 100644 briar-headless/witness.gradle diff --git a/briar-headless/build.gradle b/briar-headless/build.gradle new file mode 100644 index 000000000..910ebd620 --- /dev/null +++ b/briar-headless/build.gradle @@ -0,0 +1,41 @@ +plugins { + id 'java' + id 'net.ltgt.apt' + id 'idea' + id 'witness' +} +apply from: 'witness.gradle' + +sourceCompatibility = 1.8 +targetCompatibility = 1.8 + +dependencies { + implementation project(path: ':briar-core', configuration: 'default') + implementation project(path: ':bramble-java', configuration: 'default') + + implementation 'io.javalin:javalin:1.7.0' + implementation 'org.slf4j:slf4j-simple:1.7.25' + implementation 'com.fasterxml.jackson.core:jackson-databind:2.9.6' + + apt 'com.google.dagger:dagger-compiler:2.0.2' + + testImplementation project(path: ':bramble-api', configuration: 'testOutput') + testImplementation project(path: ':bramble-core', configuration: 'testOutput') + testImplementation 'junit:junit:4.12' + testImplementation "org.jmock:jmock:2.8.2" + testImplementation "org.jmock:jmock-junit4:2.8.2" + testImplementation "org.jmock:jmock-legacy:2.8.2" + testImplementation "org.hamcrest:hamcrest-library:1.3" + testImplementation "org.hamcrest:hamcrest-core:1.3" +} + +jar { + manifest { + attributes( + 'Main-Class': 'org.briarproject.briar.headless.Main' + ) + } + from { + configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } + } +} diff --git a/briar-headless/src/main/java/org/briarproject/bramble/account/HeadlessAccountManager.java b/briar-headless/src/main/java/org/briarproject/bramble/account/HeadlessAccountManager.java new file mode 100644 index 000000000..0186fd914 --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/bramble/account/HeadlessAccountManager.java @@ -0,0 +1,19 @@ +package org.briarproject.bramble.account; + +import org.briarproject.bramble.api.account.AccountManager; +import org.briarproject.bramble.api.crypto.CryptoComponent; +import org.briarproject.bramble.api.db.DatabaseConfig; +import org.briarproject.bramble.api.identity.IdentityManager; + +import javax.inject.Inject; + +class HeadlessAccountManager extends AccountManagerImpl + implements AccountManager { + + @Inject + HeadlessAccountManager(DatabaseConfig databaseConfig, + CryptoComponent crypto, IdentityManager identityManager) { + super(databaseConfig, crypto, identityManager); + } + +} diff --git a/briar-headless/src/main/java/org/briarproject/bramble/account/HeadlessAccountModule.java b/briar-headless/src/main/java/org/briarproject/bramble/account/HeadlessAccountModule.java new file mode 100644 index 000000000..4780aaac8 --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/bramble/account/HeadlessAccountModule.java @@ -0,0 +1,18 @@ +package org.briarproject.bramble.account; + +import org.briarproject.bramble.api.account.AccountManager; + +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; + +@Module +public class HeadlessAccountModule { + + @Provides + @Singleton + AccountManager provideAccountManager(HeadlessAccountManager accountManager) { + return accountManager; + } +} diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/BriarHeadlessApp.java b/briar-headless/src/main/java/org/briarproject/briar/headless/BriarHeadlessApp.java new file mode 100644 index 000000000..5d43d5488 --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/BriarHeadlessApp.java @@ -0,0 +1,21 @@ +package org.briarproject.briar.headless; +import org.briarproject.bramble.BrambleCoreModule; +import org.briarproject.bramble.account.HeadlessAccountModule; +import org.briarproject.bramble.system.DesktopSecureRandomModule; +import org.briarproject.briar.BriarCoreModule; + +import javax.inject.Singleton; + +import dagger.Component; + +@Component(modules = { + BrambleCoreModule.class, + BriarCoreModule.class, + DesktopSecureRandomModule.class, + HeadlessAccountModule.class, + HeadlessModule.class +}) +@Singleton +public interface BriarHeadlessApp { + Router router(); +} \ No newline at end of file diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/ForumController.java b/briar-headless/src/main/java/org/briarproject/briar/headless/ForumController.java new file mode 100644 index 000000000..ed6b5efd8 --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/ForumController.java @@ -0,0 +1,39 @@ +package org.briarproject.briar.headless; + +import org.briarproject.bramble.api.db.DbException; +import org.briarproject.briar.api.forum.Forum; +import org.briarproject.briar.api.forum.ForumManager; + +import java.util.Collection; + +import javax.inject.Inject; + +import io.javalin.Context; + +import static io.javalin.translator.json.JavalinJsonPlugin.getObjectToJsonMapper; + +public class ForumController { + + private final ForumManager forumManager; + + @Inject + public ForumController(ForumManager forumManager) { + this.forumManager = forumManager; + } + + public Context list(Context ctx) throws DbException { + Collection forums = forumManager.getForums(); + return ctx.result(getObjectToJsonMapper().map(forums)); + } + + public Context create(Context ctx) throws DbException { + String name = ctx.formParam("name"); + if (name == null || name.length() < 1) { + return ctx.status(500).result("Expecting Forum Name"); + } else { + Forum forum = forumManager.addForum(name); + return ctx.result(getObjectToJsonMapper().map(forum)); + } + } + +} diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessDatabaseConfig.java b/briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessDatabaseConfig.java new file mode 100644 index 000000000..2db281705 --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessDatabaseConfig.java @@ -0,0 +1,32 @@ +package org.briarproject.briar.headless; + +import org.briarproject.bramble.api.db.DatabaseConfig; +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +import java.io.File; + +@NotNullByDefault +class HeadlessDatabaseConfig implements DatabaseConfig { + + private final File dbDir, keyDir; + + HeadlessDatabaseConfig(File dbDir, File keyDir) { + this.dbDir = dbDir; + this.keyDir = keyDir; + } + + @Override + public File getDatabaseDirectory() { + return dbDir; + } + + @Override + public File getDatabaseKeyDirectory() { + return keyDir; + } + + @Override + public long getMaxSize() { + return Long.MAX_VALUE; + } +} diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessModule.java b/briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessModule.java new file mode 100644 index 000000000..0e2588fea --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessModule.java @@ -0,0 +1,90 @@ +package org.briarproject.briar.headless; + +import org.briarproject.bramble.api.crypto.CryptoComponent; +import org.briarproject.bramble.api.crypto.PublicKey; +import org.briarproject.bramble.api.db.DatabaseConfig; +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.bramble.api.plugin.PluginConfig; +import org.briarproject.bramble.api.plugin.duplex.DuplexPluginFactory; +import org.briarproject.bramble.api.plugin.simplex.SimplexPluginFactory; +import org.briarproject.bramble.api.reporting.DevConfig; +import org.briarproject.bramble.util.StringUtils; + +import java.io.File; +import java.security.GeneralSecurityException; +import java.util.Collection; + +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; + +import static java.util.Collections.emptyList; +import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_ONION_ADDRESS; +import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_PUBLIC_KEY_HEX; + +@Module +public class HeadlessModule { + + @Provides + @Singleton + DatabaseConfig provideDatabaseConfig() { + File dbDir = new File("dbDir"); + File keyDir = new File("keyDir"); + return new HeadlessDatabaseConfig(dbDir, keyDir); + } + + @Provides + PluginConfig providePluginConfig() { + Collection duplex = emptyList(); + @NotNullByDefault + PluginConfig pluginConfig = new PluginConfig() { + + @Override + public Collection getDuplexFactories() { + return duplex; + } + + @Override + public Collection getSimplexFactories() { + return emptyList(); + } + + @Override + public boolean shouldPoll() { + return true; + } + }; + return pluginConfig; + } + + @Provides + @Singleton + DevConfig provideDevConfig(CryptoComponent crypto) { + @NotNullByDefault + DevConfig devConfig = new DevConfig() { + + @Override + public PublicKey getDevPublicKey() { + try { + return crypto.getMessageKeyParser().parsePublicKey( + StringUtils.fromHexString(DEV_PUBLIC_KEY_HEX)); + } catch (GeneralSecurityException e) { + throw new RuntimeException(e); + } + } + + @Override + public String getDevOnionAddress() { + return DEV_ONION_ADDRESS; + } + + @Override + public File getReportDir() { + return new File("reportDir"); + } + }; + return devConfig; + } + +} diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/Main.java b/briar-headless/src/main/java/org/briarproject/briar/headless/Main.java new file mode 100644 index 000000000..eb4ec2d66 --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/Main.java @@ -0,0 +1,12 @@ +package org.briarproject.briar.headless; + +public class Main { + + public static void main(String[] args) { + DaggerBriarHeadlessApp + .create() + .router() + .start(); + } + +} diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/Router.java b/briar-headless/src/main/java/org/briarproject/briar/headless/Router.java new file mode 100644 index 000000000..41f4b4d8b --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/Router.java @@ -0,0 +1,46 @@ +package org.briarproject.briar.headless; + +import org.briarproject.bramble.api.account.AccountManager; +import org.briarproject.bramble.api.lifecycle.LifecycleManager; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import io.javalin.Javalin; + +@Singleton +public class Router { + + private final AccountManager accountManager; + private final LifecycleManager lifecycleManager; + private final ForumController forumController; + + @Inject + public Router(AccountManager accountManager, + LifecycleManager lifecycleManager, + ForumController forumController) { + this.accountManager = accountManager; + this.lifecycleManager = lifecycleManager; + this.forumController = forumController; + } + + public void start() { + if (accountManager.accountExists()) { + accountManager.signIn("test"); + } else { + accountManager.createAccount("test", "test"); + } + assert accountManager.getDatabaseKey() != null; + + lifecycleManager.startServices(accountManager.getDatabaseKey()); + + Javalin app = Javalin.create() + .port(7000) + .disableStartupBanner() + .enableStandardRequestLogging() + .start(); + app.get("/forums", forumController::list); + app.post("/forums", forumController::create); + } + +} diff --git a/briar-headless/witness.gradle b/briar-headless/witness.gradle new file mode 100644 index 000000000..ae314d1ee --- /dev/null +++ b/briar-headless/witness.gradle @@ -0,0 +1,47 @@ +dependencyVerification { + verify = [ + 'cglib:cglib:3.2.0:cglib-3.2.0.jar:adb13bab79712ad6bdf1bd59f2a3918018a8016e722e8a357065afb9e6690861', + 'com.fasterxml.jackson.core:jackson-annotations:2.9.0:jackson-annotations-2.9.0.jar:45d32ac61ef8a744b464c54c2b3414be571016dd46bfc2bec226761cf7ae457a', + 'com.fasterxml.jackson.core:jackson-core:2.9.6:jackson-core-2.9.6.jar:fab8746aedd6427788ee390ea04d438ec141bff7eb3476f8bdd5d9110fb2718a', + 'com.fasterxml.jackson.core:jackson-databind:2.9.6:jackson-databind-2.9.6.jar:657e3e979446d61f88432b9c50f0ccd9c1fe4f1c822d533f5572e4c0d172a125', + 'com.google.dagger:dagger-compiler:2.0.2:dagger-compiler-2.0.2.jar:b74bc9de063dd4c6400b232231f2ef5056145b8fbecbf5382012007dd1c071b3', + 'com.google.dagger:dagger-producers:2.0-beta:dagger-producers-2.0-beta.jar:99ec15e8a0507ba569e7655bc1165ee5e5ca5aa914b3c8f7e2c2458f724edd6b', + 'com.google.dagger:dagger:2.0.2:dagger-2.0.2.jar:84c0282ed8be73a29e0475d639da030b55dee72369e58dd35ae7d4fe6243dcf9', + 'com.google.guava:guava:18.0:guava-18.0.jar:d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99', + 'io.javalin:javalin:1.7.0:javalin-1.7.0.jar:d97d2044a7b050a3b6564c9a99a0a94a4c6d8c57818033cf0d8236bc90a8069b', + 'javax.inject:javax.inject:1:javax.inject-1.jar:91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff', + 'javax.servlet:javax.servlet-api:3.1.0:javax.servlet-api-3.1.0.jar:af456b2dd41c4e82cf54f3e743bc678973d9fe35bd4d3071fa05c7e5333b8482', + 'junit:junit:4.12:junit-4.12.jar:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a', + 'org.apache.ant:ant-launcher:1.9.4:ant-launcher-1.9.4.jar:7bccea20b41801ca17bcbc909a78c835d0f443f12d639c77bd6ae3d05861608d', + 'org.apache.ant:ant:1.9.4:ant-1.9.4.jar:649ae0730251de07b8913f49286d46bba7b92d47c5f332610aa426c4f02161d8', + 'org.beanshell:bsh:1.3.0:bsh-1.3.0.jar:9b04edc75d19db54f1b4e8b5355e9364384c6cf71eb0a1b9724c159d779879f8', + 'org.eclipse.jetty.websocket:websocket-api:9.4.9.v20180320:websocket-api-9.4.9.v20180320.jar:985b737f5c0928d48fc9890b261cbed096625350b9c0e321f44bde8a803c85ec', + 'org.eclipse.jetty.websocket:websocket-client:9.4.9.v20180320:websocket-client-9.4.9.v20180320.jar:2f5c6a64987ac27a21862a6349bd2b1d25545cba9aa68084e50ef77af7adcd7d', + 'org.eclipse.jetty.websocket:websocket-common:9.4.9.v20180320:websocket-common-9.4.9.v20180320.jar:26fc6bba6ad8e6522b27d5f397429c349264bcea076bd186ad885ef0cd0a73c8', + 'org.eclipse.jetty.websocket:websocket-server:9.4.9.v20180320:websocket-server-9.4.9.v20180320.jar:93ebcfa8e8af9876491d1524b4e8d273be8a7576e18b75ef699bad9564f76de2', + 'org.eclipse.jetty.websocket:websocket-servlet:9.4.9.v20180320:websocket-servlet-9.4.9.v20180320.jar:cac3f46db4917722b860e194907c36c251d2765ca1ce8323085c47cefafec52b', + 'org.eclipse.jetty:jetty-client:9.4.9.v20180320:jetty-client-9.4.9.v20180320.jar:d6d8eca17806261a96137f64ad14c33feed26ba031c92180162961589141072d', + 'org.eclipse.jetty:jetty-http:9.4.9.v20180320:jetty-http-9.4.9.v20180320.jar:823e76a9565f8a98c96542745f34560e2a6a9dfa6fbe320614061ad9b17b950b', + 'org.eclipse.jetty:jetty-io:9.4.9.v20180320:jetty-io-9.4.9.v20180320.jar:fffa35ca529d3267ad80d87f83ad4f6796b0981ae21d3ff621151bbe0a8f4155', + 'org.eclipse.jetty:jetty-security:9.4.9.v20180320:jetty-security-9.4.9.v20180320.jar:5cbaeb9837aa331a8ee918724786655c6f60f8cc65ab84e03ff587bc212a2327', + 'org.eclipse.jetty:jetty-server:9.4.9.v20180320:jetty-server-9.4.9.v20180320.jar:b45869789b8f8081c1c75c059b4fd262d2fd440fa676c54bc753365fdd1f82d6', + 'org.eclipse.jetty:jetty-servlet:9.4.9.v20180320:jetty-servlet-9.4.9.v20180320.jar:a96f8711d4f9d5d4c3fcafa046fb5caefec17eefcbfcd35b6c2e1d5a0549edfc', + 'org.eclipse.jetty:jetty-util:9.4.9.v20180320:jetty-util-9.4.9.v20180320.jar:86ccb5e178e7001f26a12ec4bf56c522911424a0edf60424f15add8601355fc5', + 'org.eclipse.jetty:jetty-webapp:9.4.9.v20180320:jetty-webapp-9.4.9.v20180320.jar:7d6c6af12f10a47524e8eabc607226b038100680612ea569f92c030158bd5566', + 'org.eclipse.jetty:jetty-xml:9.4.9.v20180320:jetty-xml-9.4.9.v20180320.jar:2a0c8e64364cb8d0f483e5e050db6fbd26f0ad9e5098367f8af7928887fa5ece', + 'org.hamcrest:hamcrest-core:1.3:hamcrest-core-1.3.jar:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9', + 'org.hamcrest:hamcrest-library:1.3:hamcrest-library-1.3.jar:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c', + 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.41:kotlin-stdlib-jdk7-1.2.41.jar:169ee5879cba8444499243ceea5e6a2cb6ecea5424211cc819f0704501154b35', + 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.2.41:kotlin-stdlib-jdk8-1.2.41.jar:b306e0e6735841e31e320bf3260c71d60fc35057cfa87895f23251ee260a64a8', + 'org.jetbrains.kotlin:kotlin-stdlib:1.2.41:kotlin-stdlib-1.2.41.jar:f0595b9ed88ddc6fd66bddf68c56c6f2f6c4b17faa51e43e478acad32b05303e', + 'org.jetbrains:annotations:13.0:annotations-13.0.jar:ace2a10dc8e2d5fd34925ecac03e4988b2c0f851650c94b8cef49ba1bd111478', + 'org.jmock:jmock-junit4:2.8.2:jmock-junit4-2.8.2.jar:f7ee4df4f7bd7b7f1cafad3b99eb74d579f109d5992ff625347352edb55e674c', + 'org.jmock:jmock-legacy:2.8.2:jmock-legacy-2.8.2.jar:f2b985a5c08a9edb7f37612330c058809da3f6a6d63ce792426ebf8ff0d6d31b', + 'org.jmock:jmock-testjar:2.8.2:jmock-testjar-2.8.2.jar:8900860f72c474e027cf97fe78dcbf154a1aa7fc62b6845c5fb4e4f3c7bc8760', + 'org.jmock:jmock:2.8.2:jmock-2.8.2.jar:6c73cb4a2e6dbfb61fd99c9a768539c170ab6568e57846bd60dbf19596b65b16', + 'org.objenesis:objenesis:2.1:objenesis-2.1.jar:c74330cc6b806c804fd37e74487b4fe5d7c2750c5e15fbc6efa13bdee1bdef80', + 'org.ow2.asm:asm:5.0.4:asm-5.0.4.jar:896618ed8ae62702521a78bc7be42b7c491a08e6920a15f89a3ecdec31e9a220', + 'org.slf4j:slf4j-api:1.7.25:slf4j-api-1.7.25.jar:18c4a0095d5c1da6b817592e767bb23d29dd2f560ad74df75ff3961dbde25b79', + 'org.slf4j:slf4j-simple:1.7.25:slf4j-simple-1.7.25.jar:0966e86fffa5be52d3d9e7b89dd674d98a03eed0a454fbaf7c1bd9493bd9d874', + ] +} diff --git a/settings.gradle b/settings.gradle index 97910eabe..def39c0cd 100644 --- a/settings.gradle +++ b/settings.gradle @@ -5,3 +5,4 @@ include ':bramble-java' include ':briar-api' include ':briar-core' include ':briar-android' +include ':briar-headless' diff --git a/update-dependency-pinning.sh b/update-dependency-pinning.sh index 127fa4fb4..040fe9d3b 100755 --- a/update-dependency-pinning.sh +++ b/update-dependency-pinning.sh @@ -9,6 +9,7 @@ PROJECTS=( 'briar-api' 'briar-core' 'briar-android' + 'briar-headless' ) # clear witness files to prevent errors when upgrading dependencies