Skip to content

Commit f1cc87d

Browse files
committed
Add dashboard
1) Move cache polling out of StatusController. 2) Simplify view logic. 3) Make recent transaction json output work. 4) Add dashboard view.
1 parent e437de4 commit f1cc87d

28 files changed

+859
-365
lines changed

Procfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
web: java $JAVA_OPTS -Ddw.http.port=$PORT -Ddw.http.adminPort=$PORT -Ddw.github.user=$GITHUB_USER -Ddw.github.token=$GITHUB_TOKEN -Ddw.github.repositories_heroku="$GITHUB_REPOSITORIES" -Ddw.coinbase.apiKey=$COINBASE_API_KEY -Ddw.github.webhook.password=$GITHUB_WEBHOOK_PASSWORD -jar target/BitHub-0.1.jar server
1+
web: java $JAVA_OPTS -Ddw.server.type=simple -Ddw.server.applicationContextPath=/ -Ddw.server.connector.type=http -Ddw.server.connector.port=$PORT -Ddw.github.user=$GITHUB_USER -Ddw.github.token=$GITHUB_TOKEN -Ddw.github.repositories_heroku="$GITHUB_REPOSITORIES" -Ddw.coinbase.apiKey=$COINBASE_API_KEY -Ddw.github.webhook.password=$GITHUB_WEBHOOK_PASSWORD -Ddw.organization.name="$ORGANIZATION_NAME" -Ddw.organization.donationUrl=$DONATION_URL -jar target/BitHub-0.1.jar server

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ $ heroku config:set GITHUB_TOKEN=your_bithub_authtoken
3838
$ heroku config:set GITHUB_WEBHOOK_PASSWORD=your_webhook_password
3939
$ heroku config:set GITHUB_REPOSITORIES="[{\"url\" : \"https://github.com/youraccount/yourrepo\"}, {\"url\" : \"https://github.com/youraccount/yourotherrepo\"}]"
4040
$ heroku config:set COINBASE_API_KEY=your_api_key
41+
$ heroku config:set ORGANIZATION_NAME=your_organization_name
42+
$ heroku config:set DONATION_URL=your_donation_url
4143
$ git remote add your_heroku_remote
4244
$ git push heroku master
4345
```

config/sample.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1+
organization:
2+
name: # Your name (eg. Open Whisper Systems)
3+
donationUrl: # A Coinbase link where you can receive donations (eg. https://coinbase.com/checkouts/d29fd4c37ca442393e32fdcb95304701)
4+
15
github:
26
user: # Your BitHub instance's GitHub username.
37
token: # Your BitHub instance's GitHub auth token.
8+
49
webhook:
510
password: # HTTP basic auth. The username defaults to "bithub".
11+
612
repositories: # A list of repository URLs to support payouts for.
713
- url: # A repository's URL
814
mode: # Either MONEYMONEY (default) or FREEBIE.

pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@
5656
<artifactId>dropwizard-views</artifactId>
5757
<version>${dropwizard.version}</version>
5858
</dependency>
59+
<dependency>
60+
<groupId>io.dropwizard</groupId>
61+
<artifactId>dropwizard-views-mustache</artifactId>
62+
<version>${dropwizard.version}</version>
63+
</dependency>
5964
<dependency>
6065
<groupId>io.dropwizard</groupId>
6166
<artifactId>dropwizard-servlets</artifactId>

src/main/java/org/whispersystems/bithub/BithubServerConfiguration.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.whispersystems.bithub.config.BithubConfiguration;
2222
import org.whispersystems.bithub.config.CoinbaseConfiguration;
2323
import org.whispersystems.bithub.config.GithubConfiguration;
24+
import org.whispersystems.bithub.config.OrganizationConfiguration;
2425

2526
import javax.validation.Valid;
2627
import javax.validation.constraints.NotNull;
@@ -43,6 +44,11 @@ public class BithubServerConfiguration extends Configuration {
4344
@Valid
4445
private BithubConfiguration bithub = new BithubConfiguration();
4546

47+
@Valid
48+
@NotNull
49+
@JsonProperty
50+
private OrganizationConfiguration organization;
51+
4652

4753
public GithubConfiguration getGithubConfiguration() {
4854
return github;
@@ -56,4 +62,7 @@ public BithubConfiguration getBithubConfiguration() {
5662
return bithub;
5763
}
5864

65+
public OrganizationConfiguration getOrganizationConfiguration() {
66+
return organization;
67+
}
5968
}

src/main/java/org/whispersystems/bithub/BithubService.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@
2222
import org.whispersystems.bithub.client.CoinbaseClient;
2323
import org.whispersystems.bithub.client.GithubClient;
2424
import org.whispersystems.bithub.config.RepositoryConfiguration;
25+
import org.whispersystems.bithub.controllers.DashboardController;
2526
import org.whispersystems.bithub.controllers.GithubController;
2627
import org.whispersystems.bithub.controllers.StatusController;
2728
import org.whispersystems.bithub.mappers.IOExceptionMapper;
2829
import org.whispersystems.bithub.mappers.UnauthorizedHookExceptionMapper;
30+
import org.whispersystems.bithub.storage.CacheManager;
2931

3032
import javax.servlet.DispatcherType;
3133
import java.math.BigDecimal;
@@ -60,14 +62,22 @@ public void run(BithubServerConfiguration config, Environment environment)
6062
String githubWebhookPwd = config.getGithubConfiguration().getWebhookConfiguration().getPassword();
6163
List<RepositoryConfiguration> githubRepositories = config.getGithubConfiguration().getRepositories();
6264
BigDecimal payoutRate = config.getBithubConfiguration().getPayoutRate();
63-
GithubClient githubClient = new GithubClient(githubUser, githubToken);
64-
CoinbaseClient coinbaseClient = new CoinbaseClient(config.getCoinbaseConfiguration().getApiKey());
65+
String organizationName = config.getOrganizationConfiguration().getName();
66+
String donationUrl = config.getOrganizationConfiguration().getDonationUrl().toExternalForm();
67+
68+
GithubClient githubClient = new GithubClient(githubUser, githubToken);
69+
CoinbaseClient coinbaseClient = new CoinbaseClient(config.getCoinbaseConfiguration().getApiKey());
70+
CacheManager cacheManager = new CacheManager(coinbaseClient, githubClient, githubRepositories, payoutRate);
6571

6672
environment.servlets().addFilter("CORS", CrossOriginFilter.class)
6773
.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
68-
74+
75+
environment.lifecycle().manage(cacheManager);
76+
6977
environment.jersey().register(new GithubController(githubRepositories, githubClient, coinbaseClient, payoutRate));
70-
environment.jersey().register(new StatusController(coinbaseClient, payoutRate));
78+
environment.jersey().register(new StatusController(cacheManager, githubRepositories));
79+
environment.jersey().register(new DashboardController(organizationName, donationUrl, cacheManager));
80+
7181
environment.jersey().register(new IOExceptionMapper());
7282
environment.jersey().register(new UnauthorizedHookExceptionMapper());
7383
environment.jersey().register(new BasicAuthProvider<>(new GithubWebhookAuthenticator(githubWebhookUser, githubWebhookPwd),

src/main/java/org/whispersystems/bithub/client/CoinbaseClient.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
import org.whispersystems.bithub.entities.BitcoinTransaction;
3131
import org.whispersystems.bithub.entities.BitcoinTransactionResponse;
3232
import org.whispersystems.bithub.entities.ExchangeRate;
33-
import org.whispersystems.bithub.entities.RecentTransactionsResponse;
34-
import org.whispersystems.bithub.entities.Transaction;
33+
import org.whispersystems.bithub.entities.CoinbseRecentTransactionsResponse;
34+
import org.whispersystems.bithub.entities.CoinbaseTransaction;
3535

3636
import javax.ws.rs.core.MediaType;
3737
import java.io.IOException;
@@ -59,12 +59,12 @@ public CoinbaseClient(String apiKey) {
5959
this.client = Client.create(getClientConfig());
6060
}
6161

62-
public List<Transaction> getRecentTransactions() throws IOException {
62+
public List<CoinbaseTransaction> getRecentTransactions() throws IOException {
6363
try {
6464
return client.resource(COINBASE_URL)
6565
.path(RECENT_TRANSACTIONS_PATH)
6666
.queryParam("api_key", apiKey)
67-
.get(RecentTransactionsResponse.class).getTransactions();
67+
.get(CoinbseRecentTransactionsResponse.class).getTransactions();
6868
} catch (UniformInterfaceException | ClientHandlerException e) {
6969
throw new IOException(e);
7070
}

src/main/java/org/whispersystems/bithub/client/GithubClient.java

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,10 @@
4242
*/
4343
public class GithubClient {
4444

45-
private static final String GITHUB_URL = "https://api.github.com/";
46-
private static final String COMMENT_PATH = "/repos/%s/%s/commits/%s/comments";
45+
private static final String GITHUB_URL = "https://api.github.com/";
46+
private static final String COMMENT_PATH = "/repos/%s/%s/commits/%s/comments";
47+
private static final String COMMIT_PATH = "/repos/%s/%s/git/commits/%s";
48+
private static final String REPOSITORY_PATH = "/repos/%s/%s";
4749

4850
private final Logger logger = LoggerFactory.getLogger(GithubClient.class);
4951

@@ -55,6 +57,37 @@ public GithubClient(String user, String token) {
5557
this.client = Client.create(getClientConfig());
5658
}
5759

60+
public String getCommitDescription(String commitUrl) {
61+
String[] commitUrlParts = commitUrl.split("/");
62+
String owner = commitUrlParts[commitUrlParts.length - 4];
63+
String repository = commitUrlParts[commitUrlParts.length - 3];
64+
String commit = commitUrlParts[commitUrlParts.length - 1];
65+
66+
String path = String.format(COMMIT_PATH, owner, repository, commit);
67+
WebResource resource = client.resource(GITHUB_URL).path(path);
68+
Commit response = resource.type(MediaType.APPLICATION_JSON_TYPE)
69+
.accept(MediaType.APPLICATION_JSON_TYPE)
70+
.header("Authorization", authorizationHeader)
71+
.get(Commit.class);
72+
73+
return response.getMessage();
74+
}
75+
76+
public Repository getRepository(String url) {
77+
String[] urlParts = url.split("/");
78+
String owner = urlParts[urlParts.length - 2];
79+
String name = urlParts[urlParts.length - 1];
80+
81+
String path = String.format(REPOSITORY_PATH, owner, name);
82+
WebResource resource = client.resource(GITHUB_URL).path(path);
83+
84+
return resource.type(MediaType.APPLICATION_JSON_TYPE)
85+
.accept(MediaType.APPLICATION_JSON_TYPE)
86+
.header("Authorization", authorizationHeader)
87+
.get(Repository.class);
88+
89+
}
90+
5891
public void addCommitComment(Repository repository, Commit commit, String comment) {
5992
try {
6093
String path = String.format(COMMENT_PATH, repository.getOwner().getName(),
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package org.whispersystems.bithub.config;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
import org.hibernate.validator.constraints.NotEmpty;
5+
6+
import javax.validation.Valid;
7+
import java.net.URL;
8+
9+
public class OrganizationConfiguration {
10+
11+
@JsonProperty
12+
@NotEmpty
13+
private String name;
14+
15+
@JsonProperty
16+
@Valid
17+
private URL donationUrl;
18+
19+
public String getName() {
20+
return name;
21+
}
22+
23+
public URL getDonationUrl() {
24+
return donationUrl;
25+
}
26+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package org.whispersystems.bithub.controllers;
2+
3+
import com.codahale.metrics.annotation.Timed;
4+
import org.whispersystems.bithub.storage.CacheManager;
5+
import org.whispersystems.bithub.views.DashboardView;
6+
7+
import javax.ws.rs.GET;
8+
import javax.ws.rs.Path;
9+
import javax.ws.rs.Produces;
10+
import javax.ws.rs.core.MediaType;
11+
12+
@Path("/")
13+
public class DashboardController {
14+
15+
private final CacheManager cacheManager;
16+
private final String organizationName;
17+
private final String donationUrl;
18+
19+
20+
21+
public DashboardController(String organizationName, String donationUrl,
22+
CacheManager cacheManager)
23+
{
24+
this.organizationName = organizationName;
25+
this.donationUrl = donationUrl;
26+
this.cacheManager = cacheManager;
27+
}
28+
29+
@Timed
30+
@GET
31+
@Produces(MediaType.TEXT_HTML)
32+
public DashboardView getDashboard() {
33+
return new DashboardView(organizationName, donationUrl,
34+
cacheManager.getCurrentPaymentAmount(),
35+
cacheManager.getRepositories(),
36+
cacheManager.getRecentTransactions());
37+
}
38+
39+
}

0 commit comments

Comments
 (0)