Skip to content

Commit

Permalink
Merge pull request #53 from stzups/dev
Browse files Browse the repository at this point in the history
v0.4 Project structure rework, Database rework
  • Loading branch information
griffinht authored Apr 14, 2021
2 parents f384493 + 549afb6 commit d48ff34
Show file tree
Hide file tree
Showing 133 changed files with 2,081 additions and 916 deletions.
6 changes: 6 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# These are explicitly windows files and should use crlf
*.bat text eol=crlf

11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.idea

# Gradle
.gradle
build
# Gradle binaries
# These are not needed for building the project with Docker
# These would be needed to build the projct without Docker, so instead just install Gradle on your system
gradle
gradlew
gradlew.bat
32 changes: 31 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,34 @@ Document update/delete operations, overhaul db and config
- Fix connected clients list
- Add db creation scripts into version control
- Overhaul config - improve exceptions
- Add document update and delete functionality
- Add document update and delete functionality

## v0.4
Project structure rework, invite codes

### v0.4.0
Invite codes, better state management
- Client can get invite codes for a document, persisted in db
- Client can join with an invite code
- Better server state management

### v0.4.1
Docker deployment improvements
- Fix credential typo
- Minify javascript
- Add retry logic to board-room

### v0.4.2
Swap Maven for Gradle, add board-http, Database rework
- Add Redis
- Add board-backend and refactor common Java code into Maven module

### v0.4.3
Proper cookie authentication
- Session cookies and persistent cookies
- Db caching of session cookies
- No more XSS vulnerable local storage token store

### v0.4.4
Bugfixes, better urls/file paths
- Fix cookies not having proper security properties
21 changes: 21 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#
# Build Gradle project
#
FROM gradle:jdk11 AS board-gradle-build

WORKDIR /usr/src/app

COPY . .
RUN gradle shadowJar

#
# Store resulting binaries in fresh layer (significantly cuts down on size) for other Docker images to use
#
FROM scratch

WORKDIR /usr/src/app

COPY --from=board-gradle-build /usr/src/app/board-backend/build/libs/board-backend-all.jar board-backend.jar
COPY --from=board-gradle-build /usr/src/app/board-room/build/libs/board-room-all.jar board-room.jar
# Example usage from other image
# COPY --from=board-gradle /usr/src/app/example.ext .
14 changes: 14 additions & 0 deletions board-backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM adoptopenjdk/openjdk11:alpine-jre

# Copy HTTP stuff
# Everything here can be served by the HTTP server
WORKDIR /usr/app/html

COPY --from=board-frontend /usr/src/app/dist/ ./

# Copy actual jar
WORKDIR /usr/app

COPY --from=board-gradle /usr/src/app/board-backend.jar .

ENTRYPOINT ["java", "-jar", "board-backend.jar"]
29 changes: 29 additions & 0 deletions board-backend/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
plugins {
id 'application'
id 'com.github.johnrengelman.shadow' version '6.1.0'
}

repositories {
mavenCentral()
}

dependencies {
implementation project(':board-commons')
}

// https://github.com/johnrengelman/shadow/issues/609#issuecomment-795983873
application {
mainClass.set('net.stzups.board.backend.BoardBackend')
}

shadow {
mainClassName = application.mainClass.get()
}

