diff --git a/application/src/main/java/org/togetherjava/tjbot/logging/FlaggedFilter.java b/application/src/main/java/org/togetherjava/tjbot/logging/FlaggedFilter.java
deleted file mode 100644
index 844c90a24f..0000000000
--- a/application/src/main/java/org/togetherjava/tjbot/logging/FlaggedFilter.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package org.togetherjava.tjbot.logging;
-
-import org.apache.logging.log4j.core.Core;
-import org.apache.logging.log4j.core.Filter;
-import org.apache.logging.log4j.core.LogEvent;
-import org.apache.logging.log4j.core.config.plugins.Plugin;
-import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
-import org.apache.logging.log4j.core.config.plugins.PluginFactory;
-import org.apache.logging.log4j.core.filter.AbstractFilter;
-
-/**
- * A custom Filter for Log4j2, which only lets an event pass through if a Logging Flag is set in the
- * environment. Intended to be used for local development for devs do not want to also run the
- * logviewer project. No errors in console or Log should appear, if the Flag is not set and the
- * logviewer is not running.
- */
-@Plugin(name = "FlaggedFilter", category = Core.CATEGORY_NAME, elementType = Filter.ELEMENT_TYPE)
-public class FlaggedFilter extends AbstractFilter {
-
- /**
- * The environment Variable that needs to bet set in order for this Filter to let events through
- */
- public static final String LOGGING_FLAG = "TJ_APPENDER";
-
- /**
- * Create a FlaggedFilter.
- *
- * @param onMatch The action to take on a match.
- * @param onMismatch The action to take on a mismatch.
- */
- public FlaggedFilter(Result onMatch, Result onMismatch) {
- super(onMatch, onMismatch);
- }
-
- /**
- * The actual filtering occurs here. If the Flag {@link #LOGGING_FLAG} is not set returns
- * {@link Result#DENY} so nothing goes through. If the Flag is set it returns
- * {@link Result#NEUTRAL} so other configured Filter still work.
- *
- * @param event The Event to log.
- * @return {@link Result#DENY} if the Flag is not set, else {@link Result#NEUTRAL}
- */
- @Override
- public Result filter(LogEvent event) {
- return isLoggingEnabled() ? Result.NEUTRAL : Result.DENY;
- }
-
- boolean isLoggingEnabled() {
- return System.getenv().containsKey(LOGGING_FLAG);
- }
-
- /**
- * Required by the Log4j2 - Plugin framework in order to create an instance of this Filter.
- *
- * @param onMatch The action to take on a match.
- * @param onMismatch The action to take on a mismatch.
- * @return The created FlaggedFilter.
- */
- @PluginFactory
- public static FlaggedFilter createFilter(
- @PluginAttribute(value = "onMatch", defaultString = "NEUTRAL") Result onMatch,
-
- @PluginAttribute(value = "onMismatch", defaultString = "DENY") Result onMismatch) {
- return new FlaggedFilter(onMatch, onMismatch);
- }
-}
diff --git a/application/src/main/resources/log4j2.xml b/application/src/main/resources/log4j2.xml
index 4f68a45e5f..3de21e9d65 100644
--- a/application/src/main/resources/log4j2.xml
+++ b/application/src/main/resources/log4j2.xml
@@ -13,13 +13,6 @@
-
-
-
-
-
-
-
@@ -29,7 +22,6 @@
-
diff --git a/application/src/test/java/org/togetherjava/tjbot/logging/FilterTest.java b/application/src/test/java/org/togetherjava/tjbot/logging/FilterTest.java
deleted file mode 100644
index cda30d60fa..0000000000
--- a/application/src/test/java/org/togetherjava/tjbot/logging/FilterTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package org.togetherjava.tjbot.logging;
-
-import org.apache.logging.log4j.core.Filter;
-import org.apache.logging.log4j.core.LogEvent;
-import org.apache.logging.log4j.core.impl.Log4jLogEvent;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mockito;
-
-final class FilterTest {
-
- private FlaggedFilter filter;
- private LogEvent event;
-
- @BeforeEach
- void setUp() {
- this.filter = FlaggedFilter.createFilter(Filter.Result.NEUTRAL, Filter.Result.DENY);
- this.event = Log4jLogEvent.newBuilder().build();
- }
-
- @Test
- void shouldPassFilter() {
- FlaggedFilter spy = Mockito.spy(this.filter);
- Mockito.when(spy.isLoggingEnabled()).thenReturn(true);
- Assertions.assertEquals(Filter.Result.NEUTRAL, spy.filter(this.event));
- }
-
- @Test
- void shouldNotPassFilter() {
- FlaggedFilter spy = Mockito.spy(this.filter);
- Mockito.when(spy.isLoggingEnabled()).thenReturn(false);
- Assertions.assertEquals(Filter.Result.DENY, spy.filter(this.event));
- }
-}
diff --git a/docker-compose.yml.example b/docker-compose.yml.example
index 74465edf74..362b1aa334 100644
--- a/docker-compose.yml.example
+++ b/docker-compose.yml.example
@@ -1,20 +1,27 @@
version: "3.9"
services:
- bot:
- image: togetherjava/tjbot:latest
+ tjbot-develop:
+ image: "togetherjava.duckdns.org:5001/togetherjava/tjbot:develop"
+ command: ["/home/bot/config/config.json"]
volumes:
- - "./application/config.json:/config.json"
- - "./application/logs/:/logs"
- links:
- - logs
- environment:
- - TJ_LOG_TARGET=logs
- logs:
- image: togetherjava/tjlogs:latest
+ - database:/home/bot/database
+ - ./config:/home/bot/config
+ restart: always
+ networks:
+ - develop-bot
+
+ tj-develop-website:
+ image: "togetherjava.duckdns.org:5001/togetherjava/website:develop"
ports:
- - "5050:5050"
- volumes:
- - "./logviewer/config.json:/logviewer/config.json"
- - "./application/logs:/application/logs"
- - "./logviewer/logs:/logviewer/logs"
- - "./logviewer/db:/logviewer/db"
+ - "127.0.0.1:5051:5051"
+ networks:
+ - develop-bot
+ restart: always
+
+volumes:
+ database:
+ name: "tj-bot-develop-database"
+
+networks:
+ develop-bot:
+ name: "develop-bot"
diff --git a/logviewer/build.gradle b/logviewer/build.gradle
deleted file mode 100644
index 2086804732..0000000000
--- a/logviewer/build.gradle
+++ /dev/null
@@ -1,103 +0,0 @@
-plugins {
- id "com.google.cloud.tools.jib" version "3.1.4"
- id "org.springframework.boot" version "2.6.1"
- id "io.spring.dependency-management" version "1.0.11.RELEASE"
- id "com.vaadin" version "21.0.2"
- id 'java'
- id 'database-settings'
-}
-
-defaultTasks("clean", "bootRun")
-
-repositories {
- mavenCentral()
- maven {
- url = uri("https://maven.vaadin.com/vaadin-addons")
- }
-}
-
-configurations {
- developmentOnly
- runtimeClasspath.extendsFrom(developmentOnly)
-}
-
-jooq {
- configurations {
- main {
- generationTool {
- generator {
- target {
- packageName = 'org.togetherjava.tjbot.db.generated'
- }
- }
- }
- }
- }
-}
-
-dependencies {
- implementation('org.apache.logging.log4j:log4j-api') {
- version {
- require '2.16.0'
- }
- because 'Log4Shell happened'
- }
- runtimeOnly('org.apache.logging.log4j:log4j-core') {
- version {
- require '2.16.0'
- }
- because 'Log4Shell happened'
- }
-
- runtimeOnly 'org.apache.logging.log4j:log4j-jul:2.16.0'
- runtimeOnly 'org.apache.logging.log4j:log4j-slf4j-impl:2.16.0'
-
-
- implementation(project(":database"))
- implementation 'org.jooq:jooq:3.15.3'
-
- implementation 'com.vaadin:vaadin-core:21.0.2'
- implementation('com.vaadin:vaadin-spring:18.0.0')
- implementation 'org.vaadin.artur:a-vaadin-helper:1.7.2'
- implementation 'org.vaadin.crudui:crudui:4.6.0'
- implementation 'com.vaadin.componentfactory:enhanced-dialog:21.0.0'
-
-
- implementation('org.springframework.boot:spring-boot-starter-web:2.6.1') {
- exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
- }
- implementation('org.springframework.boot:spring-boot-starter-security:2.6.1') {
- exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
- }
- implementation('org.springframework.boot:spring-boot-starter-oauth2-client:2.6.1') {
- exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
- }
-
- developmentOnly('org.springframework.boot:spring-boot-starter-actuator:2.6.1') {
- exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
- }
- developmentOnly('org.springframework.boot:spring-boot-devtools:2.6.1') {
- exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
- }
-}
-
-tasks.jib.dependsOn(tasks.vaadinBuildFrontend)
-jib {
- from.image = 'eclipse-temurin:17'
- to {
- image = 'togetherjava.duckdns.org:5001/togetherjava/tjlogs:' + System.getenv('BRANCH_NAME') ?: 'latest'
- auth {
- username = System.getenv('REGISTRY_USER') ?: ''
- password = System.getenv('REGISTRY_PASSWORD') ?: ''
- }
- }
- container {
- setPorts(["5050"].asList())
- setCreationTime(Instant.now().toString())
- }
-}
-
-vaadin {
- pnpmEnable = true
- productionMode = true
-}
diff --git a/logviewer/frontend/index.html b/logviewer/frontend/index.html
deleted file mode 100644
index 627308e8d4..0000000000
--- a/logviewer/frontend/index.html
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/logviewer/frontend/themes/logviewer/main-layout.css b/logviewer/frontend/themes/logviewer/main-layout.css
deleted file mode 100644
index 3477da5822..0000000000
--- a/logviewer/frontend/themes/logviewer/main-layout.css
+++ /dev/null
@@ -1,36 +0,0 @@
-[slot='drawer'] {
- background-image: linear-gradient(0deg, var(--lumo-shade-5pct), var(--lumo-shade-5pct));
-}
-
-[slot='drawer'] nav a {
- text-decoration: none;
- transition: color 140ms;
-}
-
-[slot='drawer'] nav a .la {
- margin-top: calc(var(--lumo-space-xs) * 0.5);
-}
-
-[slot='drawer'] nav a::before {
- border-radius: var(--lumo-border-radius);
- bottom: calc(var(--lumo-space-xs) * 0.5);
- content: '';
- left: 0;
- position: absolute;
- right: 0;
- top: calc(var(--lumo-space-xs) * 0.5);
- transition: background-color 140ms;
-}
-
-[slot='drawer'] nav a[highlight] {
- color: var(--lumo-primary-text-color);
-}
-
-[slot='drawer'] nav a[highlight]::before {
- background-color: var(--lumo-primary-color-10pct);
-}
-
-[slot='drawer'] footer vaadin-context-menu {
- align-items: center;
- display: flex;
-}
diff --git a/logviewer/frontend/themes/logviewer/styles.css b/logviewer/frontend/themes/logviewer/styles.css
deleted file mode 100644
index f7dfadb7ed..0000000000
--- a/logviewer/frontend/themes/logviewer/styles.css
+++ /dev/null
@@ -1,4 +0,0 @@
-/* Import your application global css files here or add the styles directly to this file */
-@import url('./main-layout.css');
-@import url('./views/logs-view.css');
-@import url('line-awesome/dist/line-awesome/css/line-awesome.min.css');
diff --git a/logviewer/frontend/themes/logviewer/theme.json b/logviewer/frontend/themes/logviewer/theme.json
deleted file mode 100644
index 7ccf9d1c46..0000000000
--- a/logviewer/frontend/themes/logviewer/theme.json
+++ /dev/null
@@ -1 +0,0 @@
-{"lumoImports":["typography","color","spacing","badge","utility"]}
diff --git a/logviewer/frontend/themes/logviewer/views/logs-view.css b/logviewer/frontend/themes/logviewer/views/logs-view.css
deleted file mode 100644
index aa8f478e95..0000000000
--- a/logviewer/frontend/themes/logviewer/views/logs-view.css
+++ /dev/null
@@ -1,39 +0,0 @@
-.logs-view {
- display: block;
- padding: 1em;
-}
-
-:root {
- --color-info: rgba(120, 107, 213, 0.5);
- --color-warn: rgba(170, 187, 97, 0.5);
- --color-error: rgba(255, 75, 75, 0.5);
- --color-debug: rgba(127, 255, 212, 0.5);
- --color-trace: rgba(58, 118, 58, 0.5);
-}
-
-p {
-
- line-height: normal;
- margin-top: 0.1em;
- margin-bottom: 0.1em;
-}
-
-.error {
- background-color: var(--color-error);
-}
-
-.warn {
- background-color: var(--color-warn);
-}
-
-.info {
- background-color: var(--color-info);
-}
-
-.debug {
- background-color: var(--color-debug);
-}
-
-.trace {
- background-color: var(--color-trace);
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/Application.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/Application.java
deleted file mode 100644
index b8661bd91d..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/Application.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package org.togetherjava.tjbot.logwatcher;
-
-import com.vaadin.flow.component.dependency.NpmPackage;
-import com.vaadin.flow.component.page.AppShellConfigurator;
-import com.vaadin.flow.component.page.Push;
-import com.vaadin.flow.server.PWA;
-import com.vaadin.flow.theme.Theme;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration;
-import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
-import org.togetherjava.tjbot.logwatcher.config.Config;
-import org.togetherjava.tjbot.logwatcher.logs.LogREST;
-import org.togetherjava.tjbot.logwatcher.oauth.OAuth2LoginConfig;
-import org.vaadin.artur.helpers.LaunchUtil;
-
-/**
- * This is a small Spring-Vaadin Webserver, which main purpose is to show Log-Event's generated from
- * the Bot.
- *
- * You can see the Views you can see in your Browser at {@link org.togetherjava.logwatcher.views}
- *
- * Log-Event's are captured by the REST-API at {@link LogREST}
- *
- * Security/OAuth2 Config at {@link OAuth2LoginConfig}
- *
- * And the initial Config at {@link Config}
- */
-@SpringBootApplication(exclude = {R2dbcAutoConfiguration.class})
-@Theme(value = "logviewer")
-@PWA(name = "LogViewer", shortName = "Logs", offlineResources = {"images/logo.png"})
-@NpmPackage(value = "line-awesome", version = "1.3.0")
-@Push
-public class Application extends SpringBootServletInitializer implements AppShellConfigurator {
-
- private static final Logger applicationLogger = LoggerFactory.getLogger(Application.class);
-
- public static void main(String[] args) {
- if (args.length > 1) {
- applicationLogger
- .error("Usage: Provide a single Argument, containing the Path to the Config-File");
- System.exit(1);
- }
-
- Config.init(args.length == 1 ? args[0] : "./logviewer/config.json");
- LaunchUtil.launchBrowserInDevelopmentMode(SpringApplication.run(Application.class, args));
- }
-
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/DatabaseProvider.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/DatabaseProvider.java
deleted file mode 100644
index 914687850d..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/DatabaseProvider.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.togetherjava.tjbot.logwatcher;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.FatalBeanException;
-import org.springframework.beans.factory.config.BeanDefinition;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Scope;
-import org.togetherjava.tjbot.logwatcher.config.Config;
-import org.togetherjava.tjbot.db.Database;
-
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.sql.SQLException;
-
-@Configuration
-@Scope(BeanDefinition.SCOPE_SINGLETON)
-public class DatabaseProvider {
-
- private final Database db;
- private final Config config;
-
- private static final Logger logger = LoggerFactory.getLogger(DatabaseProvider.class);
-
- public DatabaseProvider(final Config config) {
- this.config = config;
- this.db = createDB();
- }
-
- @SuppressWarnings({"java:S2139"}) // At this point there is nothing we can do about a
- // SQLException
- private Database createDB() {
- final Path dbPath = getDBPath();
-
- try {
- return new Database("jdbc:sqlite:%s".formatted(dbPath.toAbsolutePath()));
- } catch (final SQLException e) {
- logger.error("Exception while creating Database.", e);
- throw new FatalBeanException("Could not create Database.", e);
- }
- }
-
- private Path getDBPath() {
- final Path dbPath = Path.of(this.config.getDatabasePath());
-
- try {
- Files.createDirectories(dbPath.getParent());
- } catch (final IOException e) {
- logger.error("Exception while creating Database-Path.", e);
- }
-
- return dbPath;
- }
-
-
- @Bean
- public Database getDb() {
- return this.db;
- }
-
-
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/accesscontrol/AllowedRoles.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/accesscontrol/AllowedRoles.java
deleted file mode 100644
index 4b3ce22ece..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/accesscontrol/AllowedRoles.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.togetherjava.tjbot.logwatcher.accesscontrol;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import static java.lang.annotation.ElementType.TYPE;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-
-/**
- * Annotation for handling Access Control on Views
- */
-@Retention(RUNTIME)
-@Target({TYPE})
-public @interface AllowedRoles {
-
-
- /**
- * Roles to permit access to the View {@link Role}
- */
- Role[] roles();
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/accesscontrol/Role.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/accesscontrol/Role.java
deleted file mode 100644
index 364474fbf3..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/accesscontrol/Role.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package org.togetherjava.tjbot.logwatcher.accesscontrol;
-
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.Set;
-
-/**
- * Basic Roles for Access Control on Views
- */
-public enum Role {
- /**
- * Role for when Stuff goes wrong
- */
- UNKNOWN(0, "unknown"),
-
- /**
- * Base Role
- */
- USER(1, "user"),
-
- /**
- * Role for Views that should require more permissions
- */
- ADMIN(2, "admin");
-
- private final int id;
- private final String roleName;
-
- Role(int id, String roleName) {
- this.id = id;
- this.roleName = roleName;
- }
-
- public int getId() {
- return id;
- }
-
- public String getRoleName() {
- return roleName;
- }
-
- public static Role forID(final int id) {
- return Arrays.stream(values())
- .filter(r -> r.id == id)
- .findAny()
- .orElseThrow(() -> new IllegalArgumentException("Unknown RoleID: %d".formatted(id)));
- }
-
- public static Set getDisplayableRoles() {
- return EnumSet.of(USER, ADMIN);
- }
-
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/config/Config.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/config/Config.java
deleted file mode 100644
index f19cad897e..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/config/Config.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package org.togetherjava.tjbot.logwatcher.config;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.springframework.context.annotation.Configuration;
-
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.nio.file.Path;
-import java.util.Objects;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * Basic Class for accumulating Information which is required to start this application
- */
-@Configuration
-public class Config {
-
- private static final AtomicReference CONFIG_PATH = new AtomicReference<>();
-
- public static void init(final String pathToConfig) {
- if (!CONFIG_PATH.compareAndSet(null, pathToConfig)) {
- throw new IllegalStateException(
- "Config Path already set to %s".formatted(CONFIG_PATH.get()));
- }
- }
-
-
- /**
- * Client-Name of the OAuth2-Application
- */
- private final String clientName;
-
- /**
- * Client-ID of the OAuth2-Application
- */
- private final String clientId;
-
- /**
- * Client-Secret of the OAuth2-Application
- */
- private final String clientSecret;
-
- /**
- * Discord-Username of the User to add as 1. User
- */
- private final String rootUserName;
-
- /**
- * Discord-ID of the User to add as 1. User
- */
- private final String rootDiscordID;
-
- /**
- * Path of the Log directory
- */
- private final String logPath;
-
- /**
- * Redirect Path for OAuth2
- */
- private final String redirectPath;
-
- /**
- * Path for this Database
- */
- private final String databasePath;
-
- public Config(final ObjectMapper mapper) {
- final JsonNode jsonNode = getJsonNode(mapper);
-
- this.clientName = jsonNode.get("clientName").asText();
- this.clientId = jsonNode.get("clientId").asText();
- this.clientSecret = jsonNode.get("clientSecret").asText();
- this.rootUserName = jsonNode.get("rootUserName").asText();
- this.rootDiscordID = jsonNode.get("rootDiscordID").asText();
- this.logPath = jsonNode.get("logPath").asText();
- this.redirectPath = jsonNode.get("redirectPath").asText();
- this.databasePath = jsonNode.get("databasePath").asText();
- }
-
- private JsonNode getJsonNode(final ObjectMapper mapper) {
- final String pathToConfig = Objects.requireNonNull(CONFIG_PATH.get(), "Path not Set");
- try {
- return mapper.readTree(Path.of(pathToConfig).toFile());
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public String getRedirectPath() {
- return redirectPath;
- }
-
- public String getLogPath() {
- return logPath;
- }
-
- public String getRootUserName() {
- return rootUserName;
- }
-
- public String getRootDiscordID() {
- return rootDiscordID;
- }
-
- public String getClientName() {
- return clientName;
- }
-
- public String getClientId() {
- return clientId;
- }
-
- public String getClientSecret() {
- return clientSecret;
- }
-
- public String getDatabasePath() {
- return this.databasePath;
- }
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/constants/LogEventsConstants.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/constants/LogEventsConstants.java
deleted file mode 100644
index 45e46e4730..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/constants/LogEventsConstants.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package org.togetherjava.tjbot.logwatcher.constants;
-
-/**
- * Constant Class for Logevents
- */
-public final class LogEventsConstants {
-
- public static final String FIELD_INSTANT = "time";
- public static final String FIELD_END_OF_BATCH = "endOfbatch";
- public static final String FIELD_LOGGER_NAME = "loggername";
- public static final String FIELD_LOGGER_LEVEL = "level";
- public static final String FIELD_LOGGER_FQCN = "loggerfqcn";
- public static final String FIELD_MESSAGE = "message";
- public static final String FIELD_THREAD = "thread";
- public static final String FIELD_THREAD_ID = "threadid";
- public static final String FIELD_THREAD_PRIORITY = "threadpriority";
-
-
-
- /**
- * Contestants class, nothing to instantiate
- */
- private LogEventsConstants() {}
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/constants/UserConstants.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/constants/UserConstants.java
deleted file mode 100644
index 0532c11229..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/constants/UserConstants.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.togetherjava.tjbot.logwatcher.constants;
-
-/**
- * Gathers all static Values regarding Users
- */
-public final class UserConstants {
-
- public static final String FIELD_USERNAME = "username";
- public static final String FIELD_DISCORD_ID = "discordid";
-
-
- private UserConstants() {}
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/entities/InstantWrapper.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/entities/InstantWrapper.java
deleted file mode 100644
index 4754ad9b32..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/entities/InstantWrapper.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package org.togetherjava.tjbot.logwatcher.entities;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-import java.text.SimpleDateFormat;
-import java.time.Instant;
-import java.util.Date;
-
-public class InstantWrapper {
-
- private long epochSecond;
- private long nanoOfSecond;
-
- /**
- * @param epochSecond
- * @param nanoOfSecond
- */
- @JsonCreator
- public InstantWrapper(@JsonProperty("epochSecond") long epochSecond,
- @JsonProperty("nanoOfSecond") long nanoOfSecond) {
- super();
- this.epochSecond = epochSecond;
- this.nanoOfSecond = nanoOfSecond;
- }
-
- public long getEpochSecond() {
- return epochSecond;
- }
-
- public void setEpochSecond(long epochSecond) {
- this.epochSecond = epochSecond;
- }
-
- public long getNanoOfSecond() {
- return nanoOfSecond;
- }
-
- public void setNanoOfSecond(long nanoOfSecond) {
- this.nanoOfSecond = nanoOfSecond;
- }
-
- @Override
- public String toString() {
- final var instant = toInstant();
-
- return new SimpleDateFormat("yyy-MM-dd HH:mm:ss.SSS").format(Date.from(instant));
- }
-
- public Instant toInstant() {
- return Instant.ofEpochSecond(this.epochSecond, this.nanoOfSecond);
- }
-
- @Override
- public boolean equals(Object o) {
- if (!(o instanceof InstantWrapper other)) {
- return false;
- }
-
- return epochSecond == other.epochSecond && nanoOfSecond != other.nanoOfSecond;
- }
-
- @Override
- public int hashCode() {
- int result = (int) (epochSecond ^ (epochSecond >>> 32));
- result = 31 * result + (int) (nanoOfSecond ^ (nanoOfSecond >>> 32));
- return result;
- }
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/entities/LogEvent.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/entities/LogEvent.java
deleted file mode 100644
index fcf80c671d..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/entities/LogEvent.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package org.togetherjava.tjbot.logwatcher.entities;
-
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
-
-import java.time.Instant;
-
-
-@JsonInclude(JsonInclude.Include.NON_NULL)
-public class LogEvent {
-
- private Instant instant;
-
- private String thread;
-
- private String level;
-
- private String loggerName;
-
- private String message;
-
- private Boolean endOfBatch;
-
- private String loggerFqcn;
-
- private Integer threadId;
-
- private Integer threadPriority;
-
- @JsonCreator
- public LogEvent(@JsonProperty("instant") InstantWrapper wrapper,
- @JsonProperty("thread") String thread, @JsonProperty("level") String level,
- @JsonProperty("loggerName") String loggerName, @JsonProperty("message") String message,
- @JsonProperty("endOfBatch") Boolean endOfBatch,
- @JsonProperty("loggerFqcn") String loggerFqcn,
- @JsonProperty("threadId") Integer threadId,
- @JsonProperty("threadPriority") Integer threadPriority) {
- this.instant = wrapper.toInstant();
- this.thread = thread;
- this.level = level;
- this.loggerName = loggerName;
- this.message = message;
- this.endOfBatch = endOfBatch;
- this.loggerFqcn = loggerFqcn;
- this.threadId = threadId;
- this.threadPriority = threadPriority;
- }
-
-
- public Instant getInstant() {
- return instant;
- }
-
- public void setInstant(Instant instant) {
- this.instant = instant;
- }
-
- public String getThread() {
- return thread;
- }
-
- public void setThread(String thread) {
- this.thread = thread;
- }
-
- public String getLevel() {
- return level;
- }
-
- public void setLevel(String level) {
- this.level = level;
- }
-
- public String getLoggerName() {
- return loggerName;
- }
-
- public void setLoggerName(String loggerName) {
- this.loggerName = loggerName;
- }
-
- public String getMessage() {
- return message;
- }
-
- public void setMessage(String message) {
- this.message = message;
- }
-
- public Boolean getEndOfBatch() {
- return endOfBatch;
- }
-
- public void setEndOfBatch(Boolean endOfBatch) {
- this.endOfBatch = endOfBatch;
- }
-
- public String getLoggerFqcn() {
- return loggerFqcn;
- }
-
- public void setLoggerFqcn(String loggerFqcn) {
- this.loggerFqcn = loggerFqcn;
- }
-
- public Integer getThreadId() {
- return threadId;
- }
-
- public void setThreadId(Integer threadId) {
- this.threadId = threadId;
- }
-
- public Integer getThreadPriority() {
- return threadPriority;
- }
-
- public void setThreadPriority(Integer threadPriority) {
- this.threadPriority = threadPriority;
- }
-
- @Override
- public String toString() {
- return "LogDTO{" + "instant=" + instant + ", thread='" + thread + '\'' + ", level='" + level
- + '\'' + ", loggerName='" + loggerName + '\'' + ", message='" + message + '\''
- + ", endOfBatch=" + endOfBatch + ", loggerFqcn='" + loggerFqcn + '\''
- + ", threadId=" + threadId + ", threadPriority=" + threadPriority + '}';
- }
-
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/entities/UserWrapper.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/entities/UserWrapper.java
deleted file mode 100644
index 8bd55eefda..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/entities/UserWrapper.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.togetherjava.tjbot.logwatcher.entities;
-
-import org.togetherjava.tjbot.logwatcher.accesscontrol.Role;
-
-import java.io.Serial;
-import java.io.Serializable;
-import java.util.Collections;
-import java.util.Objects;
-import java.util.Set;
-
-public final class UserWrapper implements Serializable {
- @Serial
- private static final long serialVersionUID = -3701246411434315431L;
-
- private long discordID;
- private String userName;
- private Set roles = Collections.emptySet();
-
- public UserWrapper() {}
-
- public UserWrapper(long discordID, String userName, Set roles) {
- this.discordID = discordID;
- this.userName = userName;
- this.roles = roles;
- }
-
- public void setDiscordID(long discordID) {
- this.discordID = discordID;
- }
-
- public void setUserName(String userName) {
- this.userName = userName;
- }
-
- public void setRoles(Set roles) {
- this.roles = roles;
- }
-
- public long getDiscordID() {
- return discordID;
- }
-
- public String getUserName() {
- return userName;
- }
-
- public Set getRoles() {
- return roles;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof UserWrapper other)) {
- return true;
- }
- return this.discordID == other.discordID && Objects.equals(this.userName, other.userName)
- && Objects.equals(this.roles, other.roles);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(discordID, userName, roles);
- }
-
- @Override
- public String toString() {
- return "UserDTO[" + "discordID=" + discordID + ", " + "userName=" + userName + ", "
- + "roles=" + roles + ']';
- }
-
-
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/logs/LogREST.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/logs/LogREST.java
deleted file mode 100644
index c1d2103a6f..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/logs/LogREST.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package org.togetherjava.tjbot.logwatcher.logs;
-
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RestController;
-import org.togetherjava.tjbot.logwatcher.entities.LogEvent;
-import org.togetherjava.tjbot.logwatcher.watcher.StreamWatcher;
-import org.togetherjava.tjbot.db.generated.tables.pojos.Logevents;
-
-@RestController
-public class LogREST {
-
- private final LogRepository logs;
-
- public LogREST(final LogRepository logs) {
- this.logs = logs;
- }
-
- @PostMapping(path = "/rest/api/logs", consumes = "application/json")
- public ResponseEntity logEvent(@RequestBody final LogEvent body) {
- this.logs.save(mapToLogevents(body));
- StreamWatcher.notifyOfEvent();
- return ResponseEntity.ok().build();
- }
-
- private Logevents mapToLogevents(final LogEvent body) {
- return new Logevents(Integer.MIN_VALUE, body.getInstant(), body.getThread(),
- body.getLevel(), body.getLoggerName(), body.getMessage(), body.getEndOfBatch(),
- body.getLoggerFqcn(), body.getThreadId(), body.getThreadPriority());
- }
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/logs/LogRepository.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/logs/LogRepository.java
deleted file mode 100644
index be2ae85de5..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/logs/LogRepository.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package org.togetherjava.tjbot.logwatcher.logs;
-
-import org.togetherjava.tjbot.db.generated.tables.pojos.Logevents;
-
-import java.util.Collection;
-import java.util.List;
-
-public interface LogRepository {
-
- /**
- * Saves the given event to the DB, does not update or merge
- *
- * @param event Event to Insert
- */
- void save(Logevents event);
-
- /**
- * Fetches all Events from the DB
- *
- * @return List of LogEvents
- */
- List findAll();
-
- /**
- * Fetches all Events, which LogLevel matches the given Collection, from the DB
- *
- * @return List of LogEvents
- */
- List findWithLevelMatching(Collection logLevels);
-
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/logs/LogRepositoryImpl.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/logs/LogRepositoryImpl.java
deleted file mode 100644
index 865b3efd72..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/logs/LogRepositoryImpl.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package org.togetherjava.tjbot.logwatcher.logs;
-
-import org.springframework.stereotype.Repository;
-import org.togetherjava.tjbot.db.Database;
-import org.togetherjava.tjbot.db.generated.tables.pojos.Logevents;
-import org.togetherjava.tjbot.db.generated.tables.records.LogeventsRecord;
-
-import java.util.Collection;
-import java.util.List;
-
-import static org.togetherjava.tjbot.db.generated.tables.Logevents.LOGEVENTS;
-
-@Repository
-public class LogRepositoryImpl implements LogRepository {
-
- private final Database db;
-
- public LogRepositoryImpl(final Database db) {
- this.db = db;
- }
-
-
- @Override
- public void save(Logevents event) {
- this.db.writeTransaction(ctx -> {
- LogeventsRecord toInsert = ctx.newRecord(LOGEVENTS)
- .setEndofbatch(event.getEndofbatch())
- .setLevel(event.getLevel())
- .setLoggername(event.getLoggername())
- .setLoggerfqcn(event.getLoggerfqcn())
- .setMessage(event.getMessage())
- .setTime(event.getTime())
- .setThread(event.getThread())
- .setThreadid(event.getThreadid())
- .setThreadpriority(event.getThreadpriority());
-
- if (event.getId() != Integer.MIN_VALUE) {
- toInsert.setId(event.getId());
- }
-
- // No merge or Update here, Logs are not supposed to be updated
- toInsert.insert();
- });
- }
-
- @Override
- public List findAll() {
- return this.db.read(ctx -> ctx.selectFrom(LOGEVENTS).fetch(this::recordToPojo));
- }
-
-
- @Override
- public List findWithLevelMatching(Collection logLevels) {
- return this.db.read(ctx -> ctx.selectFrom(LOGEVENTS)
- .where(LOGEVENTS.LEVEL.in(logLevels))
- .fetch(this::recordToPojo));
- }
-
- private Logevents recordToPojo(final LogeventsRecord logRecord) {
- return new Logevents(logRecord.getId(), logRecord.getTime(), logRecord.getThread(),
- logRecord.getLevel(), logRecord.getLoggername(), logRecord.getMessage(),
- logRecord.getEndofbatch(), logRecord.getLoggerfqcn(), logRecord.getThreadid(),
- logRecord.getThreadpriority());
- }
-
-
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/oauth/OAuth2LoginConfig.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/oauth/OAuth2LoginConfig.java
deleted file mode 100644
index eb9bfc92a7..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/oauth/OAuth2LoginConfig.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package org.togetherjava.tjbot.logwatcher.oauth;
-
-import com.vaadin.flow.spring.security.VaadinWebSecurityConfigurerAdapter;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.security.config.annotation.web.builders.HttpSecurity;
-import org.springframework.security.config.annotation.web.builders.WebSecurity;
-import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
-import org.springframework.security.oauth2.client.InMemoryOAuth2AuthorizedClientService;
-import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
-import org.springframework.security.oauth2.client.registration.ClientRegistration;
-import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
-import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
-import org.springframework.security.oauth2.client.web.AuthenticatedPrincipalOAuth2AuthorizedClientRepository;
-import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
-import org.springframework.security.oauth2.core.AuthorizationGrantType;
-import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
-import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
-import org.togetherjava.tjbot.logwatcher.config.Config;
-
-/**
- * Configures Spring Security so that we use Discord-OAuth2 as the identity provider
- */
-@Configuration
-public class OAuth2LoginConfig {
-
- @Bean
- public ClientRegistrationRepository clientRegistrationRepository(Config config) {
- return new InMemoryClientRegistrationRepository(googleClientRegistration(config));
- }
-
- @Bean
- public OAuth2AuthorizedClientService authorizedClientService(
- ClientRegistrationRepository clientRegistrationRepository) {
- return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository);
- }
-
- @Bean
- public OAuth2AuthorizedClientRepository authorizedClientRepository(
- OAuth2AuthorizedClientService authorizedClientService) {
- return new AuthenticatedPrincipalOAuth2AuthorizedClientRepository(authorizedClientService);
- }
-
- /**
- * This is where we actually configure the Security-API to talk to Discord
- *
- * @return The ClientRegistration for Discord
- */
- private ClientRegistration googleClientRegistration(Config config) {
- return ClientRegistration.withRegistrationId("Discord")
- .clientName(config.getClientName())
- .clientId(config.getClientId())
- .clientSecret(config.getClientSecret())
- .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST)
- .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
- .scope("identify")
- .authorizationUri("https://discord.com/api/oauth2/authorize")
- .userInfoUri("https://discordapp.com/api/users/@me")
- .userNameAttributeName("username")
- .tokenUri("https://discordapp.com/api/oauth2/token")
- .redirectUri(config.getRedirectPath())
- .build();
- }
-
- /**
- * Configures the Security-API which path's should be protected and generally what to do
- */
- @EnableWebSecurity
- public static class OAuth2LoginSecurityConfig extends VaadinWebSecurityConfigurerAdapter {
-
- @Override
- public void configure(WebSecurity web) throws Exception {
- super.configure(web);
- web.ignoring().antMatchers("/rest/api/**");
- }
-
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- http.authorizeRequests().antMatchers("/rest/api/**").anonymous();
- http.oauth2Login();
- http.logout()
- .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
- .deleteCookies("JSESSIONID")
- .invalidateHttpSession(true)
- .clearAuthentication(true);
-
- // Enables Vaadin to load Server Resources
- super.configure(http);
- }
- }
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/users/AuthenticatedUser.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/users/AuthenticatedUser.java
deleted file mode 100644
index eaf128785d..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/users/AuthenticatedUser.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package org.togetherjava.tjbot.logwatcher.users;
-
-import com.vaadin.flow.component.UI;
-import com.vaadin.flow.server.VaadinServletRequest;
-import org.springframework.security.core.context.SecurityContext;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.oauth2.core.user.OAuth2User;
-import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
-import org.springframework.stereotype.Component;
-import org.togetherjava.tjbot.logwatcher.accesscontrol.Role;
-import org.togetherjava.tjbot.db.generated.tables.pojos.Users;
-
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-
-/**
- * Wrapper for accessing the current User
- */
-@Component
-public class AuthenticatedUser {
-
- private final UserRepository userRepository;
-
- public AuthenticatedUser(UserRepository userRepository) {
- this.userRepository = userRepository;
- }
-
- /**
- * Check's if you could register the current User
- *
- * @return true, if the Current user is Authenticated
- */
- public boolean canRegister() {
- return getAuthenticatedUser().isPresent();
- }
-
- /**
- * Check's if the current User is already registered
- *
- * @return true, if the User is already in the repository
- */
- public boolean isRegistered() {
- if (!canRegister()) {
- return false;
- }
-
- return getAuthenticatedUser().map(this::extractID)
- .map(userRepository::findByDiscordID)
- .isPresent();
- }
-
- /**
- * Attempts to register the current User, if he is not yet registered
- */
- public void register() {
- if (!canRegister() || isRegistered()) {
- throw new IllegalStateException("Can not register an already registered User");
- }
-
- getAuthenticatedUser().map(this::toUser).ifPresent(userRepository::save);
- }
-
- /**
- * Get's the current User Object from the repository
- *
- * @return The Optional User, should in most cases not be empty
- */
- public Users get() {
- return getAuthenticatedUser().map(this::extractID)
- .map(userRepository::findByDiscordID)
- .orElseThrow(() -> new IllegalArgumentException("No authenticated User present."));
- }
-
- public Set getRoles() {
- return this.userRepository.fetchRolesForUser(get());
- }
-
- /**
- * Performs a logout on the current User
- */
- public void logout() {
- UI.getCurrent().getPage().setLocation("/");
- SecurityContextLogoutHandler logoutHandler = new SecurityContextLogoutHandler();
- logoutHandler.logout(VaadinServletRequest.getCurrent().getHttpServletRequest(), null, null);
- }
-
- /**
- * Extracts the principal from the current SessionContext of the user
- *
- * @return The Optional Principal of the current User
- */
- private Optional getAuthenticatedUser() {
- SecurityContext context = SecurityContextHolder.getContext();
- Object principal = context.getAuthentication().getPrincipal();
-
- return principal instanceof OAuth2User ? Optional.of(principal).map(OAuth2User.class::cast)
- : Optional.empty();
- }
-
- /**
- * Maps the principal to the User object
- *
- * @param oAuth2User Principal to map
- * @return User-Object derived from the Principal
- */
- private Users toUser(OAuth2User oAuth2User) {
- return new Users(extractID(oAuth2User), oAuth2User.getName());
- }
-
- /**
- * Extracts the discord-ID from the Principal
- *
- * @param oAuth2User Principal with the ID
- * @return Discord-ID from the given Principal
- */
- private long extractID(OAuth2User oAuth2User) {
- final String id = oAuth2User.getAttribute("id");
- return Long.parseLong(
- Objects.requireNonNull(id, "ID from OAuth-User is null, this should never happen"));
- }
-
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/users/UserDetailsServiceImpl.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/users/UserDetailsServiceImpl.java
deleted file mode 100644
index ad8a7e6b8d..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/users/UserDetailsServiceImpl.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package org.togetherjava.tjbot.logwatcher.users;
-
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.authority.SimpleGrantedAuthority;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.UserDetailsService;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
-import org.springframework.stereotype.Service;
-import org.togetherjava.tjbot.logwatcher.accesscontrol.Role;
-import org.togetherjava.tjbot.logwatcher.config.Config;
-import org.togetherjava.tjbot.db.generated.tables.pojos.Users;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * Service to load a spring UserDetail-Object from the userRepository, currently only used for
- * db-initialisation
- */
-@Service
-public class UserDetailsServiceImpl implements UserDetailsService {
-
- private final UserRepository userRepository;
-
- public UserDetailsServiceImpl(UserRepository userRepository, Config config) {
- this.userRepository = userRepository;
-
- if (this.userRepository.count() == 0) {
- final Users defaultUser =
- new Users(Long.parseLong(config.getRootDiscordID()), config.getRootUserName());
-
- this.userRepository.save(defaultUser);
- this.userRepository.saveRolesForUser(defaultUser, Set.of(Role.ADMIN, Role.USER));
- }
- }
-
- private List getAuthorities(Users user) {
- return this.userRepository.fetchRolesForUser(user)
- .stream()
- .map(Role::getRoleName)
- .map(name -> "ROLE_" + name)
- .map(SimpleGrantedAuthority::new)
- .map(GrantedAuthority.class::cast)
- .toList();
-
- }
-
- /**
- * Loads the user from the userRepository and maps it to the Spring-Object UserDetails
- *
- * @param username Username of the User to Load
- * @return The UserDetail-Object that is associated with the discordID, or else throws an
- * {@link UsernameNotFoundException}
- */
- @Override
- public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
- Users user = userRepository.findByUsername(username);
- if (user == null) {
- throw new UsernameNotFoundException("No user present with username: " + username);
- } else {
- return new org.springframework.security.core.userdetails.User(user.getUsername(), null,
- getAuthorities(user));
- }
- }
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/users/UserRepository.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/users/UserRepository.java
deleted file mode 100644
index de78e71d8a..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/users/UserRepository.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.togetherjava.tjbot.logwatcher.users;
-
-import org.togetherjava.tjbot.logwatcher.accesscontrol.Role;
-import org.togetherjava.tjbot.db.generated.tables.pojos.Users;
-
-import java.util.List;
-import java.util.Set;
-
-/**
- * Basic JPA-Repository for loading Users from the DB
- */
-public interface UserRepository {
-
- /**
- * Load's the User from the DB, that matches the discordID
- *
- * @param discordID Discord-ID of the User
- * @return User-Object of the user where the discordID matches, else null
- */
- Users findByDiscordID(long discordID);
-
- /**
- * Load's the User from the DB, that matches the username
- *
- * @param username Username of the User to load
- * @return User-Object of the user where the username matches, else null
- */
- Users findByUsername(final String username);
-
- /**
- * Fetches all saved User
- *
- * @return List of Users from the DB, never null
- */
- List findAll();
-
- /**
- * Counts the amount of Users saved in the DB
- *
- * @return Count of Users in the db >=0
- */
- int count();
-
- /**
- * Merges the given user in the DB
- *
- * @param user User to Save in the DB
- */
- void save(Users user);
-
- /**
- * Removes this User and all referencing Entities
- */
- void delete(Users user);
-
- /**
- * Fetches the Roles the User has, see {@link Role}
- *
- * @param user User to fetch the Roles for
- * @return Set of Roles, never null
- */
- Set fetchRolesForUser(Users user);
-
- /**
- * Updates/Saves the Roles for the User
- *
- * @param user User to update the Role's
- * @param roles All Roles the User should have
- */
- void saveRolesForUser(Users user, Set roles);
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/users/UserRepositoryImpl.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/users/UserRepositoryImpl.java
deleted file mode 100644
index 792a4c9984..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/users/UserRepositoryImpl.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package org.togetherjava.tjbot.logwatcher.users;
-
-import org.springframework.stereotype.Component;
-import org.togetherjava.tjbot.logwatcher.accesscontrol.Role;
-import org.togetherjava.tjbot.db.Database;
-import org.togetherjava.tjbot.db.generated.tables.Userroles;
-import org.togetherjava.tjbot.db.generated.tables.pojos.Users;
-import org.togetherjava.tjbot.db.generated.tables.records.UserrolesRecord;
-import org.togetherjava.tjbot.db.generated.tables.records.UsersRecord;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import static org.togetherjava.tjbot.db.generated.tables.Users.USERS;
-
-@Component
-public class UserRepositoryImpl implements UserRepository {
-
- private final Database db;
-
- public UserRepositoryImpl(Database db) {
- this.db = db;
- }
-
- @Override
- public Users findByDiscordID(long discordID) {
- return this.db.readTransaction(ctx -> ctx.selectFrom(USERS)
- .where(USERS.DISCORDID.eq(discordID))
- .fetchOne(this::recordToRole));
- }
-
- @Override
- public Users findByUsername(String username) {
- return this.db.readTransaction(ctx -> ctx.selectFrom(USERS)
- .where(USERS.USERNAME.eq(username))
- .fetchOne(this::recordToRole));
- }
-
- @Override
- public List findAll() {
- return this.db.readTransaction(ctx -> ctx.selectFrom(USERS).fetch(this::recordToRole));
- }
-
- @Override
- public int count() {
- return this.db.readTransaction(ctx -> ctx.fetchCount(USERS));
- }
-
- @Override
- public void save(Users user) {
- this.db.writeTransaction(ctx -> ctx.newRecord(USERS)
- .setDiscordid(user.getDiscordid())
- .setUsername(user.getUsername())
- .merge());
- }
-
- @Override
- public void delete(Users user) {
- this.db.writeTransaction(ctx -> ctx.deleteFrom(USERS)
- .where(USERS.DISCORDID.eq(user.getDiscordid()))
- .execute());
- }
-
- @Override
- public Set fetchRolesForUser(Users user) {
- return new HashSet<>(this.db.readTransaction(ctx -> ctx.selectFrom(Userroles.USERROLES)
- .where(Userroles.USERROLES.USERID.eq(user.getDiscordid()))
- .fetch(this::recordToRole)));
- }
-
- @Override
- public void saveRolesForUser(Users user, Set roles) {
- this.db.writeTransaction(ctx -> {
- ctx.deleteFrom(Userroles.USERROLES)
- .where(Userroles.USERROLES.USERID.eq(user.getDiscordid()))
- .execute();
-
- for (final Role role : roles) {
- ctx.newRecord(Userroles.USERROLES)
- .setRoleid(role.getId())
- .setUserid(user.getDiscordid())
- .insert();
- }
- });
- }
-
- private Users recordToRole(UsersRecord usersRecord) {
- return new Users(usersRecord.getDiscordid(), usersRecord.getUsername());
- }
-
- private Role recordToRole(UserrolesRecord rolesRecord) {
- return Role.forID(rolesRecord.getRoleid());
- }
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/util/LogReader.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/util/LogReader.java
deleted file mode 100644
index 9aadc236af..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/util/LogReader.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package org.togetherjava.tjbot.logwatcher.util;
-
-import org.springframework.stereotype.Component;
-import org.togetherjava.tjbot.logwatcher.config.Config;
-
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.List;
-import java.util.stream.Stream;
-
-@Component
-public final class LogReader {
-
- private final Path logPath;
-
- public LogReader(Config config) {
- this.logPath = Path.of(config.getLogPath());
- }
-
- /**
- * Returns all log Files in the configured Path {@link Config#logPath}
- *
- * @return Names of the Logfiles
- */
- public List getLogs() {
- try (final Stream stream = Files.list(this.logPath)) {
- return stream.filter(Files::isRegularFile)
- .filter(s -> s.toString().endsWith(".log") || s.toString().endsWith(".log.gz"))
- .toList();
- } catch (final IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- /**
- * Read's the content of the given Logfile in the configured Logging path
- *
- * @param log Name of the Logfile
- * @return The Content of the Log
- */
- public List readLog(final Path log) {
- try {
- return Files.readAllLines(log);
- } catch (final IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/util/LogUtils.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/util/LogUtils.java
deleted file mode 100644
index 719fb20223..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/util/LogUtils.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package org.togetherjava.tjbot.logwatcher.util;
-
-import org.togetherjava.tjbot.db.generated.tables.pojos.Logevents;
-
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.Locale;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-public final class LogUtils {
-
- /**
- * Loglevel of all Configurable Levels in the logger
- */
- public enum LogLevel {
- INFO,
- WARN,
- ERROR,
- DEBUG,
- TRACE;
-
- /**
- * Collects all LogLevel in a Set
- *
- * @return A Set containing every Loglevel
- */
- public static Set getAll() {
- return EnumSet.allOf(LogLevel.class);
- }
-
- /**
- * Maps the LogLevel to their name and collects it in a Set
- *
- * @return A Set containing every LogLevel as String
- */
- public static Set getAllNames() {
- return Arrays.stream(values()).map(Enum::name).collect(Collectors.toUnmodifiableSet());
- }
- }
-
- /**
- * Maps a Logevent to the color-coded css-Class (css class has i.e. red as background-color for
- * ERROR events)
- *
- * @param event Logevent from the DB with a specific Logevent
- * @return The name of the CSS class to use with this Logevent.
- */
- public static String logLevelToCssClass(final Logevents event) {
- return event.getLevel().toLowerCase(Locale.ENGLISH);
- }
-
-
-
- private LogUtils() {}
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/util/NotificationUtils.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/util/NotificationUtils.java
deleted file mode 100644
index e2968b1165..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/util/NotificationUtils.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package org.togetherjava.tjbot.logwatcher.util;
-
-import com.vaadin.flow.component.notification.Notification;
-import com.vaadin.flow.component.notification.NotificationVariant;
-
-import java.util.concurrent.TimeUnit;
-
-/**
- * Util class for handy Methods regarding Notifications for the Client
- */
-public final class NotificationUtils {
-
-
- private NotificationUtils() {}
-
- /**
- * Prepares a little Notification to display an Errormessage, in case anything goes wrong
- *
- * @param e Exception that occurred
- * @return Notification for the user
- */
- public static Notification getNotificationForError(final Exception e) {
- final Notification not = new Notification();
- not.setDuration((int) TimeUnit.SECONDS.toMillis(6));
- not.setPosition(Notification.Position.MIDDLE);
- not.setText("Exception occurred while saving. %s".formatted(e.getMessage()));
- not.addThemeVariants(NotificationVariant.LUMO_ERROR);
- return not;
- }
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/views/MainLayout.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/views/MainLayout.java
deleted file mode 100644
index d3f60008d7..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/views/MainLayout.java
+++ /dev/null
@@ -1,173 +0,0 @@
-package org.togetherjava.tjbot.logwatcher.views;
-
-import com.google.common.collect.Sets;
-import com.vaadin.flow.component.Component;
-import com.vaadin.flow.component.applayout.AppLayout;
-import com.vaadin.flow.component.applayout.DrawerToggle;
-import com.vaadin.flow.component.avatar.Avatar;
-import com.vaadin.flow.component.button.ButtonVariant;
-import com.vaadin.flow.component.contextmenu.ContextMenu;
-import com.vaadin.flow.component.html.*;
-import com.vaadin.flow.router.PageTitle;
-import com.vaadin.flow.router.RouterLink;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.togetherjava.tjbot.logwatcher.accesscontrol.AllowedRoles;
-import org.togetherjava.tjbot.logwatcher.accesscontrol.Role;
-import org.togetherjava.tjbot.logwatcher.users.AuthenticatedUser;
-import org.togetherjava.tjbot.logwatcher.views.logs.LogsView;
-import org.togetherjava.tjbot.logwatcher.views.logs.StreamedView;
-import org.togetherjava.tjbot.logwatcher.views.usermanagement.UserManagement;
-import org.togetherjava.tjbot.db.generated.tables.pojos.Users;
-
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Stream;
-
-/**
- * The main view is a top-level placeholder for other views.
- */
-@PageTitle("Main")
-@SuppressWarnings({"java:S1192"})
-// Those are css names, and those don't need an extra Constants Class
-public class MainLayout extends AppLayout {
-
- private final transient AuthenticatedUser authenticatedUser;
- private H1 viewTitle;
- private static final Logger logger = LoggerFactory.getLogger(MainLayout.class);
-
- public MainLayout(AuthenticatedUser authUser) {
- this.authenticatedUser = authUser;
- setPrimarySection(Section.DRAWER);
- addToNavbar(true, createHeaderContent());
- addToDrawer(createDrawerContent());
-
- if (authUser.canRegister() && !authUser.isRegistered()) {
- authUser.register();
- }
-
-
- if (this.authenticatedUser.getRoles().isEmpty()) {
- authUser.logout();
- }
-
- }
-
- private static RouterLink createLink(MenuItemInfo menuItemInfo) {
- RouterLink link = new RouterLink();
- link.addClassNames("flex", "mx-s", "p-s", "relative", "text-secondary");
- link.setRoute(menuItemInfo.view());
-
- Span icon = new Span();
- icon.addClassNames("me-s", "text-l");
- if (!menuItemInfo.iconClass().isEmpty()) {
- icon.addClassNames(menuItemInfo.iconClass());
- }
-
- Span text = new Span(menuItemInfo.text());
- text.addClassNames("font-medium", "text-s");
-
- link.add(icon, text);
- return link;
- }
-
- private Component createHeaderContent() {
- DrawerToggle toggle = new DrawerToggle();
- toggle.addClassName("text-secondary");
- toggle.addThemeVariants(ButtonVariant.LUMO_CONTRAST);
- toggle.getElement().setAttribute("aria-label", "Menu toggle");
-
- viewTitle = new H1();
- viewTitle.addClassNames("m-0", "text-l");
-
- Header header = new Header(toggle, viewTitle);
- header.addClassNames("bg-base", "border-b", "border-contrast-10", "box-border", "flex",
- "h-xl", "items-center", "w-full");
- return header;
- }
-
- private Component createDrawerContent() {
- H2 appName = new H2("Logviewer");
- appName.addClassNames("flex", "items-center", "h-xl", "m-0", "px-m", "text-m");
-
- com.vaadin.flow.component.html.Section section = new com.vaadin.flow.component.html.Section(
- appName, createNavigation(), createFooter());
- section.addClassNames("flex", "flex-col", "items-stretch", "max-h-full", "min-h-full");
- return section;
- }
-
- private Nav createNavigation() {
- Nav nav = new Nav();
- nav.addClassNames("border-b", "border-contrast-10", "flex-grow", "overflow-auto");
- nav.getElement().setAttribute("aria-labelledby", "views");
-
- H3 views = new H3("Views");
- views.addClassNames("flex", "h-m", "items-center", "mx-m", "my-0", "text-s",
- "text-tertiary");
- views.setId("views");
-
- createLinks().forEach(nav::add);
-
- return nav;
- }
-
- private List createLinks() {
- return Stream
- .of(new MenuItemInfo("Logs", "la la-globe", LogsView.class),
- new MenuItemInfo("Streamed", "la la-globe", StreamedView.class),
- new MenuItemInfo("User Management", "la la-file", UserManagement.class))
- .filter(this::checkAccess)
- .map(MainLayout::createLink)
- .toList();
- }
-
- private boolean checkAccess(MenuItemInfo menuItemInfo) {
- final Class extends Component> view = menuItemInfo.view;
- final AllowedRoles annotation = view.getAnnotation(AllowedRoles.class);
-
- if (annotation == null) {
- logger.warn("Class {} not properly secured with Annotation", view);
- return false;
- }
-
- final Set roles = Set.of(annotation.roles());
-
- return !Sets.intersection(this.authenticatedUser.getRoles(), roles).isEmpty();
- }
-
- private Footer createFooter() {
- Footer layout = new Footer();
- layout.addClassNames("flex", "items-center", "my-s", "px-m", "py-xs");
-
- Users user = this.authenticatedUser.get();
-
- Avatar avatar = new Avatar(user.getUsername());
- avatar.addClassNames("me-xs");
-
- ContextMenu userMenu = new ContextMenu(avatar);
- userMenu.setOpenOnClick(true);
- userMenu.addItem("Logout", e -> authenticatedUser.logout());
-
- Span name = new Span(user.getUsername());
- name.addClassNames("font-medium", "text-s", "text-secondary");
-
- layout.add(avatar, name);
-
- return layout;
- }
-
- @Override
- protected void afterNavigation() {
- super.afterNavigation();
- viewTitle.setText(getCurrentPageTitle());
- }
-
- private String getCurrentPageTitle() {
- PageTitle title = getContent().getClass().getAnnotation(PageTitle.class);
- return title == null ? "" : title.value();
- }
-
-
- private record MenuItemInfo(String text, String iconClass, Class extends Component> view) {
- }
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/views/logs/LogsView.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/views/logs/LogsView.java
deleted file mode 100644
index 97e23e70e5..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/views/logs/LogsView.java
+++ /dev/null
@@ -1,183 +0,0 @@
-package org.togetherjava.tjbot.logwatcher.views.logs;
-
-import com.vaadin.flow.component.AbstractField;
-import com.vaadin.flow.component.HasValue;
-import com.vaadin.flow.component.checkbox.Checkbox;
-import com.vaadin.flow.component.combobox.ComboBox;
-import com.vaadin.flow.component.html.Paragraph;
-import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
-import com.vaadin.flow.component.orderedlayout.Scroller;
-import com.vaadin.flow.component.orderedlayout.VerticalLayout;
-import com.vaadin.flow.data.provider.DataProvider;
-import com.vaadin.flow.data.renderer.TextRenderer;
-import com.vaadin.flow.router.PageTitle;
-import com.vaadin.flow.router.Route;
-import com.vaadin.flow.router.RouteAlias;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.togetherjava.tjbot.logwatcher.accesscontrol.AllowedRoles;
-import org.togetherjava.tjbot.logwatcher.accesscontrol.Role;
-import org.togetherjava.tjbot.logwatcher.util.LogReader;
-import org.togetherjava.tjbot.logwatcher.util.LogUtils;
-import org.togetherjava.tjbot.logwatcher.util.NotificationUtils;
-import org.togetherjava.tjbot.logwatcher.views.MainLayout;
-
-import javax.annotation.security.PermitAll;
-import java.io.UncheckedIOException;
-import java.nio.file.Path;
-import java.util.Collections;
-import java.util.List;
-import java.util.Locale;
-import java.util.Objects;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-
-/**
- * The Logs View in the Browser
- */
-
-@PageTitle("Logs")
-@Route(value = "logs", layout = MainLayout.class)
-@RouteAlias(value = "", layout = MainLayout.class)
-@AllowedRoles(roles = {Role.USER})
-@PermitAll
-public class LogsView extends VerticalLayout {
-
- private static final Logger logger = LoggerFactory.getLogger(LogsView.class);
-
- private static final Pattern LOGLEVEL_MATCHER =
- Pattern.compile("(%s)".formatted(String.join("|", LogUtils.LogLevel.getAllNames())));
-
- /**
- * Field where the events are displayed
- */
- private final VerticalLayout events = new VerticalLayout();
-
- private final transient LogReader watcher;
-
- public LogsView(LogReader watcher) {
- this.watcher = watcher;
- this.events.setWidthFull();
-
- addClassName("logs-view");
-
- HorizontalLayout options = new HorizontalLayout();
- options.setAlignItems(Alignment.START);
-
- for (final String level : LogUtils.LogLevel.getAllNames()) {
- final Checkbox ch = new Checkbox(level);
- ch.setValue(true);
- ch.addValueChangeListener(this::onLogLevelCheckbox);
- options.add(ch);
- }
-
- ComboBox logs = createComboBox();
- logs.getOptionalValue().ifPresent(this::fillTextField);
-
- add(logs, options, new Scroller(this.events, Scroller.ScrollDirection.VERTICAL));
- }
-
- private void onLogLevelCheckbox(
- AbstractField.ComponentValueChangeEvent event) {
- if (!event.isFromClient()) {
- return;
- }
-
- final String level = event.getSource().getLabel().toLowerCase(Locale.ENGLISH);
-
- this.events.getChildren()
- .filter(Paragraph.class::isInstance)
- .map(Paragraph.class::cast)
- .filter(c -> c.getClassName().equals(level))
- .forEach(c -> c.setVisible(event.getValue()));
- }
-
- /**
- * Creates the Combobox of Logfile-Names where the User can choose what File to view
- *
- * @return The created Combobox
- */
- private ComboBox createComboBox() {
- final ComboBox logs = new ComboBox<>("Log-Files");
- logs.setAllowCustomValue(false);
- logs.setRenderer(new TextRenderer<>(p -> p.getFileName().toString()));
-
- final List logFiles = getLogFiles();
- logs.setItems(DataProvider.ofCollection(logFiles));
- logFiles.stream().findFirst().ifPresent(logs::setValue);
-
- logs.addValueChangeListener(this::onLogFileCombobox);
-
- return logs;
- }
-
- /**
- * When User chooses another Logfile, reload the Log and set it in the textField
- *
- * @param event Generated Event, containing old and new Value
- */
- private void onLogFileCombobox(HasValue.ValueChangeEvent event) {
- if (Objects.equals(event.getOldValue(), event.getValue())) {
- return;
- }
-
- fillTextField(event.getValue());
- }
-
- /**
- * Reload the Log and set it in the textField
- *
- * @param logFileName Name of the Logfile
- */
- private void fillTextField(final Path logFileName) {
- this.events.removeAll();
-
- final List logEntries = getLogEntries(logFileName);
-
- String previousGroup = "unknown";
- for (final String event : logEntries) {
- final String trimmed = event.trim();
- final Paragraph text = new Paragraph(trimmed);
-
- final Matcher matcher = LOGLEVEL_MATCHER.matcher(trimmed);
- if (matcher.find()) {
- previousGroup = matcher.group().toLowerCase(Locale.ENGLISH);
- }
-
- text.addClassName(previousGroup);
- this.events.add(text);
- }
- }
-
- /**
- * Gathers all available Logfiles
- *
- * @return Names of available Logfiles
- */
- private List getLogFiles() {
- try {
- return this.watcher.getLogs();
- } catch (final UncheckedIOException e) {
- logger.error("Exception while gathering LogFiles", e);
- NotificationUtils.getNotificationForError(e).open();
- return Collections.emptyList();
- }
- }
-
- /**
- * Reads the log for the given Logfile
- *
- * @param logFile Name of the log to read
- * @return Contents of the LogFile
- */
- private List getLogEntries(final Path logFile) {
- try {
- return this.watcher.readLog(logFile);
- } catch (final UncheckedIOException e) {
- logger.error("Exception while gathering LogFiles", e);
- NotificationUtils.getNotificationForError(e).open();
- return Collections.emptyList();
- }
- }
-}
diff --git a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/views/logs/StreamedView.java b/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/views/logs/StreamedView.java
deleted file mode 100644
index 2d15ac9cb1..0000000000
--- a/logviewer/src/main/java/org/togetherjava/tjbot/logwatcher/views/logs/StreamedView.java
+++ /dev/null
@@ -1,189 +0,0 @@
-package org.togetherjava.tjbot.logwatcher.views.logs;
-
-import com.vaadin.componentfactory.EnhancedDialog;
-import com.vaadin.flow.component.*;
-import com.vaadin.flow.component.button.Button;
-import com.vaadin.flow.component.checkbox.Checkbox;
-import com.vaadin.flow.component.dependency.CssImport;
-import com.vaadin.flow.component.grid.Grid;
-import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
-import com.vaadin.flow.component.orderedlayout.VerticalLayout;
-import com.vaadin.flow.data.renderer.LocalDateTimeRenderer;
-import com.vaadin.flow.router.PageTitle;
-import com.vaadin.flow.router.Route;
-import com.vaadin.flow.server.SessionDestroyEvent;
-import com.vaadin.flow.server.VaadinService;
-import org.togetherjava.tjbot.db.generated.tables.pojos.Logevents;
-import org.togetherjava.tjbot.logwatcher.accesscontrol.AllowedRoles;
-import org.togetherjava.tjbot.logwatcher.accesscontrol.Role;
-import org.togetherjava.tjbot.logwatcher.constants.LogEventsConstants;
-import org.togetherjava.tjbot.logwatcher.logs.LogRepository;
-import org.togetherjava.tjbot.logwatcher.util.LogUtils;
-import org.togetherjava.tjbot.logwatcher.views.MainLayout;
-import org.togetherjava.tjbot.logwatcher.watcher.StreamWatcher;
-import org.vaadin.crudui.crud.impl.GridCrud;
-
-import javax.annotation.security.PermitAll;
-import java.time.LocalDateTime;
-import java.time.ZoneOffset;
-import java.time.format.DateTimeFormatter;
-import java.util.*;
-import java.util.stream.Collectors;
-
-/**
- * The Logs View in the Browser
- */
-
-@PageTitle("Streamed")
-@Route(value = "streamed", layout = MainLayout.class)
-@AllowedRoles(roles = {Role.USER})
-@PermitAll
-@CssImport(themeFor = "vaadin-grid", value = "./themes/logviewer/views/logs-view.css")
-public class StreamedView extends VerticalLayout {
-
- private final GridCrud grid = new GridCrud<>(Logevents.class);
- private final UUID uuid = UUID.randomUUID();
- private final Set enabledLogLevel = new HashSet<>(LogUtils.LogLevel.getAllNames());
-
- public StreamedView(LogRepository logs) {
- addClassName("logs-view");
-
- final HorizontalLayout buttonPanel =
- new HorizontalLayout(new Button("Change Columns", this::onChangeColumns));
-
- for (final String level : this.enabledLogLevel) {
- final Checkbox ch = new Checkbox(level);
- ch.setValue(true);
- ch.addValueChangeListener(this::onLogLevelCheckbox);
- buttonPanel.add(ch);
- }
-
- add(buttonPanel, this.grid);
-
- this.grid.setOperations(() -> logs.findWithLevelMatching(this.enabledLogLevel), null, null,
- null);
- this.grid.setAddOperationVisible(false);
- this.grid.setDeleteOperationVisible(false);
- this.grid.setUpdateOperationVisible(false);
-
-
- final Grid baseGrid = this.grid.getGrid();
- baseGrid.setColumns(LogEventsConstants.FIELD_INSTANT, LogEventsConstants.FIELD_LOGGER_NAME,
- LogEventsConstants.FIELD_MESSAGE);
- setInstantFormatter();
- baseGrid.getColumns().forEach(c -> c.setAutoWidth(true));
- baseGrid.getColumns().forEach(c -> c.setResizable(true));
- baseGrid.setClassNameGenerator(LogUtils::logLevelToCssClass);
- baseGrid.recalculateColumnWidths();
- baseGrid.setColumnReorderingAllowed(true);
-
- VaadinService.getCurrent().addSessionDestroyListener(this::onDestroy);
- final UI ui = UI.getCurrent();
- StreamWatcher.addSubscription(this.uuid, () -> ui.access(this.grid::refreshGrid));
- }
-
- private void onLogLevelCheckbox(
- AbstractField.ComponentValueChangeEvent event) {
- if (!event.isFromClient()) {
- return;
- }
-
- final String logLevel = event.getSource().getLabel();
-
- final boolean isChecked = event.getValue();// don't inline this, else SonarLint is crying
- if (isChecked) {
- this.enabledLogLevel.add(logLevel);
- } else {
- this.enabledLogLevel.remove(logLevel);
- }
- this.grid.refreshGrid();
- }
-
- private void onDestroy(SessionDestroyEvent event) {
- removeHook();
- }
-
- @Override
- protected void onDetach(DetachEvent detachEvent) {
- removeHook();
- super.onDetach(detachEvent);
- }
-
- private void removeHook() {
- StreamWatcher.removeSubscription(this.uuid);
- }
-
- private void setInstantFormatter() {
- final Grid innerGrid = this.grid.getGrid();
- final Optional> column =
- Optional.ofNullable(innerGrid.getColumnByKey(LogEventsConstants.FIELD_INSTANT));
- if (column.isEmpty()) {
- return;
- }
-
- final Grid.Column instant = column.orElseThrow();
- innerGrid.removeColumn(instant);
-
- final String[] keys =
- innerGrid.getColumns().stream().map(Grid.Column::getKey).toArray(String[]::new);
- innerGrid.removeAllColumns();
-
-
- innerGrid
- .addColumn(new LocalDateTimeRenderer<>(
- logEvents -> LocalDateTime.ofInstant(logEvents.getTime(), ZoneOffset.UTC),
- DateTimeFormatter.ofPattern("yyy-MM-dd HH:mm:ss.SSS")))
- .setHeader("Instant")
- .setComparator(Comparator.comparing(Logevents::getTime))
- .setKey(LogEventsConstants.FIELD_INSTANT);
-
- innerGrid.addColumns(keys);
- }
-
- private void onChangeColumns(ClickEvent