Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #152

Merged
merged 44 commits into from
Jan 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
aa93efa
Introduce PublicEndpoint for dynamic public endpoint resolution
MichiBaum Jan 5, 2025
e773024
Merge pull request #146 from MichiBaum/public-endpoint-resolving
MichiBaum Jan 6, 2025
044a26a
Move robots.txt and sitemap.xml generation to backend
MichiBaum Jan 6, 2025
0d3047f
Merge pull request #148 from MichiBaum/144-feature-request-generate-s…
MichiBaum Jan 6, 2025
34c30f5
Update service security to enforce specific permissions
MichiBaum Jan 6, 2025
c1b6e97
Refactor AdminServiceCredentials to use immutable properties
MichiBaum Jan 6, 2025
1b9b48f
Use `linkedSignal` and skip tests in Maven build.
MichiBaum Jan 7, 2025
070fed6
Adjust event query range to include only last month.
MichiBaum Jan 7, 2025
bf01d51
Release version 1.0.0.
MichiBaum Jan 7, 2025
a6cbfcf
Upgrade Mockk and Maven plugins to newer version.
MichiBaum Jan 7, 2025
25948c0
Add SECURITY.md to outline vulnerability reporting process
MichiBaum Jan 7, 2025
b293566
Merge pull request #149 from MichiBaum/cleanup-refactorings-and-impro…
MichiBaum Jan 7, 2025
7985bb9
Remove Fide Id column from chess person selection table
MichiBaum Jan 8, 2025
074ed2d
Tmp: Add FIDE ratings import functionality
MichiBaum Jan 8, 2025
66a5e7e
Tmp added MetaService, Refactor services structure for better organiz…
MichiBaum Jan 9, 2025
11113ee
Add token expiration check and auto-logout mechanism
MichiBaum Jan 9, 2025
770bde1
Merge pull request #150 from MichiBaum/cleanup-refactorings-and-impro…
MichiBaum Jan 9, 2025
168acca
Update PrimeNG and @primeng/themes to version 19.0.4
MichiBaum Jan 9, 2025
c59ad4a
Update Angular dependencies to version 19.0.6
MichiBaum Jan 9, 2025
8ce1da4
Add chess engine and opening functionality
MichiBaum Jan 11, 2025
21084c5
Add engine management functionality and clean up PersonService
MichiBaum Jan 13, 2025
ae02e79
Add chess opening management feature
MichiBaum Jan 13, 2025
a449c78
Use spaces instead of tabs in .editorconfig
MichiBaum Jan 13, 2025
2465fda
Remove unused imports and reformat code alignment
MichiBaum Jan 13, 2025
a605f9d
Add hierarchical move evaluations to chess openings
MichiBaum Jan 15, 2025
e56b1c0
Add chess move tree visualization and API enhancements
MichiBaum Jan 17, 2025
955099d
Add chess opening and move form components with dialogs
MichiBaum Jan 18, 2025
56af449
Add support for creating and saving chess moves and openings
MichiBaum Jan 19, 2025
1c10c9f
Update chess move tree permissions and dynamic menu logic
MichiBaum Jan 20, 2025
08c10bb
Migrate domain entities to database package
MichiBaum Jan 21, 2025
e74e54a
Add ChessOpeningActions component for managing chess moves
MichiBaum Jan 21, 2025
70e3c54
chess-move-tree emit unselect
MichiBaum Jan 21, 2025
2fb4772
update PrimeNG from 19.0.4 to 19.0.5
MichiBaum Jan 21, 2025
6dfdbe5
Add move tree depth parameter and improve UI layout
MichiBaum Jan 21, 2025
275573d
Introduce move evaluation UI and backend logic for chess openings
MichiBaum Jan 22, 2025
7036024
Update MockK to version 1.13.16
MichiBaum Jan 22, 2025
4f6d184
Add starting openings feature to chess module
MichiBaum Jan 22, 2025
261fc9f
Refactor chess openings route for mobile compatibility.
MichiBaum Jan 22, 2025
e4bce08
Add soft delete functionality for openings and moves
MichiBaum Jan 23, 2025
0ccc37b
Refactor chess evaluation form and dialog components.
MichiBaum Jan 23, 2025
ab629e2
Merge pull request #151 from MichiBaum/chess-update-game-moves-opening
MichiBaum Jan 23, 2025
fa0267c
Upgrade Angular and related dependencies to latest versions
MichiBaum Jan 23, 2025
b78ef82
Fix: Add @PublicEndpoint annotation to getAllChessEngines method
MichiBaum Jan 24, 2025
0ef5532
Add dynamic URL generation for data-driven sitemap entries
MichiBaum Jan 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ jobs:
run: npm run --prefix website build-production