sourceSets {
main {
resources {
srcDirs "src/main/resources"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package net.stzups.board.backend;

import io.netty.channel.ChannelFuture;
import net.stzups.board.BoardConfigKeys;
import net.stzups.board.backend.server.Server;
import net.stzups.board.data.database.BoardDatabase;
import net.stzups.board.data.database.Database;
import net.stzups.board.util.LogFactory;
import net.stzups.board.util.config.Config;
import net.stzups.board.util.config.configs.ArgumentConfig;
import net.stzups.board.util.config.configs.EnvironmentVariableConfig;
import net.stzups.board.util.config.configs.PropertiesConfig;

import java.util.logging.Logger;

public class BoardBackend {
private static final Logger logger = LogFactory.getLogger("BoardBackend");
private static final Config config = new Config();
private static Database database;

public static void main(String[] args) throws Exception {
logger.info("Starting Board Backend server...");

long start = System.currentTimeMillis();

config.addConfigProvider(new ArgumentConfig(args))
.addConfigProvider(new EnvironmentVariableConfig("board."));
//this is added last in case the other config strategies have a different value for this
config.addConfigProvider(new PropertiesConfig(config.getString(BoardConfigKeys.BOARD_PROPERTIES)));

database = new BoardDatabase(logger, config);

Server server = new Server();
ChannelFuture channelFuture = server.start();

logger.info("Started Board Room server in " + (System.currentTimeMillis() - start) + "ms");

channelFuture.sync();

start = System.currentTimeMillis();

logger.info("Stopping Board Room server");

server.stop();

logger.info("Stopped Board Room server in " + (System.currentTimeMillis() - start) + "ms");
}

public static Logger getLogger() {
return logger;
}

public static Config getConfig() {
return config;
}

public static Database getDatabase() {
return database;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package net.stzups.board.backend;

import net.stzups.board.util.config.ConfigKey;
import net.stzups.board.util.config.OptionalConfigKey;
import net.stzups.board.util.config.RequiredConfigKey;

public class BoardBackendConfigKeys {
public static final ConfigKey<String> HTML_ROOT = new OptionalConfigKey<>("html.root", "html");
public static final ConfigKey<String> MIME_TYPES_FILE_PATH = new OptionalConfigKey<>("mimetypes.path", "mime.types");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package net.stzups.board.backend.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.ssl.SslContext;
import net.stzups.board.backend.BoardBackend;
import net.stzups.board.util.LogFactory;

/**
* Uses netty to create an HTTP/WebSocket server on the specified port
*/
public class Server {
private static final int HTTP_PORT = 80;
private static final int HTTPS_PORT = 443;

private EventLoopGroup bossGroup;
private EventLoopGroup workerGroup;

/**
* Initializes the server and binds to the specified port
*/
public ChannelFuture start() throws Exception {
SslContext sslContext;
int port;

port = HTTP_PORT;

bossGroup = new NioEventLoopGroup();
workerGroup = new NioEventLoopGroup();
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogFactory.getLogger("netty").getName(), LogLevel.DEBUG))
.childHandler(new ServerInitializer(null));
BoardBackend.getLogger().info("Binding to port " + port);
return serverBootstrap.bind(port).sync().channel().closeFuture();
}

/**
* Shuts down the server gracefully, then blocks until the server is shut down
*/
public void stop() {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package net.stzups.board.backend.server;

import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpContentCompressor;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.traffic.GlobalTrafficShapingHandler;
import io.netty.handler.traffic.TrafficCounter;
import net.stzups.board.backend.BoardBackend;
import net.stzups.board.backend.BoardBackendConfigKeys;
import net.stzups.board.backend.server.http.HttpServerHandler;
import net.stzups.board.util.LogFactory;

import java.io.File;
import java.util.concurrent.Executors;
import java.util.logging.Logger;

/**
* Creates pipeline to handle Websocket connections
* WebSocket connections should be made to the specified WebSocket path
* Connections not made to the WebSocket path go to ServerHandler
*/
public class ServerInitializer extends ChannelInitializer<SocketChannel> {
private GlobalTrafficShapingHandler globalTrafficShapingHandler = new GlobalTrafficShapingHandler(Executors.newSingleThreadScheduledExecutor(), 0, 0, 1000) {
@Override
protected void doAccounting(TrafficCounter counter) {
if (false) System.out.print("\rread " + (double) counter.lastReadThroughput() / 1000 * 8 + "kb/s, write " + (double) counter.lastWriteThroughput() / 1000 * 8 + "kb/s");
}
};

private Logger logger;
private SslContext sslContext;

ServerInitializer(SslContext sslContext) {
this.sslContext = sslContext;
}

@Override
protected void initChannel(SocketChannel socketChannel) {
logger = LogFactory.getLogger(socketChannel.remoteAddress().toString());
logger.info("Connection");
ChannelPipeline pipeline = socketChannel.pipeline();
pipeline
.addLast(new ChannelDuplexHandler() {
@Override
public void exceptionCaught(ChannelHandlerContext channelHandlerContext, Throwable throwable) {
logger.warning("Uncaught exception");
throwable.printStackTrace();
}
})
.addLast(globalTrafficShapingHandler);
if (sslContext != null) {
pipeline.addLast(sslContext.newHandler(socketChannel.alloc()));
}
pipeline
.addLast(new HttpServerCodec())
.addLast(new HttpObjectAggregator(65536))
.addLast(new HttpContentCompressor())
.addLast(new ChunkedWriteHandler())
.addLast(new HttpServerHandler(logger));
}
}
Loading

0 comments on commit d48ff34

Please sign in to comment.