Some refactoring, added Swagger documentation

This commit is contained in:
Christian Basler 2015-11-20 21:43:14 +01:00
parent d322d09604
commit 7adf048438
13 changed files with 122 additions and 333 deletions

2
.gitignore vendored
View File

@ -1,6 +1,8 @@
# Project specific files
*list.conf
config.properties
/*.db
/application.properties
# Created by https://www.gitignore.io

View File

@ -37,6 +37,8 @@ dependencies {
compile("org.springframework.boot:spring-boot-starter-hateoas")
compile("org.springframework.boot:spring-boot-starter-jersey")
compile("org.springframework.boot:spring-boot-starter-web")
compile("io.springfox:springfox-swagger2:2.0.2")
compile("io.springfox:springfox-swagger-ui:2.0.2")
compile 'ch.dissem.jabit:jabit-domain:0.2.1-SNAPSHOT'
compile 'ch.dissem.jabit:jabit-networking:0.2.1-SNAPSHOT'

View File

@ -16,90 +16,15 @@
package ch.dissem.bitmessage.server;
import ch.dissem.bitmessage.BitmessageContext;
import ch.dissem.bitmessage.entity.BitmessageAddress;
import ch.dissem.bitmessage.entity.Plaintext;
import ch.dissem.bitmessage.server.entities.Broadcasts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.context.annotation.ComponentScan;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.inject.Inject;
import java.util.List;
import java.util.Set;
import java.util.Timer;
import static ch.dissem.bitmessage.server.Converter.broadcasts;
import static ch.dissem.bitmessage.server.Converter.message;
@CrossOrigin
@RestController
@SpringBootApplication
@EnableSwagger2
@ComponentScan(basePackageClasses = JabitServerController.class)
public class JabitServerApplication {
private static final Logger LOG = LoggerFactory.getLogger(JabitServerApplication.class);
private static final long HOUR = 60 * 60 * 1000l; // in ms
private static final String CONFIG_FILE = "config.properties";
private static final String PROPERTY_PORT = "port";
private static final int SHORTLIST_SIZE = 5;
@Resource
private Set<String> whitelist;
@Resource
private Set<String> shortlist;
@Resource
private Set<String> blacklist;
@Inject
private BitmessageContext ctx;
@RequestMapping("status")
public String status() {
return ctx.status().toString();
}
@RequestMapping("read/{broadcastAddress}")
public Broadcasts read(@PathVariable String broadcastAddress) {
BitmessageAddress broadcaster = ctx.addresses().getAddress(broadcastAddress);
if (broadcaster == null) {
broadcaster = new BitmessageAddress(broadcastAddress);
}
if (!whitelist.isEmpty() && !whitelist.contains(broadcaster.getAddress())) {
return broadcasts(broadcaster, message("Not Whitelisted", "Messages for " + broadcaster +
" can't be shown, as the sender isn't on the whitelist."));
}
if (blacklist.contains(broadcaster.getAddress())) {
return broadcasts(broadcaster, message("Blacklisted", "Unfortunately, " + broadcaster +
" is on the blacklist, so it's messages can't be shown."));
}
if (!broadcaster.isSubscribed()) {
ctx.addSubscribtion(broadcaster);
}
List<Plaintext> messages = ctx.messages().findMessages(broadcaster);
if (shortlist.contains(broadcaster.getAddress())) {
while (messages.size() > SHORTLIST_SIZE) {
ctx.messages().remove(messages.get(messages.size() - 1));
messages.remove(messages.size() - 1);
}
}
return broadcasts(broadcaster, messages);
}
@PostConstruct
public void setUp() {
ctx.startup();
new Timer().scheduleAtFixedRate(new CleanupJob(ctx), 1 * HOUR, 24 * HOUR);
}
public static void main(String[] args) {
SpringApplication.run(JabitServerApplication.class, args);

View File

@ -11,6 +11,8 @@ import ch.dissem.bitmessage.security.bc.BouncySecurity;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import java.util.Set;
@ -71,4 +73,11 @@ public class JabitServerConfig {
"# Bitmessage addresses in this file are being ignored and their broadcasts won't be returned.\n"
);
}
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.build();
}
}

View File

@ -0,0 +1,96 @@
package ch.dissem.bitmessage.server;
import ch.dissem.bitmessage.BitmessageContext;
import ch.dissem.bitmessage.entity.BitmessageAddress;
import ch.dissem.bitmessage.entity.Plaintext;
import ch.dissem.bitmessage.server.entities.Broadcasts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.inject.Inject;
import java.util.List;
import java.util.Set;
import java.util.Timer;
import static ch.dissem.bitmessage.server.Converter.broadcasts;
import static ch.dissem.bitmessage.server.Converter.message;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
/**
* @author Christian Basler
*/
@CrossOrigin
@RestController
public class JabitServerController {
private static final Logger LOG = LoggerFactory.getLogger(JabitServerController.class);
private static final long HOUR = 60 * 60 * 1000l; // in ms
private static final String CONFIG_FILE = "config.properties";
private static final String PROPERTY_PORT = "port";
private static final int SHORTLIST_SIZE = 5;
@Resource
private Set<String> whitelist;
@Resource
private Set<String> shortlist;
@Resource
private Set<String> blacklist;
@Inject
private BitmessageContext ctx;
@RequestMapping(value = "status", method = GET, produces = "application/json")
public String status() {
return ctx.status().toString();
}
@RequestMapping(value = "read/{broadcastAddress}", method = GET)
public Broadcasts read(@PathVariable String broadcastAddress) {
if ("test".equalsIgnoreCase(broadcastAddress)) {
return broadcasts(
new BitmessageAddress("BM-2cWhyaPxydemCeM8dWJUBmEo8iu7v2JptK"),
message("Test", "This is a test message. The rest service is running."),
message("Another Test", "And because it's such fun, a second message.")
);
}
BitmessageAddress broadcaster = ctx.addresses().getAddress(broadcastAddress);
if (broadcaster == null) {
broadcaster = new BitmessageAddress(broadcastAddress);
}
if (!whitelist.isEmpty() && !whitelist.contains(broadcaster.getAddress())) {
return broadcasts(broadcaster, message("Not Whitelisted", "Messages for " + broadcaster +
" can't be shown, as the sender isn't on the whitelist."));
}
if (blacklist.contains(broadcaster.getAddress())) {
return broadcasts(broadcaster, message("Blacklisted", "Unfortunately, " + broadcaster +
" is on the blacklist, so it's messages can't be shown."));
}
if (!broadcaster.isSubscribed()) {
ctx.addSubscribtion(broadcaster);
}
List<Plaintext> messages = ctx.messages().findMessages(broadcaster);
if (shortlist.contains(broadcaster.getAddress())) {
while (messages.size() > SHORTLIST_SIZE) {
ctx.messages().remove(messages.get(messages.size() - 1));
messages.remove(messages.size() - 1);
}
}
return broadcasts(broadcaster, messages);
}
@PostConstruct
public void setUp() {
ctx.startup();
new Timer().scheduleAtFixedRate(new CleanupJob(ctx), 1 * HOUR, 24 * HOUR);
}
}

