diff --git a/build.gradle.kts b/build.gradle.kts index b81a3e2..4cba31a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,6 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import io.spring.gradle.dependencymanagement.dsl.DependencyManagementExtension +import io.gitlab.arturbosch.detekt.extensions.DetektExtension plugins { kotlin("jvm") @@ -15,6 +16,8 @@ plugins { // A Gradle plugin that provides Maven-like dependency management and exclusions // https://docs.spring.io/dependency-management-plugin/docs/current/reference/html/ id("io.spring.dependency-management") + + id("io.gitlab.arturbosch.detekt").version("1.18.0") } allprojects { @@ -40,6 +43,26 @@ subprojects { println("Enabling Spring Boot Dependency Management in project ${project.name}...") apply(plugin = "io.spring.dependency-management") + println("Enabling Detekt support in project ${project.name}...") + apply(plugin = "io.gitlab.arturbosch.detekt") + + detekt { + config = files("$rootDir/detekt-config.yml") + source = files( + DetektExtension.Companion.DEFAULT_SRC_DIR_JAVA, + DetektExtension.Companion.DEFAULT_SRC_DIR_KOTLIN, + ) + reports { + txt.enabled = false + xml.enabled = false + html{ + enabled = true + destination = file("${project.buildDir}/reports/kotlin-detekt-${project.name}.html") + } + + } + } + configure { imports { mavenBom(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES) diff --git a/detekt-config.yml b/detekt-config.yml new file mode 100644 index 0000000..db6624b --- /dev/null +++ b/detekt-config.yml @@ -0,0 +1,396 @@ +build: + maxIssues: 0 + weights: + # complexity: 2 + # LongParameterList: 1 + # style: 1 + # comments: 1 + +processors: + active: true + exclude: + # - 'FunctionCountProcessor' + # - 'PropertyCountProcessor' + # - 'ClassCountProcessor' + # - 'PackageCountProcessor' + # - 'KtFileCountProcessor' + +formatting: + active: true + android: true + autoCorrect: true + MaximumLineLength: + active: true + +console-reports: + active: false + exclude: + # - 'ProjectStatisticsReport' + # - 'ComplexityReport' + # - 'NotificationReport' + # - 'FindingsReport' + # - 'BuildFailureReport' + +comments: + active: false + CommentOverPrivateFunction: + active: false + CommentOverPrivateProperty: + active: false + EndOfSentenceFormat: + active: false + endOfSentenceFormat: ([.?!][ \t\n\r\f<])|([.?!]$) + UndocumentedPublicClass: + active: false + searchInNestedClass: true + searchInInnerClass: true + searchInInnerObject: true + searchInInnerInterface: true + UndocumentedPublicFunction: + active: false + +complexity: + active: true + ComplexCondition: + active: true + threshold: 5 + ComplexInterface: + active: false + threshold: 10 + includeStaticDeclarations: false + ComplexMethod: + active: true + threshold: 10 + ignoreSingleWhenExpression: true + ignoreSimpleWhenEntries: true + LabeledExpression: + active: true + LargeClass: + active: true + threshold: 800 + LongMethod: + active: true + threshold: 40 + LongParameterList: + active: true + threshold: 10 + ignoreDefaultParameters: false + MethodOverloading: + active: false + threshold: 5 + NestedBlockDepth: + active: true + threshold: 4 + StringLiteralDuplication: + active: true + threshold: 3 + ignoreAnnotation: true + excludeStringsWithLessThan5Characters: true + ignoreStringsRegex: '$^' + TooManyFunctions: + active: true + thresholdInFiles: 20 + thresholdInClasses: 20 + thresholdInInterfaces: 20 + thresholdInObjects: 20 + thresholdInEnums: 20 + ignoreDeprecated: false + ignorePrivate: false + +empty-blocks: + active: true + EmptyCatchBlock: + active: true + allowedExceptionNameRegex: "^(_|(ignore|expected).*)" + EmptyClassBlock: + active: true + EmptyDefaultConstructor: + active: false + EmptyDoWhileBlock: + active: true + EmptyElseBlock: + active: true + EmptyFinallyBlock: + active: true + EmptyForBlock: + active: true + EmptyFunctionBlock: + active: true + ignoreOverridden: false + EmptyIfBlock: + active: true + EmptyInitBlock: + active: true + EmptyKtFile: + active: true + EmptySecondaryConstructor: + active: true + EmptyWhenBlock: + active: true + EmptyWhileBlock: + active: true + +exceptions: + active: true + ExceptionRaisedInUnexpectedLocation: + active: true + methodNames: 'toString,hashCode,equals,finalize' + InstanceOfCheckForException: + active: false + NotImplementedDeclaration: + active: true + PrintStackTrace: + active: true + RethrowCaughtException: + active: false + ReturnFromFinally: + active: false + SwallowedException: + active: false + ThrowingExceptionFromFinally: + active: false + ThrowingExceptionInMain: + active: false + ThrowingExceptionsWithoutMessageOrCause: + active: true + exceptions: 'IllegalArgumentException,IllegalStateException,IOException' + ThrowingNewInstanceOfSameException: + active: false + TooGenericExceptionCaught: + active: true + exceptionNames: + - ArrayIndexOutOfBoundsException + - Error + - Exception + - IllegalMonitorStateException + - NullPointerException + - IndexOutOfBoundsException + - RuntimeException + - Throwable + allowedExceptionNameRegex: "^(_|(ignore|expected).*)" + TooGenericExceptionThrown: + active: true + exceptionNames: + - Error + - Exception + - Throwable + - RuntimeException + +naming: + active: true + ClassNaming: + active: true + classPattern: '[A-Z$][a-zA-Z0-9$]*' + ConstructorParameterNaming: + active: true + parameterPattern: '[a-z][A-Za-z0-9]*' + privateParameterPattern: '[a-z][A-Za-z0-9]*' + excludeClassPattern: '$^' + EnumNaming: + active: true + enumEntryPattern: '^[A-Z][_a-zA-Z0-9]*' + ForbiddenClassName: + active: false + forbiddenName: '' + FunctionMaxLength: + active: false + maximumFunctionNameLength: 30 + FunctionMinLength: + active: false + minimumFunctionNameLength: 3 + FunctionNaming: + active: true + functionPattern: '^([a-z$][a-zA-Z$0-9]*)|(`.*`)$' + excludeClassPattern: '$^' + ignoreOverridden: true + FunctionParameterNaming: + active: true + parameterPattern: '[a-z][A-Za-z0-9]*' + excludeClassPattern: '$^' + ignoreOverridden: true + MatchingDeclarationName: + active: true + MemberNameEqualsClassName: + active: false + ignoreOverridden: true + ObjectPropertyNaming: + active: true + constantPattern: '[A-Za-z][_A-Za-z0-9]*' + propertyPattern: '[A-Za-z][_A-Za-z0-9]*' + privatePropertyPattern: '[A-Za-z][_A-Za-z0-9]*' + PackageNaming: + active: false + packagePattern: '^[a-z]+(\.[a-z][a-z0-9]*)*$' + TopLevelPropertyNaming: + active: true + constantPattern: '[A-Z][_A-Z0-9]*' + propertyPattern: '[A-Za-z][_A-Za-z0-9]*' + privatePropertyPattern: '[A-Za-z][_A-Za-z0-9]*' + VariableMaxLength: + active: false + maximumVariableNameLength: 64 + VariableMinLength: + active: false + minimumVariableNameLength: 1 + VariableNaming: + active: true + variablePattern: '[a-z][A-Za-z0-9]*' + privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*' + excludeClassPattern: '$^' + ignoreOverridden: true + +performance: + active: true + ArrayPrimitive: + active: false + ForEachOnRange: + active: true + SpreadOperator: + active: false + UnnecessaryTemporaryInstantiation: + active: true + +potential-bugs: + active: true + DuplicateCaseInWhenExpression: + active: true + EqualsAlwaysReturnsTrueOrFalse: + active: false + EqualsWithHashCodeExist: + active: true + ExplicitGarbageCollectionCall: + active: true + InvalidRange: + active: true + IteratorHasNextCallsNextMethod: + active: false + IteratorNotThrowingNoSuchElementException: + active: false + LateinitUsage: + active: false + excludeAnnotatedProperties: "" + ignoreOnClassesPattern: "" + UnconditionalJumpStatementInLoop: + active: false + UnreachableCode: + active: true + UnsafeCallOnNullableType: + active: false + UnsafeCast: + active: false + UselessPostfixExpression: + active: false + WrongEqualsTypeParameter: + active: false + +style: + active: true + CollapsibleIfStatements: + active: false + DataClassContainsFunctions: + active: false + conversionFunctionPrefix: 'to' + EqualsNullCall: + active: true + ExplicitItLambdaParameter: + active: true + ExpressionBodySyntax: + active: false + includeLineWrapping: false + ForbiddenComment: + active: true + values: 'STOPSHIP:' + ForbiddenImport: + active: false + imports: '' + ForbiddenVoid: + active: false + FunctionOnlyReturningConstant: + active: false + ignoreOverridableFunction: true + excludedFunctions: 'describeContents' + LoopWithTooManyJumpStatements: + active: false + maxJumpCount: 1 + MagicNumber: + active: false + ignoreNumbers: '-1,0,1,2' + ignoreHashCodeFunction: true + ignorePropertyDeclaration: false + ignoreConstantDeclaration: true + ignoreCompanionObjectPropertyDeclaration: true + ignoreAnnotation: false + ignoreNamedArgument: true + ignoreEnums: false + MandatoryBracesIfStatements: + active: true + MaxLineLength: + active: true + maxLineLength: 150 + excludePackageStatements: true + excludeImportStatements: true + excludeCommentStatements: false + MayBeConst: + active: true + ModifierOrder: + active: true + NestedClassesVisibility: + active: false + NewLineAtEndOfFile: + active: true + NoTabs: + active: true + OptionalAbstractKeyword: + active: true + OptionalUnit: + active: false + OptionalWhenBraces: + active: false + PreferToOverPairSyntax: + active: true + ProtectedMemberInFinalClass: + active: true + RedundantVisibilityModifierRule: + active: true + ReturnCount: + active: true + max: 3 + excludedFunctions: "equals" + SafeCast: + active: true + SerialVersionUIDInSerializableClass: + active: false + SpacingBetweenPackageAndImports: + active: true + ThrowsCount: + active: true + max: 3 + TrailingWhitespace: + active: true + UnnecessaryAbstractClass: + active: false + excludeAnnotatedClasses: "dagger.Module" + UnnecessaryApply: + active: true + UnnecessaryInheritance: + active: true + UnnecessaryLet: + active: true + UnnecessaryParentheses: + active: true + UntilInsteadOfRangeTo: + active: true + UnusedImports: + active: true + UnusedPrivateClass: + active: true + UnusedPrivateMember: + active: true + allowedNames: "(_|ignored|expected|serialVersionUID)" + UtilityClassWithPublicConstructor: + active: false + VarCouldBeVal: + active: true + WildcardImport: + active: true + excludeImports: 'java.util.*,kotlinx.android.synthetic.*' diff --git a/exception-handler-logger-spring-web/src/main/kotlin/ru/touchin/exception/handler/spring/EnableSpringExceptionHandler.kt b/exception-handler-logger-spring-web/src/main/kotlin/ru/touchin/exception/handler/spring/EnableSpringExceptionHandlerLogger.kt similarity index 100% rename from exception-handler-logger-spring-web/src/main/kotlin/ru/touchin/exception/handler/spring/EnableSpringExceptionHandler.kt rename to exception-handler-logger-spring-web/src/main/kotlin/ru/touchin/exception/handler/spring/EnableSpringExceptionHandlerLogger.kt diff --git a/exception-handler-logger-spring-web/src/main/kotlin/ru/touchin/exception/handler/spring/configurations/ExceptionHandlerLoggerConfiguration.kt b/exception-handler-logger-spring-web/src/main/kotlin/ru/touchin/exception/handler/spring/configurations/ExceptionHandlerLoggerConfiguration.kt index d93fd54..1f88365 100644 --- a/exception-handler-logger-spring-web/src/main/kotlin/ru/touchin/exception/handler/spring/configurations/ExceptionHandlerLoggerConfiguration.kt +++ b/exception-handler-logger-spring-web/src/main/kotlin/ru/touchin/exception/handler/spring/configurations/ExceptionHandlerLoggerConfiguration.kt @@ -1,4 +1,5 @@ package ru.touchin.exception.handler.spring.configurations + import org.springframework.context.annotation.Bean import org.springframework.context.annotation.ComponentScan import org.springframework.context.annotation.Configuration diff --git a/exception-handler-spring-web/src/main/kotlin/ru/touchin/exception/handler/spring/advices/ExceptionHandlerAdvice.kt b/exception-handler-spring-web/src/main/kotlin/ru/touchin/exception/handler/spring/advices/ExceptionHandlerAdvice.kt index 7e8a6b3..4b7f51a 100644 --- a/exception-handler-spring-web/src/main/kotlin/ru/touchin/exception/handler/spring/advices/ExceptionHandlerAdvice.kt +++ b/exception-handler-spring-web/src/main/kotlin/ru/touchin/exception/handler/spring/advices/ExceptionHandlerAdvice.kt @@ -33,10 +33,14 @@ class ExceptionHandlerAdvice( val body = exceptionResponseBodyCreator(result.apiError) - val headers = if (exceptionResolverProperties.includeHeaders) HttpHeaders().apply { - set("X-Error-Code", result.apiError.errorCode.toString()) - set("X-Error-Message", result.apiError.errorMessage) - } else null + val headers = if (exceptionResolverProperties.includeHeaders) { + HttpHeaders().apply { + set("X-Error-Code", result.apiError.errorCode.toString()) + set("X-Error-Message", result.apiError.errorMessage) + } + } else { + null + } return ResponseEntity(body, headers, result.status) } diff --git a/gradle.properties b/gradle.properties index 0e52839..eb33900 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ kotlin.code.style=official springBootVersion=2.5.3 springDependencyManagementVersion=1.0.11.RELEASE -kotlinVersion=1.5.21 +kotlinVersion=1.6.21 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f371643..ae04661 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/logger-spring/src/main/kotlin/ru/touchin/logger/spring/aspects/LogAspect.kt b/logger-spring/src/main/kotlin/ru/touchin/logger/spring/aspects/LogAspect.kt index b9f1397..a090198 100644 --- a/logger-spring/src/main/kotlin/ru/touchin/logger/spring/aspects/LogAspect.kt +++ b/logger-spring/src/main/kotlin/ru/touchin/logger/spring/aspects/LogAspect.kt @@ -4,6 +4,7 @@ import org.aspectj.lang.ProceedingJoinPoint import org.aspectj.lang.annotation.Around import org.aspectj.lang.annotation.Aspect import org.aspectj.lang.reflect.MethodSignature +import org.slf4j.LoggerFactory import ru.touchin.logger.spring.annotations.AutoLogging import ru.touchin.logger.spring.annotations.LogValue import ru.touchin.logger.builder.LogDataItem @@ -22,6 +23,7 @@ class LogAspect( ) { @Around("@annotation(autoLoggingAnnotation)") + @Suppress("TooGenericExceptionCaught") fun logInvocation(pjp: ProceedingJoinPoint, autoLoggingAnnotation: AutoLogging): Any? { val duration = LogDuration() @@ -46,8 +48,11 @@ class LogAspect( .build() .error() } catch (logError: Throwable) { - error.printStackTrace() - logError.printStackTrace() + LoggerFactory.getLogger(this::class.java) + .let { logger -> + logger.error("Cannot build logger", error) + logger.error("Cannot create logger", logError) + } } } diff --git a/logger/src/main/kotlin/ru/touchin/logger/context/DefaultContextFields.kt b/logger/src/main/kotlin/ru/touchin/logger/context/DefaultContextFields.kt index b204267..ef8a311 100644 --- a/logger/src/main/kotlin/ru/touchin/logger/context/DefaultContextFields.kt +++ b/logger/src/main/kotlin/ru/touchin/logger/context/DefaultContextFields.kt @@ -1,6 +1,6 @@ package ru.touchin.logger.context -@Suppress("unused", "EnumEntryName") +@Suppress("unused", "EnumEntryName", "EnumNaming") enum class DefaultContextFields { id, host, diff --git a/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/scope/repositories/ScopeRepositoryTest.kt b/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/scope/repositories/ScopeRepositoryTest.kt index 5ee13c0..1d7957e 100644 --- a/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/scope/repositories/ScopeRepositoryTest.kt +++ b/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/scope/repositories/ScopeRepositoryTest.kt @@ -48,7 +48,7 @@ internal class ScopeRepositoryTest { val savedScope = scopeRepository.findByIdOrThrow(scope.name) assertTrue( - ReflectionEquals(scope, "createdAt").matches(savedScope) + ReflectionEquals(scope, "createdAt", "users").matches(savedScope) ) } diff --git a/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/user/repositories/UserRepositoryTest.kt b/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/user/repositories/UserRepositoryTest.kt index 13ff569..c220ee7 100644 --- a/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/user/repositories/UserRepositoryTest.kt +++ b/security-authorization-server-core/src/test/kotlin/ru/touchin/auth/core/user/repositories/UserRepositoryTest.kt @@ -51,7 +51,7 @@ internal class UserRepositoryTest { val savedUser = userRepository.findByIdOrThrow(user.id!!) - assertTrue(ReflectionEquals(user, "createdAt").matches(savedUser)) + assertTrue(ReflectionEquals(user, "createdAt", "confirmedAt").matches(savedUser)) } diff --git a/security-authorization-server-oauth2-metadata/src/main/kotlin/ru/touchin/auth/security/jwks/controllers/JwksController.kt b/security-authorization-server-oauth2-metadata/src/main/kotlin/ru/touchin/auth/security/jwks/controllers/JwksController.kt index da625ad..f149d7a 100644 --- a/security-authorization-server-oauth2-metadata/src/main/kotlin/ru/touchin/auth/security/jwks/controllers/JwksController.kt +++ b/security-authorization-server-oauth2-metadata/src/main/kotlin/ru/touchin/auth/security/jwks/controllers/JwksController.kt @@ -1,6 +1,5 @@ package ru.touchin.auth.security.jwks.controllers -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController diff --git a/server-info-spring-web/src/main/kotlin/ru/touchin/server/info/services/ServerInfoHeader.kt b/server-info-spring-web/src/main/kotlin/ru/touchin/server/info/services/ServerInfoHeader.kt index 135f77b..1e553dd 100644 --- a/server-info-spring-web/src/main/kotlin/ru/touchin/server/info/services/ServerInfoHeader.kt +++ b/server-info-spring-web/src/main/kotlin/ru/touchin/server/info/services/ServerInfoHeader.kt @@ -1,7 +1,5 @@ package ru.touchin.server.info.services -import org.springframework.util.MultiValueMap - interface ServerInfoHeader { fun getHeaders(): Map diff --git a/server-info-spring-web/src/main/kotlin/ru/touchin/server/info/services/version/BuildVersionHeader.kt b/server-info-spring-web/src/main/kotlin/ru/touchin/server/info/services/version/BuildVersionHeader.kt index aa3a66f..117a439 100644 --- a/server-info-spring-web/src/main/kotlin/ru/touchin/server/info/services/version/BuildVersionHeader.kt +++ b/server-info-spring-web/src/main/kotlin/ru/touchin/server/info/services/version/BuildVersionHeader.kt @@ -1,10 +1,8 @@ package ru.touchin.server.info.services.version import org.springframework.stereotype.Component -import org.springframework.util.LinkedMultiValueMap -import org.springframework.util.MultiValueMap -import ru.touchin.server.info.services.version.properties.ServerInfoProperties import ru.touchin.server.info.services.ServerInfoHeader +import ru.touchin.server.info.services.version.properties.ServerInfoProperties @Component class BuildVersionHeader( diff --git a/validation-spring/src/main/kotlin/ru/touchin/validation/spring/validators/EmailValidator.kt b/validation-spring/src/main/kotlin/ru/touchin/validation/spring/validators/EmailValidator.kt index cfbdda0..8ea6973 100644 --- a/validation-spring/src/main/kotlin/ru/touchin/validation/spring/validators/EmailValidator.kt +++ b/validation-spring/src/main/kotlin/ru/touchin/validation/spring/validators/EmailValidator.kt @@ -16,6 +16,7 @@ class EmailValidator( } companion object { + @Suppress("MaxLineLength") private const val DEFAULT_EMAIL_REGEX = "^((([A-Za-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`\\{\\|\\}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([A-Za-z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`\\{\\|\\}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([A-Za-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([A-Za-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([A-Za-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([A-Za-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([A-Za-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([A-Za-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([A-Za-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([A-Za-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))$" }