From 6c296c134899ec12cd991065946af63e6fe9050e Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Fri, 17 Aug 2018 19:23:29 -0300 Subject: [PATCH 01/40] 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 From 0d1ebddcd21a191d9712ec3897408c564dece55d Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Sat, 18 Aug 2018 17:15:22 -0300 Subject: [PATCH 02/40] Allow account creation and reading password from STDIN --- .../briar/headless/BriarService.java | 105 ++++++++++++++++++ .../briarproject/briar/headless/Router.java | 22 +--- 2 files changed, 109 insertions(+), 18 deletions(-) create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/BriarService.java diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/BriarService.java b/briar-headless/src/main/java/org/briarproject/briar/headless/BriarService.java new file mode 100644 index 000000000..abfa21996 --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/BriarService.java @@ -0,0 +1,105 @@ +package org.briarproject.briar.headless; + +import org.briarproject.bramble.api.account.AccountManager; +import org.briarproject.bramble.api.lifecycle.LifecycleManager; +import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; + +import java.io.Console; +import java.util.Scanner; +import java.util.logging.Logger; + +import javax.annotation.ParametersAreNonnullByDefault; +import javax.inject.Inject; + +import static java.lang.System.console; +import static java.lang.System.err; +import static java.lang.System.exit; +import static java.lang.System.out; +import static java.util.logging.Logger.getLogger; +import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; + +@MethodsNotNullByDefault +@ParametersAreNonnullByDefault +public class BriarService { + + private final static Logger LOG = getLogger(BriarService.class.getName()); + + private final AccountManager accountManager; + private final LifecycleManager lifecycleManager; + + @Inject + public BriarService(AccountManager accountManager, + LifecycleManager lifecycleManager) { + this.accountManager = accountManager; + this.lifecycleManager = lifecycleManager; + } + + public void start() { + Console console = console(); + out.println("Welcome to Briar!\n"); + + if (!accountManager.accountExists()) { + if (console == null) { + LOG.warning("No account found."); + LOG.warning("Please start in terminal to set one up."); + exit(1); + } + console.printf("No account found. Let's create one!\n\n"); + String nickname = createNickname(console); + String password = createPassword(console); + accountManager.createAccount(nickname, password); + } else { + out.print("Password: "); + String password; + if (console == null) { + Scanner scanner = new Scanner(System.in); + password = scanner.nextLine(); + } else { + password = new String(console.readPassword()); + } + if (!accountManager.signIn(password)) { + err.println("Error: Password invalid"); + exit(1); + } + } + assert accountManager.getDatabaseKey() != null; + + lifecycleManager.startServices(accountManager.getDatabaseKey()); + } + + private String createNickname(Console console) { + String nickname; + boolean error; + do { + nickname = console.readLine("Nickname: "); + if (nickname.length() == 0) { + console.printf("Please enter a nickname!\n"); + error = true; + } else if (nickname.length() > MAX_AUTHOR_NAME_LENGTH) { + console.printf("Please choose a shorter nickname!\n"); + error = true; + } else { + error = false; + } + } while (error); + return nickname; + } + + private String createPassword(Console console) { + String password; + boolean error; + do { + password = new String(console.readPassword("Password: ")); + if (password.length() < 4) { + console.printf( + "Please enter a password with at least 4 characters!\n"); + error = true; + // TODO enforce stronger password + } else { + error = false; + } + } while (error); + return password; + } + +} 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 index 41f4b4d8b..8975175af 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/Router.java +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/Router.java @@ -1,8 +1,5 @@ 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; @@ -11,28 +8,17 @@ import io.javalin.Javalin; @Singleton public class Router { - private final AccountManager accountManager; - private final LifecycleManager lifecycleManager; + private final BriarService briarService; private final ForumController forumController; @Inject - public Router(AccountManager accountManager, - LifecycleManager lifecycleManager, - ForumController forumController) { - this.accountManager = accountManager; - this.lifecycleManager = lifecycleManager; + public Router(BriarService briarService, ForumController forumController) { + this.briarService = briarService; 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()); + briarService.start(); Javalin app = Javalin.create() .port(7000) From d11f1d28053be5195382f5938bac8cb8b52fc4c0 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Sat, 18 Aug 2018 17:30:45 -0300 Subject: [PATCH 03/40] Add a poor man's argument to explicitly turn on verbose logging --- .../java/org/briarproject/briar/headless/Main.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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 index eb4ec2d66..87074df20 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/Main.java +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/Main.java @@ -1,8 +1,21 @@ package org.briarproject.briar.headless; +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.Logger; + public class Main { public static void main(String[] args) { + Logger rootLogger = LogManager.getLogManager().getLogger(""); + rootLogger.setLevel(Level.WARNING); + + for (String arg : args) { + if (arg.equals("-v")) { + rootLogger.setLevel(Level.INFO); + } + } + DaggerBriarHeadlessApp .create() .router() From 5334a8c9ca4bdcc2641c12077b3b8cdbf7255ad2 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Sat, 18 Aug 2018 18:15:14 -0300 Subject: [PATCH 04/40] Add basic support for listing and writing blog posts --- .../briar/headless/BriarService.java | 4 + .../briarproject/briar/headless/Router.java | 33 +++++++- .../briar/headless/blogs/BlogController.java | 81 +++++++++++++++++++ .../briar/headless/blogs/OutputBlogPost.java | 38 +++++++++ .../{ => forums}/ForumController.java | 10 ++- 5 files changed, 162 insertions(+), 4 deletions(-) create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogController.java create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/blogs/OutputBlogPost.java rename briar-headless/src/main/java/org/briarproject/briar/headless/{ => forums}/ForumController.java (75%) diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/BriarService.java b/briar-headless/src/main/java/org/briarproject/briar/headless/BriarService.java index abfa21996..74d2b678f 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/BriarService.java +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/BriarService.java @@ -9,7 +9,9 @@ import java.util.Scanner; import java.util.logging.Logger; import javax.annotation.ParametersAreNonnullByDefault; +import javax.annotation.concurrent.Immutable; import javax.inject.Inject; +import javax.inject.Singleton; import static java.lang.System.console; import static java.lang.System.err; @@ -18,6 +20,8 @@ import static java.lang.System.out; import static java.util.logging.Logger.getLogger; import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH; +@Immutable +@Singleton @MethodsNotNullByDefault @ParametersAreNonnullByDefault public class BriarService { 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 index 8975175af..b0995e39e 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/Router.java +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/Router.java @@ -1,20 +1,36 @@ package org.briarproject.briar.headless; +import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; +import org.briarproject.briar.headless.blogs.BlogController; +import org.briarproject.briar.headless.forums.ForumController; + +import javax.annotation.ParametersAreNonnullByDefault; +import javax.annotation.concurrent.Immutable; import javax.inject.Inject; import javax.inject.Singleton; import io.javalin.Javalin; +import static io.javalin.ApiBuilder.get; +import static io.javalin.ApiBuilder.path; +import static io.javalin.ApiBuilder.post; + +@Immutable @Singleton +@MethodsNotNullByDefault +@ParametersAreNonnullByDefault public class Router { private final BriarService briarService; private final ForumController forumController; + private final BlogController blogController; @Inject - public Router(BriarService briarService, ForumController forumController) { + public Router(BriarService briarService, ForumController forumController, + BlogController blogController) { this.briarService = briarService; this.forumController = forumController; + this.blogController = blogController; } public void start() { @@ -24,9 +40,20 @@ public class Router { .port(7000) .disableStartupBanner() .enableStandardRequestLogging() + .enableRouteOverview("/") + .enableDynamicGzip() .start(); - app.get("/forums", forumController::list); - app.post("/forums", forumController::create); + + app.routes(() -> { + path("/forums", () -> { + get(forumController::list); + post(forumController::create); + }); + path("/blogs", () -> path("/posts", () -> { + get(blogController::listPosts); + post(blogController::createPost); + })); + }); } } diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogController.java b/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogController.java new file mode 100644 index 000000000..358e0f6b1 --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogController.java @@ -0,0 +1,81 @@ +package org.briarproject.briar.headless.blogs; + +import org.briarproject.bramble.api.FormatException; +import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.identity.IdentityManager; +import org.briarproject.bramble.api.identity.LocalAuthor; +import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; +import org.briarproject.bramble.api.system.Clock; +import org.briarproject.briar.api.blog.Blog; +import org.briarproject.briar.api.blog.BlogManager; +import org.briarproject.briar.api.blog.BlogPost; +import org.briarproject.briar.api.blog.BlogPostFactory; +import org.briarproject.briar.api.blog.BlogPostHeader; + +import java.security.GeneralSecurityException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import javax.annotation.ParametersAreNonnullByDefault; +import javax.annotation.concurrent.Immutable; +import javax.inject.Inject; +import javax.inject.Singleton; + +import io.javalin.Context; + +@Immutable +@Singleton +@MethodsNotNullByDefault +@ParametersAreNonnullByDefault +public class BlogController { + + private final BlogManager blogManager; + private final BlogPostFactory blogPostFactory; + private final IdentityManager identityManager; + private final Clock clock; + + @Inject + public BlogController(BlogManager blogManager, + BlogPostFactory blogPostFactory, IdentityManager identityManager, + Clock clock) { + this.blogManager = blogManager; + this.blogPostFactory = blogPostFactory; + this.identityManager = identityManager; + this.clock = clock; + } + + public Context listPosts(Context ctx) throws DbException { + List posts = new ArrayList<>(); + for (Blog b : blogManager.getBlogs()) { + Collection headers = + blogManager.getPostHeaders(b.getId()); + for (BlogPostHeader header : headers) { + String body = blogManager.getPostBody(header.getId()); + OutputBlogPost post = new OutputBlogPost(header, body); + posts.add(post); + } + } + return ctx.json(posts); + } + + public Context createPost(Context ctx) + throws DbException, GeneralSecurityException, FormatException { + String text = ctx.formParam("text"); + if (text == null || text.length() < 1) { + return ctx.status(500).result("Expecting Blog text"); + } else { + LocalAuthor author = identityManager.getLocalAuthor(); + Blog blog = blogManager.getPersonalBlog(author); + long now = clock.currentTimeMillis(); + BlogPost post = blogPostFactory + .createBlogPost(blog.getId(), now, null, author, text); + blogManager.addLocalPost(post); + BlogPostHeader header = blogManager + .getPostHeader(blog.getId(), post.getMessage().getId()); + OutputBlogPost outputPost = new OutputBlogPost(header, text); + return ctx.json(outputPost); + } + } + +} diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/OutputBlogPost.java b/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/OutputBlogPost.java new file mode 100644 index 000000000..f1dd2a8a9 --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/blogs/OutputBlogPost.java @@ -0,0 +1,38 @@ +package org.briarproject.briar.headless.blogs; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.bramble.identity.OutputAuthor; +import org.briarproject.briar.api.blog.BlogPostHeader; + +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +@Immutable +@NotNullByDefault +@SuppressWarnings("WeakerAccess") +class OutputBlogPost { + + public final String body; + public final OutputAuthor author; + public final String authorStatus, type; + public final byte[] id; + @Nullable + public final byte[] parentId; + public final boolean read, rssFeed; + public final long timestamp, timestampReceived; + + OutputBlogPost(BlogPostHeader header, String body) { + this.body = body; + this.author = new OutputAuthor(header.getAuthor()); + this.authorStatus = header.getAuthorStatus().name().toLowerCase(); + this.type = header.getType().name().toLowerCase(); + this.id = header.getId().getBytes(); + this.parentId = header.getParentId() == null ? null : + header.getParentId().getBytes(); + this.read = header.isRead(); + this.rssFeed = header.isRssFeed(); + this.timestamp = header.getTimestamp(); + this.timestampReceived = header.getTimeReceived(); + } + +} diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/ForumController.java b/briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumController.java similarity index 75% rename from briar-headless/src/main/java/org/briarproject/briar/headless/ForumController.java rename to briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumController.java index ed6b5efd8..483b98d02 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/ForumController.java +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumController.java @@ -1,17 +1,25 @@ -package org.briarproject.briar.headless; +package org.briarproject.briar.headless.forums; import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.briar.api.forum.Forum; import org.briarproject.briar.api.forum.ForumManager; import java.util.Collection; +import javax.annotation.ParametersAreNonnullByDefault; +import javax.annotation.concurrent.Immutable; import javax.inject.Inject; +import javax.inject.Singleton; import io.javalin.Context; import static io.javalin.translator.json.JavalinJsonPlugin.getObjectToJsonMapper; +@Immutable +@Singleton +@MethodsNotNullByDefault +@ParametersAreNonnullByDefault public class ForumController { private final ForumManager forumManager; From 31e4045cf7acaefc3add60d3897707f958f82cae Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Mon, 20 Aug 2018 12:46:51 -0300 Subject: [PATCH 05/40] Try to shutdown cleanly when server stops or SIGINT is received --- .../java/org/briarproject/briar/headless/BriarService.java | 4 ++++ .../main/java/org/briarproject/briar/headless/Router.java | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/BriarService.java b/briar-headless/src/main/java/org/briarproject/briar/headless/BriarService.java index 74d2b678f..724f89752 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/BriarService.java +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/BriarService.java @@ -106,4 +106,8 @@ public class BriarService { return password; } + public void stop() { + lifecycleManager.stopServices(); + } + } 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 index b0995e39e..257d94ee0 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/Router.java +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/Router.java @@ -14,6 +14,9 @@ import io.javalin.Javalin; import static io.javalin.ApiBuilder.get; import static io.javalin.ApiBuilder.path; import static io.javalin.ApiBuilder.post; +import static io.javalin.event.EventType.SERVER_START_FAILED; +import static io.javalin.event.EventType.SERVER_STOPPED; +import static java.lang.Runtime.getRuntime; @Immutable @Singleton @@ -35,6 +38,7 @@ public class Router { public void start() { briarService.start(); + getRuntime().addShutdownHook(new Thread(briarService::stop)); Javalin app = Javalin.create() .port(7000) @@ -42,6 +46,8 @@ public class Router { .enableStandardRequestLogging() .enableRouteOverview("/") .enableDynamicGzip() + .event(SERVER_START_FAILED, event -> briarService.stop()) + .event(SERVER_STOPPED, event -> briarService.stop()) .start(); app.routes(() -> { From a798e25bf2e8fb06005e6247aa33e65ece599b7b Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Mon, 20 Aug 2018 13:54:51 -0300 Subject: [PATCH 06/40] Save app data always in $HOME/.briar for now --- .../briar/headless/HeadlessModule.java | 48 +++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) 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 index 0e2588fea..67665dd4e 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessModule.java +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessModule.java @@ -11,26 +11,51 @@ import org.briarproject.bramble.api.reporting.DevConfig; import org.briarproject.bramble.util.StringUtils; import java.io.File; +import java.io.IOException; +import java.nio.file.attribute.PosixFilePermission; import java.security.GeneralSecurityException; import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import java.util.logging.Logger; import javax.inject.Singleton; import dagger.Module; import dagger.Provides; +import static java.nio.file.Files.setPosixFilePermissions; +import static java.nio.file.attribute.PosixFilePermission.OWNER_EXECUTE; +import static java.nio.file.attribute.PosixFilePermission.OWNER_READ; +import static java.nio.file.attribute.PosixFilePermission.OWNER_WRITE; import static java.util.Collections.emptyList; +import static java.util.logging.Level.WARNING; +import static java.util.logging.Logger.getLogger; 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 { + private final static Logger LOG = getLogger(HeadlessModule.class.getName()); + + private final String appDir; + + public HeadlessModule() { + String home = System.getProperty("user.home"); + appDir = home + File.separator + ".briar"; + try { + ensurePermissions(new File(appDir)); + } catch (IOException e) { + LOG.log(WARNING, e.getMessage(), e); + } + } + @Provides @Singleton DatabaseConfig provideDatabaseConfig() { - File dbDir = new File("dbDir"); - File keyDir = new File("keyDir"); + File dbDir = appDir("db"); + File keyDir = appDir("key"); return new HeadlessDatabaseConfig(dbDir, keyDir); } @@ -81,10 +106,27 @@ public class HeadlessModule { @Override public File getReportDir() { - return new File("reportDir"); + return appDir("reportDir"); } }; return devConfig; } + private File appDir(String file) { + return new File(appDir + File.separator + file); + } + + private void ensurePermissions(File file)throws IOException { + if (!file.exists()) { + if (!file.mkdirs()) { + throw new IOException("Could not create directory"); + } + } + Set perms = new HashSet<>(); + perms.add(OWNER_READ); + perms.add(OWNER_WRITE); + perms.add(OWNER_EXECUTE); + setPosixFilePermissions(file.toPath(), perms); + } + } From 48f6a3b91fe5b1d691e86a85c6407f95a8b04522 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Wed, 22 Aug 2018 19:10:03 -0300 Subject: [PATCH 07/40] Add Tor plugin to headless client and introduce new ConfigurationManager --- .../system/JavaConfigurationManager.java | 56 ++++++++++++ .../bramble/system/JavaSystemModule.java | 8 ++ .../briar/headless/BriarHeadlessApp.java | 6 +- .../briar/headless/HeadlessModule.java | 91 +++++++++---------- .../org/briarproject/briar/headless/Main.java | 15 ++- 5 files changed, 123 insertions(+), 53 deletions(-) create mode 100644 bramble-j2se/src/main/java/org/briarproject/bramble/system/JavaConfigurationManager.java diff --git a/bramble-j2se/src/main/java/org/briarproject/bramble/system/JavaConfigurationManager.java b/bramble-j2se/src/main/java/org/briarproject/bramble/system/JavaConfigurationManager.java new file mode 100644 index 000000000..f777ea41c --- /dev/null +++ b/bramble-j2se/src/main/java/org/briarproject/bramble/system/JavaConfigurationManager.java @@ -0,0 +1,56 @@ +package org.briarproject.bramble.system; + +import org.briarproject.bramble.api.ConfigurationManager; +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +import java.io.File; +import java.io.IOException; +import java.nio.file.attribute.PosixFilePermission; +import java.util.HashSet; +import java.util.Set; +import java.util.logging.Logger; + +import javax.inject.Inject; + +import static java.nio.file.Files.setPosixFilePermissions; +import static java.nio.file.attribute.PosixFilePermission.OWNER_EXECUTE; +import static java.nio.file.attribute.PosixFilePermission.OWNER_READ; +import static java.nio.file.attribute.PosixFilePermission.OWNER_WRITE; +import static java.util.logging.Level.WARNING; +import static org.briarproject.bramble.util.LogUtils.logException; + +@NotNullByDefault +class JavaConfigurationManager implements ConfigurationManager { + + private static final Logger LOG = + Logger.getLogger(JavaConfigurationManager.class.getName()); + + @Inject + public JavaConfigurationManager() { + try { + ensurePermissions(getAppDir()); + } catch (IOException e) { + logException(LOG, WARNING, e); + } + } + + @Override + public File getAppDir() { + String home = System.getProperty("user.home"); + return new File(home + File.separator + ".briar"); + } + + private void ensurePermissions(File file)throws IOException { + if (!file.exists()) { + if (!file.mkdirs()) { + throw new IOException("Could not create directory"); + } + } + Set perms = new HashSet<>(); + perms.add(OWNER_READ); + perms.add(OWNER_WRITE); + perms.add(OWNER_EXECUTE); + setPosixFilePermissions(file.toPath(), perms); + } + +} diff --git a/bramble-java/src/main/java/org/briarproject/bramble/system/JavaSystemModule.java b/bramble-java/src/main/java/org/briarproject/bramble/system/JavaSystemModule.java index c33192d9b..1547f6c0d 100644 --- a/bramble-java/src/main/java/org/briarproject/bramble/system/JavaSystemModule.java +++ b/bramble-java/src/main/java/org/briarproject/bramble/system/JavaSystemModule.java @@ -1,5 +1,6 @@ package org.briarproject.bramble.system; +import org.briarproject.bramble.api.ConfigurationManager; import org.briarproject.bramble.api.system.LocationUtils; import org.briarproject.bramble.api.system.ResourceProvider; @@ -11,6 +12,13 @@ import dagger.Provides; @Module public class JavaSystemModule { + @Provides + @Singleton + ConfigurationManager provideConfigurationManager( + JavaConfigurationManager configurationManager) { + return configurationManager; + } + @Provides @Singleton LocationUtils provideLocationUtils(JavaLocationUtils locationUtils) { 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 index 5d43d5488..ac3897e31 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/BriarHeadlessApp.java +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/BriarHeadlessApp.java @@ -1,7 +1,10 @@ package org.briarproject.briar.headless; + +import org.briarproject.bramble.BrambleCoreEagerSingletons; import org.briarproject.bramble.BrambleCoreModule; import org.briarproject.bramble.account.HeadlessAccountModule; import org.briarproject.bramble.system.DesktopSecureRandomModule; +import org.briarproject.briar.BriarCoreEagerSingletons; import org.briarproject.briar.BriarCoreModule; import javax.inject.Singleton; @@ -16,6 +19,7 @@ import dagger.Component; HeadlessModule.class }) @Singleton -public interface BriarHeadlessApp { +public interface BriarHeadlessApp + extends BrambleCoreEagerSingletons, BriarCoreEagerSingletons { Router router(); } \ No newline at end of file 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 index 67665dd4e..bf81001b9 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessModule.java +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/HeadlessModule.java @@ -1,67 +1,73 @@ package org.briarproject.briar.headless; +import org.briarproject.bramble.api.ConfigurationManager; 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.event.EventBus; +import org.briarproject.bramble.api.lifecycle.IoExecutor; +import org.briarproject.bramble.api.network.NetworkManager; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.bramble.api.plugin.BackoffFactory; 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.api.system.Clock; +import org.briarproject.bramble.api.system.LocationUtils; +import org.briarproject.bramble.api.system.ResourceProvider; +import org.briarproject.bramble.network.JavaNetworkModule; +import org.briarproject.bramble.plugin.tor.CircumventionModule; +import org.briarproject.bramble.plugin.tor.CircumventionProvider; +import org.briarproject.bramble.plugin.tor.LinuxTorPluginFactory; +import org.briarproject.bramble.system.JavaSystemModule; import org.briarproject.bramble.util.StringUtils; import java.io.File; -import java.io.IOException; -import java.nio.file.attribute.PosixFilePermission; import java.security.GeneralSecurityException; import java.util.Collection; -import java.util.HashSet; -import java.util.Set; -import java.util.logging.Logger; +import java.util.concurrent.Executor; import javax.inject.Singleton; +import javax.net.SocketFactory; import dagger.Module; import dagger.Provides; -import static java.nio.file.Files.setPosixFilePermissions; -import static java.nio.file.attribute.PosixFilePermission.OWNER_EXECUTE; -import static java.nio.file.attribute.PosixFilePermission.OWNER_READ; -import static java.nio.file.attribute.PosixFilePermission.OWNER_WRITE; import static java.util.Collections.emptyList; -import static java.util.logging.Level.WARNING; -import static java.util.logging.Logger.getLogger; +import static java.util.Collections.singletonList; import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_ONION_ADDRESS; import static org.briarproject.bramble.api.reporting.ReportingConstants.DEV_PUBLIC_KEY_HEX; -@Module +@Module(includes = { + JavaNetworkModule.class, + JavaSystemModule.class, + CircumventionModule.class +}) public class HeadlessModule { - private final static Logger LOG = getLogger(HeadlessModule.class.getName()); - - private final String appDir; - - public HeadlessModule() { - String home = System.getProperty("user.home"); - appDir = home + File.separator + ".briar"; - try { - ensurePermissions(new File(appDir)); - } catch (IOException e) { - LOG.log(WARNING, e.getMessage(), e); - } - } - @Provides @Singleton - DatabaseConfig provideDatabaseConfig() { - File dbDir = appDir("db"); - File keyDir = appDir("key"); + DatabaseConfig provideDatabaseConfig( + ConfigurationManager configurationManager) { + File dbDir = appDir(configurationManager, "db"); + File keyDir = appDir(configurationManager, "key"); return new HeadlessDatabaseConfig(dbDir, keyDir); } @Provides - PluginConfig providePluginConfig() { - Collection duplex = emptyList(); + PluginConfig providePluginConfig(@IoExecutor Executor ioExecutor, + SocketFactory torSocketFactory, BackoffFactory backoffFactory, + NetworkManager networkManager, LocationUtils locationUtils, + EventBus eventBus, ResourceProvider resourceProvider, + CircumventionProvider circumventionProvider, Clock clock, + ConfigurationManager configurationManager) { + File torDirectory = appDir(configurationManager, "tor"); + DuplexPluginFactory tor = new LinuxTorPluginFactory(ioExecutor, + networkManager, locationUtils, eventBus, torSocketFactory, + backoffFactory, resourceProvider, circumventionProvider, clock, + torDirectory); + Collection duplex = singletonList(tor); @NotNullByDefault PluginConfig pluginConfig = new PluginConfig() { @@ -85,7 +91,8 @@ public class HeadlessModule { @Provides @Singleton - DevConfig provideDevConfig(CryptoComponent crypto) { + DevConfig provideDevConfig(CryptoComponent crypto, + ConfigurationManager configurationManager) { @NotNullByDefault DevConfig devConfig = new DevConfig() { @@ -106,27 +113,15 @@ public class HeadlessModule { @Override public File getReportDir() { - return appDir("reportDir"); + return appDir(configurationManager, "reportDir"); } }; return devConfig; } - private File appDir(String file) { - return new File(appDir + File.separator + file); - } - - private void ensurePermissions(File file)throws IOException { - if (!file.exists()) { - if (!file.mkdirs()) { - throw new IOException("Could not create directory"); - } - } - Set perms = new HashSet<>(); - perms.add(OWNER_READ); - perms.add(OWNER_WRITE); - perms.add(OWNER_EXECUTE); - setPosixFilePermissions(file.toPath(), perms); + private File appDir(ConfigurationManager configurationManager, + String file) { + return new File(configurationManager.getAppDir(), file); } } 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 index 87074df20..6cbfe467b 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/Main.java +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/Main.java @@ -1,5 +1,8 @@ package org.briarproject.briar.headless; +import org.briarproject.bramble.BrambleCoreModule; +import org.briarproject.briar.BriarCoreModule; + import java.util.logging.Level; import java.util.logging.LogManager; import java.util.logging.Logger; @@ -16,10 +19,14 @@ public class Main { } } - DaggerBriarHeadlessApp - .create() - .router() - .start(); + BriarHeadlessApp app = DaggerBriarHeadlessApp.builder() + .headlessModule(new HeadlessModule()).build(); + // We need to load the eager singletons directly after making the + // dependency graphs + BrambleCoreModule.initEagerSingletons(app); + BriarCoreModule.initEagerSingletons(app); + + app.router().start(); } } From 787e62345fc1130b37bf1c938e4bd0c0a9ec81e6 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Fri, 24 Aug 2018 18:29:21 -0300 Subject: [PATCH 08/40] Add simple MessagingController --- .../briarproject/briar/headless/Router.java | 11 ++- .../messaging/MessagingController.java | 97 +++++++++++++++++++ .../messaging/OutputPrivateMessage.java | 43 ++++++++ 3 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingController.java create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateMessage.java 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 index 257d94ee0..60dd7feb0 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/Router.java +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/Router.java @@ -3,6 +3,7 @@ package org.briarproject.briar.headless; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.briar.headless.blogs.BlogController; import org.briarproject.briar.headless.forums.ForumController; +import org.briarproject.briar.headless.messaging.MessagingController; import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.concurrent.Immutable; @@ -25,13 +26,17 @@ import static java.lang.Runtime.getRuntime; public class Router { private final BriarService briarService; + private final MessagingController messagingController; private final ForumController forumController; private final BlogController blogController; @Inject - public Router(BriarService briarService, ForumController forumController, + public Router(BriarService briarService, + MessagingController messagingController, + ForumController forumController, BlogController blogController) { this.briarService = briarService; + this.messagingController = messagingController; this.forumController = forumController; this.blogController = blogController; } @@ -51,6 +56,10 @@ public class Router { .start(); app.routes(() -> { + path("/messages/:contactId", () -> { + get(messagingController::list); + post(messagingController::write); + }); path("/forums", () -> { get(forumController::list); post(forumController::create); diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingController.java b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingController.java new file mode 100644 index 000000000..7146bc8ce --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingController.java @@ -0,0 +1,97 @@ +package org.briarproject.briar.headless.messaging; + +import org.briarproject.bramble.api.FormatException; +import org.briarproject.bramble.api.contact.Contact; +import org.briarproject.bramble.api.contact.ContactId; +import org.briarproject.bramble.api.contact.ContactManager; +import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.db.NoSuchContactException; +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.bramble.api.sync.Group; +import org.briarproject.bramble.api.system.Clock; +import org.briarproject.briar.api.messaging.MessagingManager; +import org.briarproject.briar.api.messaging.PrivateMessage; +import org.briarproject.briar.api.messaging.PrivateMessageFactory; +import org.briarproject.briar.api.messaging.PrivateMessageHeader; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; +import javax.inject.Inject; +import javax.inject.Singleton; + +import io.javalin.Context; + +import static org.briarproject.briar.api.messaging.MessagingConstants.MAX_PRIVATE_MESSAGE_BODY_LENGTH; + +@Immutable +@Singleton +@NotNullByDefault +public class MessagingController { + + private final MessagingManager messagingManager; + private final PrivateMessageFactory privateMessageFactory; + private final ContactManager contactManager; + private final Clock clock; + + @Inject + public MessagingController(MessagingManager messagingManager, + PrivateMessageFactory privateMessageFactory, + ContactManager contactManager, + Clock clock) { + this.messagingManager = messagingManager; + this.privateMessageFactory = privateMessageFactory; + this.contactManager = contactManager; + this.clock = clock; + } + + public Context list(Context ctx) throws DbException { + Contact contact = getContact(ctx); + if (contact == null) return ctx.status(404); + + Collection headers = + messagingManager.getMessageHeaders(contact.getId()); + List messages = new ArrayList<>(headers.size()); + for (PrivateMessageHeader header : headers) { + String body = messagingManager.getMessageBody(header.getId()); + messages.add(new OutputPrivateMessage(header, body)); + } + return ctx.json(messages); + } + + public Context write(Context ctx) throws DbException, FormatException { + Contact contact = getContact(ctx); + if (contact == null) return ctx.status(404); + + String message = ctx.formParam("message"); + if (message == null || message.length() < 1) + return ctx.status(500).result("Expecting Message text"); + if (message.length() > MAX_PRIVATE_MESSAGE_BODY_LENGTH) + return ctx.status(500).result("Message text too large"); + + Group group = messagingManager.getContactGroup(contact); + long now = clock.currentTimeMillis(); + PrivateMessage m = privateMessageFactory + .createPrivateMessage(group.getId(), now, message); + + messagingManager.addLocalMessage(m); + return ctx.json(new OutputPrivateMessage(m, message)); + } + + @Nullable + private Contact getContact(Context ctx) throws DbException { + String contactString = ctx.param("contactId"); + if (contactString == null) return null; + int contactInt = Integer.parseInt(contactString); + ContactId contactId = new ContactId(contactInt); + try { + return contactManager.getContact(contactId); + } catch (NoSuchContactException e) { + return null; + } + } + +} diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateMessage.java b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateMessage.java new file mode 100644 index 000000000..6cf491d0e --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateMessage.java @@ -0,0 +1,43 @@ +package org.briarproject.briar.headless.messaging; + +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.briar.api.messaging.PrivateMessage; +import org.briarproject.briar.api.messaging.PrivateMessageHeader; + +import javax.annotation.concurrent.Immutable; + +@Immutable +@NotNullByDefault +@SuppressWarnings("WeakerAccess") +public class OutputPrivateMessage { + + public final String body; + public final long timestamp; + public final boolean read, seen, sent, local; + public final byte[] id, groupId; + + OutputPrivateMessage(PrivateMessageHeader header, String body) { + this.body = body; + this.timestamp = header.getTimestamp(); + this.read = header.isRead(); + this.seen = header.isSeen(); + this.sent = header.isSent(); + this.local = header.isLocal(); + this.id = header.getId().getBytes(); + this.groupId = header.getGroupId().getBytes(); + } + + /** + * Only meant for own {@link PrivateMessage}s directly after creation. + */ + OutputPrivateMessage(PrivateMessage m, String body) { + this.body = body; + this.timestamp = m.getMessage().getTimestamp(); + this.read = true; + this.seen = true; + this.sent = false; + this.local = true; + this.id = m.getMessage().getId().getBytes(); + this.groupId = m.getMessage().getGroupId().getBytes(); + } +} From bea77151bdc340ba2da04ad55921fa54cf676da1 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Mon, 27 Aug 2018 12:50:42 -0300 Subject: [PATCH 09/40] briar-headless: Add API to list all contacts --- .../bramble/identity/OutputAuthor.java | 23 +++++++++++ .../briarproject/briar/headless/Router.java | 5 +++ .../headless/contact/ContactController.java | 39 +++++++++++++++++++ .../briar/headless/contact/OutputContact.java | 24 ++++++++++++ 4 files changed, 91 insertions(+) create mode 100644 briar-headless/src/main/java/org/briarproject/bramble/identity/OutputAuthor.java create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactController.java create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/contact/OutputContact.java diff --git a/briar-headless/src/main/java/org/briarproject/bramble/identity/OutputAuthor.java b/briar-headless/src/main/java/org/briarproject/bramble/identity/OutputAuthor.java new file mode 100644 index 000000000..d093398b9 --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/bramble/identity/OutputAuthor.java @@ -0,0 +1,23 @@ +package org.briarproject.bramble.identity; + +import org.briarproject.bramble.api.identity.Author; +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +import javax.annotation.concurrent.Immutable; + +@Immutable +@NotNullByDefault +@SuppressWarnings("WeakerAccess") +public class OutputAuthor { + + public final byte[] id; + public final String name; + public final byte[] publicKey; + + public OutputAuthor(Author author) { + this.id = author.getId().getBytes(); + this.name = author.getName(); + this.publicKey = author.getPublicKey(); + } + +} 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 index 60dd7feb0..ff65063f1 100644 --- a/briar-headless/src/main/java/org/briarproject/briar/headless/Router.java +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/Router.java @@ -2,6 +2,7 @@ package org.briarproject.briar.headless; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.briar.headless.blogs.BlogController; +import org.briarproject.briar.headless.contact.ContactController; import org.briarproject.briar.headless.forums.ForumController; import org.briarproject.briar.headless.messaging.MessagingController; @@ -26,16 +27,19 @@ import static java.lang.Runtime.getRuntime; public class Router { private final BriarService briarService; + private final ContactController contactController; private final MessagingController messagingController; private final ForumController forumController; private final BlogController blogController; @Inject public Router(BriarService briarService, + ContactController contactController, MessagingController messagingController, ForumController forumController, BlogController blogController) { this.briarService = briarService; + this.contactController = contactController; this.messagingController = messagingController; this.forumController = forumController; this.blogController = blogController; @@ -56,6 +60,7 @@ public class Router { .start(); app.routes(() -> { + path("/contacts", () -> get(contactController::list)); path("/messages/:contactId", () -> { get(messagingController::list); post(messagingController::write); diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactController.java b/briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactController.java new file mode 100644 index 000000000..8c2be33ea --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactController.java @@ -0,0 +1,39 @@ +package org.briarproject.briar.headless.contact; + +import org.briarproject.bramble.api.contact.Contact; +import org.briarproject.bramble.api.contact.ContactManager; +import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import javax.annotation.concurrent.Immutable; +import javax.inject.Inject; +import javax.inject.Singleton; + +import io.javalin.Context; + +@Immutable +@Singleton +@NotNullByDefault +public class ContactController { + + private final ContactManager contactManager; + + @Inject + public ContactController(ContactManager contactManager) { + this.contactManager = contactManager; + } + + public Context list(Context ctx) throws DbException { + Collection contacts = contactManager.getActiveContacts(); + List outputContacts = new ArrayList<>(contacts.size()); + for (Contact c : contacts) { + outputContacts.add(new OutputContact(c)); + } + return ctx.json(outputContacts); + } + +} diff --git a/briar-headless/src/main/java/org/briarproject/briar/headless/contact/OutputContact.java b/briar-headless/src/main/java/org/briarproject/briar/headless/contact/OutputContact.java new file mode 100644 index 000000000..b5a026a0f --- /dev/null +++ b/briar-headless/src/main/java/org/briarproject/briar/headless/contact/OutputContact.java @@ -0,0 +1,24 @@ +package org.briarproject.briar.headless.contact; + +import org.briarproject.bramble.api.contact.Contact; +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.bramble.identity.OutputAuthor; + +import javax.annotation.concurrent.Immutable; + +@Immutable +@NotNullByDefault +@SuppressWarnings("WeakerAccess") +public class OutputContact { + + public final int id; + public final OutputAuthor author; + public final boolean verified; + + public OutputContact(Contact c) { + this.id = c.getId().getInt(); + this.author = new OutputAuthor(c.getAuthor()); + this.verified = c.isVerified(); + } + +} From 33c509cd1fca9e374d627ad537467c8e580bcca5 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Mon, 27 Aug 2018 14:59:01 -0300 Subject: [PATCH 10/40] briar-headless: Add Kotlin and first unit test for blogs with Mockk --- .idea/codeStyles/Project.xml | 12 +++- briar-headless/build.gradle | 20 ++++-- .../headless/blogs/BlogControllerTest.kt | 63 +++++++++++++++++++ briar-headless/witness.gradle | 37 +++++++---- 4 files changed, 112 insertions(+), 20 deletions(-) create mode 100644 briar-headless/src/test/java/org/briarproject/briar/headless/blogs/BlogControllerTest.kt diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 20f76712c..22aa80cae 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -257,5 +257,15 @@ + + - \ No newline at end of file + diff --git a/briar-headless/build.gradle b/briar-headless/build.gradle index 910ebd620..c6fbc5e6c 100644 --- a/briar-headless/build.gradle +++ b/briar-headless/build.gradle @@ -2,6 +2,7 @@ plugins { id 'java' id 'net.ltgt.apt' id 'idea' + id "org.jetbrains.kotlin.jvm" version "1.2.61" id 'witness' } apply from: 'witness.gradle' @@ -21,12 +22,12 @@ dependencies { 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" + + def junitVersion = '5.2.0' + testImplementation "org.junit.jupiter:junit-jupiter-api:$junitVersion" + testImplementation "org.junit.jupiter:junit-jupiter-params:$junitVersion" + testRuntime "org.junit.jupiter:junit-jupiter-engine:$junitVersion" + testImplementation "io.mockk:mockk:1.8.6" } jar { @@ -39,3 +40,10 @@ jar { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } } + +test { + useJUnitPlatform() + testLogging { + events "passed", "skipped", "failed" + } +} diff --git a/briar-headless/src/test/java/org/briarproject/briar/headless/blogs/BlogControllerTest.kt b/briar-headless/src/test/java/org/briarproject/briar/headless/blogs/BlogControllerTest.kt new file mode 100644 index 000000000..5df4dafa7 --- /dev/null +++ b/briar-headless/src/test/java/org/briarproject/briar/headless/blogs/BlogControllerTest.kt @@ -0,0 +1,63 @@ +package org.briarproject.briar.headless.blogs + +import io.javalin.Context +import io.mockk.every +import io.mockk.mockk +import io.mockk.slot +import io.mockk.verifySequence +import org.briarproject.bramble.api.identity.Author.Status.OURSELVES +import org.briarproject.bramble.api.identity.IdentityManager +import org.briarproject.bramble.api.system.Clock +import org.briarproject.bramble.test.TestUtils.* +import org.briarproject.bramble.util.StringUtils.getRandomString +import org.briarproject.briar.api.blog.Blog +import org.briarproject.briar.api.blog.BlogManager +import org.briarproject.briar.api.blog.BlogPostFactory +import org.briarproject.briar.api.blog.BlogPostHeader +import org.briarproject.briar.api.blog.MessageType.POST +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test + +class BlogControllerTest { + + private val blogManager = mockk() + private val blogPostFactory = mockk() + private val identityManager = mockk() + private val clock = mockk() + private val ctx = mockk() + + private val blogController = + BlogController(blogManager, blogPostFactory, identityManager, clock) + + private val group = getGroup(getClientId(), 0) + private val author = getAuthor() + private val blog = Blog(group, author, false) + private val message = getMessage(group.id) + private val body = getRandomString(5) + + @Test + fun testList() { + val header = BlogPostHeader(POST, group.id, message.id, null, 0, 0, author, OURSELVES, true, + true) + val slot = slot>() + + every { blogManager.blogs } returns listOf(blog) + every { blogManager.getPostHeaders(any()) } returns listOf(header) + every { blogManager.getPostBody(any()) } returns body + every { ctx.json(capture(slot)) } returns ctx + + blogController.listPosts(ctx) + + assertEquals(1, slot.captured.size) + assertEquals(header.id.bytes, slot.captured[0].id) + assertEquals(body, slot.captured[0].body) + + verifySequence { + blogManager.blogs + blogManager.getPostHeaders(group.id) + blogManager.getPostBody(message.id) + ctx.json(slot.captured) + } + } + +} diff --git a/briar-headless/witness.gradle b/briar-headless/witness.gradle index ae314d1ee..0f51803bd 100644 --- a/briar-headless/witness.gradle +++ b/briar-headless/witness.gradle @@ -1,6 +1,5 @@ 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', @@ -9,12 +8,18 @@ dependencyVerification { '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', + 'io.mockk:mockk-agent-api:1.8.6:mockk-agent-api-1.8.6.jar:613512c66538e6349e03df641a868f4ee324f13e2e1dbd67a0ed388aa664a444', + 'io.mockk:mockk-agent-common:1.8.6:mockk-agent-common-1.8.6.jar:cb7cb26fae5bfd3c89090858548990f311b27f673b9efa9d0c94f97c463b2863', + 'io.mockk:mockk-agent-jvm:1.8.6:mockk-agent-jvm-1.8.6.jar:3f30b98d23ada8b5a44d75b43cd58fc03252fcb96939ff31e7ad659818af1e5d', + 'io.mockk:mockk-common:1.8.6:mockk-common-1.8.6.jar:a04b0e2fc7d583807cf89f3bbf5c7501808725e49e385d95486e1008d8ab2ba8', + 'io.mockk:mockk-dsl-jvm:1.8.6:mockk-dsl-jvm-1.8.6.jar:c2c5df747ff04d1a3e02212b7b43f9ba4233597ae278928598275d7a7bb26d73', + 'io.mockk:mockk-dsl:1.8.6:mockk-dsl-1.8.6.jar:f6014265fe88ef1290c936741bdd0a7c3d9ceba9ee3bd2a153d65b05e1fc7946', + 'io.mockk:mockk:1.8.6:mockk-1.8.6.jar:0a200d71bab11facfe50637b1980f53c07a21bfa4dd9eb021ac8e8cc693924b2', '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', + 'net.bytebuddy:byte-buddy-agent:1.8.8:byte-buddy-agent-1.8.8.jar:dc1a2dcefe72731fa89ae84e32231c74d545ccf8216c79865096e546f20c57e8', + 'net.bytebuddy:byte-buddy:1.8.8:byte-buddy-1.8.8.jar:30aed1ae2ee5261b1d2f0e98ec3fcb40755c3f61b378089fb65d56098df1f16b', + 'org.apiguardian:apiguardian-api:1.0.0:apiguardian-api-1.0.0.jar:1f58b77470d8d147a0538d515347dd322f49a83b9e884b8970051160464b65b3', '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', @@ -29,18 +34,24 @@ dependencyVerification { '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-compiler-embeddable:1.2.61:kotlin-compiler-embeddable-1.2.61.jar:f8165810c61f440a2de6003ed9857d28a1dfc990bacbecee1436610c8ebe565b', + 'org.jetbrains.kotlin:kotlin-reflect:1.2.41:kotlin-reflect-1.2.41.jar:1bab75771dfa2bb5949cd383ceaedf6f8d354fa0d677804fc5a39e320bab70d3', + 'org.jetbrains.kotlin:kotlin-reflect:1.2.61:kotlin-reflect-1.2.61.jar:a4f1ed542390f9bf967fb9aff2c232b90988f7ce138a4b7bcc70b754821a8943', + 'org.jetbrains.kotlin:kotlin-script-runtime:1.2.61:kotlin-script-runtime-1.2.61.jar:793e4c54a8d59cf1f1cda68a7bc6be1ad54c41d771a08d308aa28c2cd304f1b1', + 'org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:1.2.61:kotlin-scripting-compiler-embeddable-1.2.61.jar:99e0ee865f9c7c8ddcc0975185c69392182311067fe2a6faa72e942185631c1c', + 'org.jetbrains.kotlin:kotlin-stdlib-common:1.2.61:kotlin-stdlib-common-1.2.61.jar:54a6fab7dae0cd7528208e95868fe1869b01b613c3018f2e53dbbad2604f6595', '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.kotlin:kotlin-stdlib:1.2.61:kotlin-stdlib-1.2.61.jar:62eaf9cc6e746cef4593abe7cdb4dd48694ef5f817c852e0d9fbbd11fcfc564e', '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.junit.jupiter:junit-jupiter-api:5.2.0:junit-jupiter-api-5.2.0.jar:47f7d71b35dc331210b9ab219bbb00d54332981aa12eb5effe817de17e1ae7b3', + 'org.junit.jupiter:junit-jupiter-engine:5.2.0:junit-jupiter-engine-5.2.0.jar:8f994f4094790e246dc84de86a1ff4194ca85e8b13bedaca0207f727ebfbc813', + 'org.junit.jupiter:junit-jupiter-params:5.2.0:junit-jupiter-params-5.2.0.jar:34ce02519044ef68217002f640a83e267c4001ce53b68270218d49d00449a836', + 'org.junit.platform:junit-platform-commons:1.2.0:junit-platform-commons-1.2.0.jar:7771af2f797d1d0ccce9920eb3cd826fb8fd7659ccb4d8877e76d9412be72cc2', + 'org.junit.platform:junit-platform-engine:1.2.0:junit-platform-engine-1.2.0.jar:60b102e94ea01556fdc8c041950a05450edc188e3708f032a6bfb1a50ba0bc22', + 'org.objenesis:objenesis:2.6:objenesis-2.6.jar:5e168368fbc250af3c79aa5fef0c3467a2d64e5a7bd74005f25d8399aeb0708d', + 'org.opentest4j:opentest4j:1.1.0:opentest4j-1.1.0.jar:65a5fd7380f53aac708bcee3091dbe2dba73a9a2e7645b66e70e0804fc36ee3b', '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', ] From 348968018a78b5c70f25a88db621172feff9b0e5 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Mon, 27 Aug 2018 16:26:41 -0300 Subject: [PATCH 11/40] Migrate REST classes to Kotlin and upgrade Javalin --- .idea/codeStyles/Project.xml | 11 +-- briar-headless/build.gradle | 3 +- .../bramble/identity/OutputAuthor.java | 23 ----- .../bramble/identity/OutputAuthor.kt | 14 +++ .../briarproject/briar/headless/Extensions.kt | 12 +++ .../briarproject/briar/headless/Router.java | 79 --------------- .../org/briarproject/briar/headless/Router.kt | 68 +++++++++++++ .../briar/headless/blogs/BlogController.java | 81 ---------------- .../briar/headless/blogs/BlogController.kt | 47 +++++++++ .../briar/headless/blogs/Extensions.kt | 5 + .../briar/headless/blogs/OutputBlogPost.java | 38 -------- .../briar/headless/blogs/OutputBlogPost.kt | 22 +++++ .../headless/contact/ContactController.java | 39 -------- .../headless/contact/ContactController.kt | 21 ++++ .../briar/headless/contact/Extensions.kt | 5 + .../briar/headless/contact/OutputContact.java | 24 ----- .../briar/headless/contact/OutputContact.kt | 15 +++ .../briar/headless/forums/Extensions.kt | 7 ++ .../headless/forums/ForumController.java | 47 --------- .../briar/headless/forums/ForumController.kt | 26 +++++ .../briar/headless/forums/OutputForum.kt | 13 +++ .../briar/headless/messaging/Extensions.kt | 8 ++ .../messaging/MessagingController.java | 97 ------------------- .../headless/messaging/MessagingController.kt | 66 +++++++++++++ .../messaging/OutputPrivateMessage.java | 43 -------- .../messaging/OutputPrivateMessage.kt | 44 +++++++++ briar-headless/witness.gradle | 35 ++++--- 27 files changed, 397 insertions(+), 496 deletions(-) delete mode 100644 briar-headless/src/main/java/org/briarproject/bramble/identity/OutputAuthor.java create mode 100644 briar-headless/src/main/java/org/briarproject/bramble/identity/OutputAuthor.kt create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/Extensions.kt delete mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/Router.java create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/Router.kt delete mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogController.java create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/blogs/BlogController.kt create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/blogs/Extensions.kt delete mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/blogs/OutputBlogPost.java create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/blogs/OutputBlogPost.kt delete mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactController.java create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/contact/ContactController.kt create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/contact/Extensions.kt delete mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/contact/OutputContact.java create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/contact/OutputContact.kt create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/forums/Extensions.kt delete mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumController.java create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/forums/ForumController.kt create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/forums/OutputForum.kt create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/messaging/Extensions.kt delete mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingController.java create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/messaging/MessagingController.kt delete mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateMessage.java create mode 100644 briar-headless/src/main/java/org/briarproject/briar/headless/messaging/OutputPrivateMessage.kt diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 22aa80cae..642d980d4 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -36,6 +36,9 @@