View File

@ -20,6 +20,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
float: right;
font-size: 60%;
}
.paper-font-body2 {
white-space: pre-wrap;
}
@ -59,7 +60,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
},
server: {
type: String,
value: 'http://localhost:8080',
value: location.port === 5000 ? 'http://localhost:8080/' : '',
notify: true
}
},
@ -68,7 +69,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
return new Date(timestamp * 1000).toLocaleString();
},
getUrl: function (server, address) {
return server + '/read/' + address;
console.log(server + 'read/' + address);
return server + 'read/' + address;
}
});
})();

View File

@ -1,44 +0,0 @@
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<link rel="import" href="../../bower_components/polymer/polymer.html">
<dom-module id="my-greeting">
<template>
<style include="shared-styles"></style>
<style>
:host {
display: block;
}
</style>
<h2 class="page-title"><span>{{greeting}}</span></h2>
<span class="paper-font-body2">Update text to change the greeting.</span>
<!-- Listens for "input" event and sets greeting to <input>.value -->
<input class="paper-font-body2" value="{{greeting::input}}">
</template>
<script>
(function() {
'use strict';
Polymer({
is: 'my-greeting',
properties: {
greeting: {
type: String,
value: 'Welcome!',
notify: true
}
}
});
})();
</script>
</dom-module>

