-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #52 from ACCULA/develop
Release v1.0
- Loading branch information
Showing
191 changed files
with
20,583 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
plugins: | ||
sonar-java: | ||
enabled: true | ||
config: | ||
sonar.java.source: "14" | ||
checks: | ||
squid:S1068: | ||
enabled: false # Unused fields. Since we use lombok, the check results so many false positives | ||
squid:S00112: | ||
enabled: false # Use of generic exceptions in method declaration. | ||
|
||
pmd: | ||
enabled: true | ||
checks: | ||
AtLeastOneConstructor: | ||
enabled: false # Since we use lombok, it's not actual | ||
LawOfDemeter: | ||
enabled: false # We love Java Stream API and other chaining-friendly libraries! | ||
JUnitTestsShouldIncludeAssert: | ||
enabled: false # Spring Boot tests use the underlying statements inside its own | ||
BeanMembersShouldSerialize: | ||
enabled: false # Most of the declared beans in our app should not be serialized | ||
UseProperClassLoader: | ||
enabled: false | ||
CommentDefaultAccessModifier: | ||
enabled: false | ||
SignatureDeclareThrowsException: | ||
enabled: false | ||
ExcessiveImports: | ||
enabled: false | ||
DefaultPackage: | ||
enabled: false # Lombok-associated issue | ||
CallSuperInConstructor: | ||
enabled: false | ||
|
||
config: | ||
file: pmd.xml | ||
|
||
checkstyle: | ||
enabled: true | ||
config: | ||
file: checkstyle.xml | ||
checks: | ||
com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck: | ||
enabled: false # We separate static imports from usual ones but this check does not expect that and thus warns | ||
com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocParagraphCheck: | ||
enabled: false | ||
com.puppycrawl.tools.checkstyle.checks.javadoc.SummaryJavadocCheck: | ||
enabled: false | ||
|
||
checks: | ||
argument-count: | ||
config: | ||
threshold: 5 | ||
complex-logic: | ||
config: | ||
threshold: 10 | ||
file-lines: | ||
config: | ||
threshold: 550 | ||
method-complexity: | ||
config: | ||
threshold: 10 | ||
method-count: | ||
config: | ||
threshold: 25 | ||
method-lines: | ||
config: | ||
threshold: 55 | ||
nested-control-flow: | ||
config: | ||
threshold: 5 | ||
return-statements: | ||
config: | ||
threshold: 5 | ||
similar-code: | ||
config: | ||
threshold: 50 | ||
identical-code: | ||
config: | ||
threshold: 50 | ||
|
||
exclude_patterns: | ||
- "/web/**" | ||
- "/api/src/test/**" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
name: Java CI with Gradle | ||
|
||
on: [push, pull_request] | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Set up JDK 14 | ||
uses: actions/setup-java@v1 | ||
with: | ||
java-version: 14 | ||
- name: Grant execute permission for gradlew | ||
run: chmod +x gradlew | ||
- name: Build with Gradle | ||
run: ./gradlew build -x web:build | ||
|
||
- uses: codecov/codecov-action@v1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
.idea | ||
**/build | ||
*.iml | ||
**/out | ||
/.gradle | ||
*.der | ||
*.pem | ||
application-secrets.* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,5 @@ | ||
# accula | ||
# Advanced Code Clones UniversaL Analyzer | ||
|
||
![Java CI with Gradle](https://github.com/ACCULA/accula/workflows/Java%20CI%20with%20Gradle/badge.svg) | ||
[![codecov](https://codecov.io/gh/accula/accula/branch/develop/graph/badge.svg)](https://codecov.io/gh/accula/accula) | ||
[![Maintainability](https://api.codeclimate.com/v1/badges/889a9bb55d985b215e1b/maintainability)](https://codeclimate.com/github/ACCULA/accula/maintainability) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
FROM gradle:jdk14 AS build | ||
WORKDIR /app | ||
COPY . /app | ||
RUN gradle build -x test -x web:build --no-daemon | ||
|
||
FROM openjdk:14-alpine | ||
COPY --from=build /app/api/build/libs/*.jar accula.jar | ||
ENTRYPOINT ["java","-jar","/accula.jar"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
plugins { | ||
id("org.springframework.boot") version "2.3.0.RC1" | ||
id("io.spring.dependency-management") version "1.0.9.RELEASE" | ||
} | ||
|
||
version = "1.0-SNAPSHOT" | ||
|
||
repositories { | ||
maven(url = "https://repo.spring.io/milestone") | ||
} | ||
|
||
dependencies { | ||
implementation("org.springframework.boot:spring-boot-starter-webflux") | ||
testImplementation("org.springframework.boot:spring-boot-starter-test") { | ||
exclude(group = "org.junit.vintage", module = "junit-vintage-engine") | ||
} | ||
implementation("org.springframework.boot:spring-boot-starter-security") | ||
testImplementation("org.springframework.security:spring-security-test") | ||
|
||
implementation("org.springframework.boot:spring-boot-starter-actuator") | ||
|
||
implementation("org.springframework.boot:spring-boot-starter-oauth2-client") | ||
implementation("org.springframework.security:spring-security-oauth2-client") | ||
|
||
implementation("com.auth0:java-jwt:3.10.2") | ||
|
||
implementation("org.springframework.boot:spring-boot-starter-data-r2dbc") | ||
implementation("io.r2dbc:r2dbc-postgresql:0.8.2.RELEASE") | ||
implementation("io.r2dbc:r2dbc-pool:0.8.2.RELEASE") | ||
implementation("io.r2dbc:r2dbc-spi:0.8.1.RELEASE") | ||
|
||
implementation("org.postgresql:postgresql") | ||
implementation("org.springframework:spring-jdbc") | ||
implementation("org.flywaydb:flyway-core") | ||
|
||
testImplementation("io.zonky.test:embedded-database-spring-test:1.5.3") | ||
|
||
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor") | ||
} |
11 changes: 11 additions & 0 deletions
11
api/src/main/java/org/accula/api/AcculaApiApplication.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package org.accula.api; | ||
|
||
import org.springframework.boot.SpringApplication; | ||
import org.springframework.boot.autoconfigure.SpringBootApplication; | ||
|
||
@SpringBootApplication | ||
public class AcculaApiApplication { | ||
public static void main(final String[] args) { | ||
SpringApplication.run(AcculaApiApplication.class, args); | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
api/src/main/java/org/accula/api/auth/CurrentAuthorizedUserProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package org.accula.api.auth; | ||
|
||
import org.accula.api.auth.jwt.AuthorizedUser; | ||
import org.accula.api.auth.jwt.JwtAuthentication; | ||
import org.springframework.security.core.context.ReactiveSecurityContextHolder; | ||
import reactor.core.publisher.Mono; | ||
|
||
/** | ||
* Provides the current authorized user stored in a {@link org.springframework.security.core.context.SecurityContext} | ||
* | ||
* @author Anton Lamtev | ||
*/ | ||
public final class CurrentAuthorizedUserProvider { | ||
private CurrentAuthorizedUserProvider() { | ||
} | ||
|
||
public static Mono<AuthorizedUser> get() { | ||
return ReactiveSecurityContextHolder | ||
.getContext() | ||
.flatMap(ctx -> { | ||
final var authentication = ctx.getAuthentication(); | ||
if (!(authentication instanceof JwtAuthentication)) { | ||
return Mono.empty(); | ||
} | ||
|
||
return Mono.just(((JwtAuthentication) authentication).getPrincipal()); | ||
}); | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
api/src/main/java/org/accula/api/auth/jwt/AuthorizedUser.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package org.accula.api.auth.jwt; | ||
|
||
import lombok.Value; | ||
|
||
/** | ||
* @author Anton Lamtev | ||
*/ | ||
@Value | ||
public class AuthorizedUser { | ||
Long id; | ||
} |
83 changes: 83 additions & 0 deletions
83
api/src/main/java/org/accula/api/auth/jwt/JwtAccessTokenResponseProducer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package org.accula.api.auth.jwt; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.accula.api.auth.jwt.crypto.Jwt; | ||
import org.accula.api.auth.util.CookieRefreshTokenHelper; | ||
import org.springframework.web.server.ServerWebExchange; | ||
import reactor.core.publisher.Mono; | ||
|
||
import java.net.URI; | ||
import java.time.Duration; | ||
|
||
import static java.nio.charset.StandardCharsets.UTF_8; | ||
import static org.springframework.http.HttpStatus.FOUND; | ||
import static org.springframework.http.HttpStatus.OK; | ||
import static org.springframework.http.MediaType.APPLICATION_JSON; | ||
|
||
/** | ||
* Produces a response in the form of HTTP-redirect or body in JSON format. | ||
* | ||
* @author Anton Lamtev | ||
* @author Vadim Dyachkov | ||
*/ | ||
@RequiredArgsConstructor | ||
public final class JwtAccessTokenResponseProducer { | ||
private static final String RESPONSE_BODY_FORMAT = "{\"accessToken\":\"%s\"}"; | ||
private static final byte[] FAILURE_BODY = String.format(RESPONSE_BODY_FORMAT, "").getBytes(UTF_8); | ||
|
||
private final Jwt jwt; | ||
private final Duration accessExpiresIn; | ||
private final Duration refreshExpiresIn; | ||
private final CookieRefreshTokenHelper cookieRefreshTokenHelper; | ||
private final String webUrl; | ||
|
||
/** | ||
* Produces a response with redirect (i.e. HttpStatus == 302) to the static web-server using the following pattern: | ||
* {@code ${webUrl}/oauth2/redirect?accessToken=${accessToken}}. | ||
*/ | ||
public Mono<Void> formSuccessRedirect(final ServerWebExchange exchange, final Long userId, final String refreshToken) { | ||
return Mono.fromRunnable(() -> { | ||
final var response = exchange.getResponse(); | ||
final var accessTokenDetails = jwt.generate(userId.toString(), accessExpiresIn); | ||
final var location = URI.create(webUrl + "/oauth2/redirect?accessToken=" + accessTokenDetails.getToken()); | ||
response.getHeaders().setLocation(location); | ||
response.setStatusCode(FOUND); | ||
cookieRefreshTokenHelper.set(response.getCookies(), refreshToken, refreshExpiresIn); | ||
}); | ||
} | ||
|
||
/** | ||
* Produces a response with the access token as a part of body JSON | ||
* (see {@code RESPONSE_BODY_FORMAT}), and refresh token included in cookies | ||
*/ | ||
public Mono<Void> formSuccessBody(final ServerWebExchange exchange, final Long userId, final String refreshToken) { | ||
final var response = exchange.getResponse(); | ||
|
||
return response.writeWith(Mono.fromSupplier(() -> { | ||
final var accessTokenDetails = jwt.generate(userId.toString(), accessExpiresIn); | ||
final var respBody = String.format(RESPONSE_BODY_FORMAT, accessTokenDetails.getToken()).getBytes(UTF_8); | ||
|
||
response.setStatusCode(OK); | ||
response.getHeaders().setContentType(APPLICATION_JSON); | ||
response.getHeaders().setContentLength(respBody.length); | ||
cookieRefreshTokenHelper.set(response.getCookies(), refreshToken, refreshExpiresIn); | ||
|
||
return response.bufferFactory().wrap(respBody); | ||
})); | ||
} | ||
|
||
/** | ||
* Produces a response with an empty access token | ||
*/ | ||
public Mono<Void> formFailureBody(final ServerWebExchange exchange) { | ||
final var response = exchange.getResponse(); | ||
|
||
return response.writeWith(Mono.fromSupplier(() -> { | ||
response.setStatusCode(OK); | ||
response.getHeaders().setContentType(APPLICATION_JSON); | ||
response.getHeaders().setContentLength(FAILURE_BODY.length); | ||
|
||
return response.bufferFactory().wrap(FAILURE_BODY); | ||
})); | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
api/src/main/java/org/accula/api/auth/jwt/JwtAuthFilter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package org.accula.api.auth.jwt; | ||
|
||
import org.springframework.security.web.server.authentication.AuthenticationWebFilter; | ||
|
||
/** | ||
* @author Anton Lamtev | ||
*/ | ||
public final class JwtAuthFilter extends AuthenticationWebFilter { | ||
public JwtAuthFilter() { | ||
super(new JwtAuthenticationManager()); | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
api/src/main/java/org/accula/api/auth/jwt/JwtAuthentication.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package org.accula.api.auth.jwt; | ||
|
||
import org.jetbrains.annotations.Nullable; | ||
import org.springframework.security.authentication.AbstractAuthenticationToken; | ||
import org.springframework.security.core.Authentication; | ||
|
||
import java.util.Collections; | ||
|
||
/** | ||
* @author Anton Lamtev | ||
*/ | ||
public final class JwtAuthentication extends AbstractAuthenticationToken implements Authentication { | ||
private static final long serialVersionUID = -7833231338530910449L; | ||
|
||
private final AuthorizedUser user; | ||
|
||
public JwtAuthentication(final AuthorizedUser user) { | ||
super(Collections.emptyList()); | ||
this.user = user; | ||
} | ||
|
||
@Override | ||
@Nullable | ||
public Object getCredentials() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public AuthorizedUser getPrincipal() { | ||
return user; | ||
} | ||
} |
Oops, something went wrong.