- name: Maven package
run: mvn package -Ppublish-image -DdockerHub.username=${{secrets.DOCKER_USERNAME}} -DdockerHub.password=${{secrets.DOCKER_PASSWORD}}
run: mvn package -Ppublish-image -DskipTests -DdockerHub.username=${{secrets.DOCKER_USERNAME}} -DdockerHub.password=${{secrets.DOCKER_PASSWORD}}
24 changes: 24 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Security Policy

## How To Report a Vulnerability

If you think you have found a vulnerability in this repository, please report it to us through coordinated disclosure.

**Please do not report security vulnerabilities through public issues, discussions, or change requests.**

Instead, report it using one of the following ways:

* Contact the [Developer Team](mailto:[email protected]) via email

Please include as much of the information listed below as you can to help us better understand and resolve the issue:

* The type of issue (e.g., buffer overflow, SQL injection, or cross-site scripting)
* Impact of the issue, including how an attacker might exploit the issue
* Step-by-step instructions to reproduce the issue
* The location of the affected source code (tag/branch/commit or direct URL)
* Full paths of source file(s) related to the manifestation of the issue
* Configuration required to reproduce the issue
* Log files that are related to this issue (if possible)
* Proof-of-concept or exploit code (if possible)

This information will help us triage your report more quickly.
6 changes: 3 additions & 3 deletions admin-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<groupId>com.michibaum</groupId>
<artifactId>microservice</artifactId>
<version>1.0.0-TEST-9</version>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down Expand Up @@ -72,13 +72,13 @@
<dependency>
<groupId>com.michibaum</groupId>
<artifactId>spring-boot-starter-discord</artifactId>
<version>1.0.0-TEST-9</version>
<version>1.0.0</version>
</dependency>

<dependency>
<groupId>com.michibaum</groupId>
<artifactId>authentication-library</artifactId>
<version>1.0.0-TEST-9</version>
<version>1.0.0</version>
</dependency>

<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties

@ConfigurationProperties(prefix = "spring.boot.admin.client")
data class AdminServiceCredentials(
var username: String = "",
var password: String = ""
val username: String,
val password: String
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.michibaum.admin_service.security

import com.michibaum.authentication_library.AuthenticationClient
import com.michibaum.authentication_library.public_endpoints.PublicEndpoint
import com.michibaum.authentication_library.public_endpoints.PublicEndpointResolver
import com.michibaum.authentication_library.security.ServletAuthenticationFilter
import com.michibaum.authentication_library.security.ServletDelegateAuthenticationManager
import com.michibaum.authentication_library.security.SpecificAuthenticationManager
Expand All @@ -10,18 +12,20 @@ import com.michibaum.authentication_library.security.basic.servlet.BasicAuthenti
import com.michibaum.authentication_library.security.jwt.JwsValidator
import com.michibaum.authentication_library.security.jwt.JwtAuthenticationManager
import com.michibaum.authentication_library.security.jwt.servlet.JwtAuthenticationConverter
import org.springframework.boot.context.properties.EnableConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Lazy
import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.web.authentication.AuthenticationConverter

@Configuration
@EnableConfigurationProperties(value = [AdminServiceCredentials::class])
class SecurityBeansConfiguration {

@Bean
fun adminServiceCredentials(): AdminServiceCredentials =
AdminServiceCredentials()
fun publicEndpointResolver(): PublicEndpointResolver =
PublicEndpointResolver(PublicEndpoint::class.java, "com.michibaum.admin_service")



Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.michibaum.admin_service.security

import com.michibaum.authentication_library.public_endpoints.PublicEndpointResolver
import com.michibaum.authentication_library.security.ServletAuthenticationFilter
import com.michibaum.permission_library.Permissions
import org.springframework.context.annotation.Bean
Expand All @@ -20,12 +21,15 @@ class SecurityConfiguration {
@Bean
fun securityFilterChain(
http: HttpSecurity,
authenticationFilter: ServletAuthenticationFilter
authenticationFilter: ServletAuthenticationFilter,
publicEndpointResolver: PublicEndpointResolver
): SecurityFilterChain {
val publicEndpoints = publicEndpointResolver.run()
return http
.authorizeHttpRequests {
it.anyRequest()
.hasAnyAuthority(Permissions.ADMIN_SERVICE.name)
.authorizeHttpRequests { authorizeHttpRequests ->
authorizeHttpRequests
.requestMatchers(*publicEndpoints.map { it.requestMatcher}.toTypedArray()).permitAll()
.anyRequest().hasAnyAuthority(Permissions.ADMIN_SERVICE.name)
}
.addFilterBefore(authenticationFilter, UsernamePasswordAuthenticationFilter::class.java)
.httpBasic { httpBasicSpec -> httpBasicSpec.disable() }
Expand Down
4 changes: 2 additions & 2 deletions authentication-library/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<artifactId>microservice</artifactId>
<groupId>com.michibaum</groupId>
<version>1.0.0-TEST-9</version>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down Expand Up @@ -53,7 +53,7 @@
<dependency>
<groupId>com.michibaum</groupId>
<artifactId>permission-library</artifactId>
<version>1.0.0-TEST-9</version>
<version>1.0.0</version>
</dependency>

<dependency>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.michibaum.authentication_library.public_endpoints

@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class PublicEndpoint(

)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.michibaum.authentication_library.public_endpoints

import org.springframework.http.HttpMethod
import org.springframework.security.web.util.matcher.AntPathRequestMatcher
import org.springframework.security.web.util.matcher.RequestMatcher
import org.springframework.web.bind.annotation.RequestMethod

class PublicEndpointDetails(
val rawPath: String,
requestMethod: RequestMethod
) {

val antPath: String = createAntPath()
val httpMethod: HttpMethod = HttpMethod.valueOf(requestMethod.name)
val requestMatcher: RequestMatcher = createRequestMatcher()

private fun createAntPath(): String {
return rawPath.replace("\\{.*}".toRegex(), "*")
}

private fun createRequestMatcher(): RequestMatcher {
return AntPathRequestMatcher.antMatcher(httpMethod, antPath)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package com.michibaum.authentication_library.public_endpoints

import org.slf4j.Logger
import org.slf4j.LoggerFactory
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider
import org.springframework.core.type.filter.AnnotationTypeFilter
import org.springframework.web.bind.annotation.*
import java.lang.reflect.Method


class PublicEndpointResolver(
private val publicAnnotation: Class<out Annotation>,
private vararg val packageName: String
) { // TODO take into account that @RestController can have @RequestMapping

private val logger: Logger = LoggerFactory.getLogger(PublicEndpointResolver::class.java)

fun run(): List<PublicEndpointDetails> {
val mappings = getAllRestController()
.map { getMethodsAnnotatedWith(it) }
.map { getMappingValue(it) }
.flatten()

logger.info("Found ${mappings.size} public endpoints")
for (mapping in mappings) {
logger.info("Mapping: ${mapping.httpMethod} '${mapping.rawPath}' converted to antPath: '${mapping.antPath}'")
}
return mappings
}


private fun getMethodsAnnotatedWith(type: Class<*>): List<Method> {
logger.debug("Searching for methods annotated with ${publicAnnotation.name} in class: ${type.name}")
val methods: Array<Method> = type.methods
logger.debug("Found ${methods.size} methods")
val annotatedMethods: MutableList<Method> = ArrayList(methods.size)
for (method in methods) {
if (method.isAnnotationPresent(publicAnnotation)) {
annotatedMethods.add(method)
}
}
logger.debug("Found ${annotatedMethods.size} annotated methods")
return annotatedMethods
}

private fun getMappingValue(methods: List<Method>): List<PublicEndpointDetails> {
return methods.map { getMappingValue(it) }
.flatten()
.toList()
}

private fun getMappingValue(method: Method): List<PublicEndpointDetails> {
logger.debug("Searching for mapping annotation on method: ${method.name}")

val mappings = ArrayList<PublicEndpointDetails>()

getEndpointsFromRequestMapping(method).also {
mappings.addAll(it)
}

if(method.isAnnotationPresent(GetMapping::class.java)){
val paths = method.getAnnotation(GetMapping::class.java).value
val result = paths.map { PublicEndpointDetails(it, RequestMethod.GET) }
mappings.addAll(result)
}

if(method.isAnnotationPresent(PostMapping::class.java)){
val paths = method.getAnnotation(PostMapping::class.java).value
val result = paths.map { PublicEndpointDetails(it, RequestMethod.POST) }
mappings.addAll(result)
}

if(method.isAnnotationPresent(PutMapping::class.java)){
val paths = method.getAnnotation(PutMapping::class.java).value
val result = paths.map { PublicEndpointDetails(it, RequestMethod.PUT) }
mappings.addAll(result)
}

if(method.isAnnotationPresent(PatchMapping::class.java)){
val paths = method.getAnnotation(PatchMapping::class.java).value
val result = paths.map { PublicEndpointDetails(it, RequestMethod.PATCH) }
mappings.addAll(result)
}

if (method.isAnnotationPresent(DeleteMapping::class.java)) {
val paths = method.getAnnotation(DeleteMapping::class.java).value
val result = paths.map { PublicEndpointDetails(it, RequestMethod.DELETE) }
mappings.addAll(result)
}

logger.debug("Found mapping: $mappings")
return mappings
}

private fun getEndpointsFromRequestMapping(
method: Method,
): List<PublicEndpointDetails> {
if (method.isAnnotationPresent(RequestMapping::class.java)) {
val paths = method.getAnnotation(RequestMapping::class.java).value
val methods = method.getAnnotation(RequestMapping::class.java).method
val result = paths.map { path ->
methods.map { method ->
PublicEndpointDetails(path, method)
}
}.flatten()
return result
}
return emptyList()
}

private fun getAllRestController(): List<Class<*>> {
logger.debug("Searching for all RestController in packages: ${packageName.joinToString(", ")}")
val scanner = ClassPathScanningCandidateComponentProvider(false)
scanner.addIncludeFilter(AnnotationTypeFilter(RestController::class.java))
val beanDefinitions = packageName.map { scanner.findCandidateComponents(it) }
.flatten()
.filterNotNull()

logger.debug("Found ${beanDefinitions.size} RestController")
val classes = beanDefinitions.map { Class.forName(it.beanClassName) }.filterNotNull().toList()
logger.debug("Resolved ${classes.size} classes of RestController")
return classes
}

}
8 changes: 4 additions & 4 deletions authentication-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<parent>
<artifactId>microservice</artifactId>
<groupId>com.michibaum</groupId>
<version>1.0.0-TEST-9</version>
<version>1.0.0</version>
</parent>

<artifactId>authentication-service</artifactId>
Expand Down Expand Up @@ -86,17 +86,17 @@
<dependency>
<groupId>com.michibaum</groupId>
<artifactId>authentication-library</artifactId>
<version>1.0.0-TEST-9</version>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.michibaum</groupId>
<artifactId>usermanagement-library</artifactId>
<version>1.0.0-TEST-9</version>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.michibaum</groupId>
<artifactId>spring-boot-starter-discord</artifactId>
<version>1.0.0-TEST-9</version>
<version>1.0.0</version>
</dependency>

<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.michibaum.authentication_service.authentication

import com.michibaum.authentication_library.AuthenticationEndpoints
import com.michibaum.authentication_library.PublicKeyDto
import com.michibaum.authentication_library.public_endpoints.PublicEndpoint
import com.michibaum.usermanagement_library.*
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Lazy
Expand All @@ -20,6 +21,7 @@ class AuthenticationController (
@Lazy
lateinit var usermanagementClient: UsermanagementClient

@PublicEndpoint
@PostMapping(value = ["/api/authenticate"])
fun authenticate(@RequestBody authenticationDto: AuthenticationDto): ResponseEntity<AuthenticationResponse> {
val loginDto = LoginDto(authenticationDto.username, authenticationDto.password)
Expand All @@ -36,6 +38,7 @@ class AuthenticationController (
return ResponseEntity.ok().body(responseBody)
}

@PublicEndpoint
@PostMapping(value = ["/api/register"])
fun register(@RequestBody registerDto: RegisterDto): ResponseEntity<RegisterResponse> {
val createUserDto = CreateUserDto(registerDto.username, registerDto.email, registerDto.password)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties

@ConfigurationProperties(prefix = "spring.boot.admin.client")
data class AdminServiceCredentials(
var username: String = "",
var password: String = ""
val username: String,
val password: String
)
Loading
Loading