View File

@ -1,52 +0,0 @@
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<link rel="import" href="../../bower_components/polymer/polymer.html">
<dom-module id="my-list">
<template>
<style>
:host {
display: block;
}
</style>
<ul>
<template is="dom-repeat" items="{{items}}">
<li><span class="paper-font-body1">{{item}}</span></li>
</template>
</ul>
</template>
<script>
(function () {
'use strict';
Polymer({
is: 'my-list',
properties: {
items: {
type: Array,
notify: true,
}
},
ready: function() {
this.items = [
'Responsive Web App boilerplate',
'Iron Elements and Paper Elements',
'End-to-end Build Tooling (including Vulcanize)',
'Unit testing with Web Component Tester',
'Routing with Page.js',
'Offline support with the Platinum Service Worker Elements'
];
}
});
})();
</script>
</dom-module>

View File

@ -34,6 +34,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
page('/read/:address', scrollToTop, function(data) {
app.route = 'message-list';
app.params = data.params;
console.log(data);
});
// add #! before urls

View File

@ -16,9 +16,8 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN
var app = document.querySelector('#app');
app.join = function() {
var index = 0;
var result = '';
for (index = 0; index < arguments.length; index++) {
for (var index = 0; index < arguments.length; index++) {
result += arguments[index];
}
return result;

View File

@ -1,32 +0,0 @@
<!doctype html>
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html>
<head>
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<title>Elements Test Runner</title>
<meta charset="UTF-8">
<script src="../../bower_components/webcomponentsjs/webcomponents.min.js"></script>
<script src="../../bower_components/web-component-tester/browser.js"></script>
</head>
<body>
<script>
WCT.loadSuites(['my-greeting-basic.html', 'my-list-basic.html']);
</script>
</body>
</html>

View File

@ -1,52 +0,0 @@
<!doctype html>
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html>
<head>
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<title>my-greeting-basic</title>
<script src="../../bower_components/webcomponentsjs/webcomponents.min.js"></script>
<script src="../../bower_components/web-component-tester/browser.js"></script>
<script src="../../bower_components/test-fixture/test-fixture-mocha.js"></script>
<link rel="import" href="../../bower_components/test-fixture/test-fixture.html">
<!-- Import the element to test -->
<link rel="import" href="../elements/my-greeting/my-greeting.html">
</head>
<body>
<test-fixture id="basic">
<template>
<my-greeting></my-greeting>
</template>
</test-fixture>
<script>
suite('my-greeting tests', function() {
var greeting, header;
setup(function() {
greeting = fixture('basic');
});
test('Welcome!', function() {
header = greeting.querySelector('h2');
assert.equal(header.textContent, 'Welcome!');
});
});
</script>
</body>
</html>

View File

@ -1,67 +0,0 @@
<!doctype html>
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html>
<head>
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<title>my-list-basic</title>
<script src="../../bower_components/webcomponentsjs/webcomponents.min.js"></script>
<script src="../../bower_components/web-component-tester/browser.js"></script>
<script src="../../bower_components/test-fixture/test-fixture-mocha.js"></script>
<link rel="import" href="../../bower_components/test-fixture/test-fixture.html">
<!-- Import the element to test -->
<link rel="import" href="../elements/my-list/my-list.html">
</head>
<body>
<test-fixture id="basic">
<template>
<my-list></my-list>
</template>
</test-fixture>
<script>
suite('my-list tests', function() {
var list, listItems;
setup(function() {
list = fixture('basic');
});
test('Item lengths should be equalled', function(done) {
// Test a property
// TODO: Fix list.items.push('Foo') causing a WeakMap exception
// Invalid value used as weak map key
list.items = [
'Responsive Web App boilerplate',
'Iron Elements and Paper Elements',
'End-to-end Build Tooling (including Vulcanize)',
'Unit testing with Web Component Tester',
'Routing with Page.js',
'Offline support with the Platinum Service Worker Elements'
];
// Data bindings will stamp out new DOM asynchronously
// so wait to check for updates
flush(function() {
listItems = list.querySelectorAll('li');
assert.equal(list.items.length, listItems.length);
done();
});
})
});
</script>
</body>
</html>