Initial commit

This commit is contained in:
CUBETIQ Solution
2021-12-20 17:26:07 +07:00
commit c72ee8968f
48 changed files with 1014 additions and 0 deletions

37
api/.gitignore vendored Normal file
View File

@@ -0,0 +1,37 @@
HELP.md
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/

52
api/build.gradle.kts Normal file
View File

@@ -0,0 +1,52 @@
import java.io.ByteArrayOutputStream
plugins {
id("org.springframework.boot")
id("io.spring.dependency-management")
kotlin("jvm")
kotlin("plugin.spring")
}
val kotlinVersion = "1.6.0"
val springBootVersion = "2.5.7"
// find the last commit
fun getGitHashLastCommit(): String {
val stdout = ByteArrayOutputStream()
exec {
commandLine("git", "rev-parse", "HEAD")
standardOutput = stdout
}
return stdout.toString().trim()
}
springBoot {
buildInfo {
properties {
additional["commitId"] = getGitHashLastCommit()
additional["springBootVersion"] = springBootVersion
additional["kotlinVersion"] = kotlinVersion
}
}
}
dependencies {
// Migrating from SpringFox
implementation("org.springdoc:springdoc-openapi-ui:1.5.13")
// SPRING FRAMEWORK AND CORE
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
// Development Runtime
developmentOnly("org.springframework.boot:spring-boot-devtools")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
tasks.withType<Test> {
useJUnitPlatform()
}

View File

@@ -0,0 +1,11 @@
package com.cubetiqs.web
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
@SpringBootApplication
class ApiApplication
fun main(args: Array<String>) {
runApplication<ApiApplication>(*args)
}

View File

@@ -0,0 +1,12 @@
package com.cubetiqs.web
import com.cubetiqs.web.stereotype.FunctionComponent
import org.springframework.context.annotation.Lazy
@FunctionComponent
@Lazy(false)
class StaticContextInitializer {
init {
println("Static context is loaded...!")
}
}

View File

@@ -0,0 +1,8 @@
package com.cubetiqs.web.annotation
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.security.SecurityRequirement
@Retention(AnnotationRetention.RUNTIME)
@Operation(security = [SecurityRequirement(name = "bearerAuth")])
annotation class ApiBearerAuth()

View File

@@ -0,0 +1,6 @@
package com.cubetiqs.web.config
import org.springframework.context.annotation.Configuration
@Configuration
class DefaultConfig

View File

@@ -0,0 +1,57 @@
package com.cubetiqs.web.config
import com.cubetiqs.web.property.AppProperties
import io.swagger.v3.oas.annotations.enums.SecuritySchemeType
import io.swagger.v3.oas.annotations.security.SecurityScheme
import io.swagger.v3.oas.models.OpenAPI
import io.swagger.v3.oas.models.info.Info
import io.swagger.v3.oas.models.info.License
import org.springdoc.core.GroupedOpenApi
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration
@SecurityScheme(
name = "bearerAuth",
type = SecuritySchemeType.HTTP,
scheme = "bearer",
bearerFormat = "JWT",
)
class OpenApiDocConfig @Autowired constructor(
val appProperties: AppProperties,
) {
companion object {
private val ADMIN_API_PATH get() = "/admin/**"
private val DEFAULT_API_PATH get() = "/**"
}
@Bean
fun defaultApi(): GroupedOpenApi {
return GroupedOpenApi.builder()
.group("default")
.pathsToMatch(DEFAULT_API_PATH)
.pathsToExclude("/error", ADMIN_API_PATH)
.packagesToScan("com.cubetiqs.web")
.build()
}
@Bean
fun adminApi(): GroupedOpenApi {
return GroupedOpenApi.builder()
.group("admin")
.pathsToMatch(ADMIN_API_PATH)
.build()
}
@Bean
fun cubetiqOpenAPI(): OpenAPI {
return OpenAPI()
.info(
Info().title(appProperties.appName)
.description(appProperties.appDescription)
.version(appProperties.appVersion)
.license(License().name("Apache 2.0").url(appProperties.appLicenseUrl))
)
}
}

View File

@@ -0,0 +1,15 @@
package com.cubetiqs.web.controller
import io.swagger.v3.oas.annotations.Hidden
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.servlet.view.RedirectView
@Hidden
@Controller
class ApiDoc {
@GetMapping(value = [ "/api-doc", "/api-docs"])
fun redirect(): RedirectView {
return RedirectView("/swagger-ui/")
}
}

View File

@@ -0,0 +1,13 @@
package com.cubetiqs.web.controller
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
interface BaseController {
fun <T> response(
data: T?,
status: HttpStatus = HttpStatus.OK,
): ResponseEntity<T?> {
return ResponseEntity.status(status).body(data)
}
}

View File

@@ -0,0 +1,47 @@
package com.cubetiqs.web.controller
import com.cubetiqs.web.model.response.ApiInfoAuthorResponse
import com.cubetiqs.web.model.response.ApiInfoResponse
import com.cubetiqs.web.model.response.HealthResponse
import com.cubetiqs.web.util.RouteConstants
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.info.BuildProperties
import org.springframework.core.env.Environment
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@Tag(name = "Miscellaneous")
@RestController
@RequestMapping(RouteConstants.INDEX)
class IndexController @Autowired constructor(
private val buildProperties: BuildProperties,
private val environment: Environment,
) : BaseController {
@GetMapping
fun index(): ResponseEntity<ApiInfoResponse?> {
val authors = listOf(
ApiInfoAuthorResponse(name = "Sambo Chea", email = "sombochea@cubetiqs.com"),
ApiInfoAuthorResponse(name = "CUBETIQ OSS", email = "oss@cubetiqs.com"),
)
val response = ApiInfoResponse(
info = "API Operation is running normally on ${environment.activeProfiles.joinToString(separator = ",")}",
name = buildProperties.name,
service = buildProperties.artifact,
version = buildProperties.version,
date = buildProperties.time.toString(),
commit = buildProperties["commitId"],
authors = authors,
)
return response(response)
}
@GetMapping("/health")
fun health(): ResponseEntity<HealthResponse?> {
return response(
HealthResponse.UP
)
}
}

View File

@@ -0,0 +1,20 @@
package com.cubetiqs.web.controller.admin
import com.cubetiqs.web.annotation.ApiBearerAuth
import com.cubetiqs.web.controller.BaseController
import com.cubetiqs.web.util.RouteConstants
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@Tag(name = "Admin")
@RestController
@RequestMapping(RouteConstants.ADMIN)
class AdminController : BaseController {
@ApiBearerAuth
@GetMapping
fun getAdmin(): String {
return "Admin"
}
}

View File

@@ -0,0 +1,14 @@
package com.cubetiqs.web.exception
open class BaseException : RuntimeException {
constructor() : super()
constructor(message: String?) : super(message)
constructor(message: String?, cause: Throwable?) : super(message, cause)
constructor(cause: Throwable?) : super(cause)
constructor(message: String?, cause: Throwable?, enableSuppression: Boolean, writableStackTrace: Boolean) : super(
message,
cause,
enableSuppression,
writableStackTrace
)
}

View File

@@ -0,0 +1,5 @@
package com.cubetiqs.web.infrastructure.component
interface BaseFunctionComponent<I, O> {
fun execute(input: I?): O?
}

View File

@@ -0,0 +1,7 @@
package com.cubetiqs.web.infrastructure.data
import java.io.Serializable
interface BaseEntity <ID : Serializable> : Serializable {
fun setId(id: ID)
}

View File

@@ -0,0 +1,5 @@
package com.cubetiqs.web.infrastructure.event
import java.io.Serializable
interface BaseEvent : Serializable

View File

@@ -0,0 +1,9 @@
package com.cubetiqs.web.infrastructure.listener
import com.cubetiqs.web.infrastructure.event.BaseEvent
interface BaseEventListener {
fun persist(event: BaseEvent) {
return
}
}

View File

@@ -0,0 +1,3 @@
package com.cubetiqs.web.infrastructure.repository
interface BaseRepository

View File

@@ -0,0 +1,3 @@
package com.cubetiqs.web.infrastructure.service
interface BaseService

View File

@@ -0,0 +1,5 @@
package com.cubetiqs.web.model.ob
import java.io.Serializable
interface BaseOb : Serializable

View File

@@ -0,0 +1,5 @@
package com.cubetiqs.web.model.request
import com.cubetiqs.web.model.ob.BaseOb
interface BaseResponseModel : BaseOb

View File

@@ -0,0 +1,20 @@
package com.cubetiqs.web.model.response
import io.swagger.v3.oas.annotations.media.Schema
@Schema(name = "ApiInfoResponse", description = "ApiInfoResponse")
data class ApiInfoResponse(
val name: String,
val info: String,
val service: String,
val version: String,
val date: String,
val commit: String,
val authors: Collection<ApiInfoAuthorResponse> = listOf(),
) : BaseRequestModel
@Schema(name = "ApiInfoAuthorResponse", description = "ApiInfoAuthorResponse")
data class ApiInfoAuthorResponse(
val name: String,
val email: String,
) : BaseRequestModel

View File

@@ -0,0 +1,5 @@
package com.cubetiqs.web.model.response
import com.cubetiqs.web.model.ob.BaseOb
interface BaseRequestModel : BaseOb

View File

@@ -0,0 +1,16 @@
package com.cubetiqs.web.model.response
import io.swagger.v3.oas.annotations.media.Schema
@Schema(name = "HealthResponse", description = "HealthResponse")
data class HealthResponse(
@Schema(name = "status", description = "Status for the service")
val status: String,
) : BaseRequestModel {
companion object {
private const val STATUS_UP = "UP"
private const val STATUS_DOWN = "DOWN"
val UP get() = HealthResponse(STATUS_UP)
val DOWN get() = HealthResponse(STATUS_DOWN)
}
}

View File

@@ -0,0 +1,5 @@
package com.cubetiqs.web.modules
interface AppModule {
fun getModule(): Class<*>
}

View File

@@ -0,0 +1,19 @@
package com.cubetiqs.web.property
import com.cubetiqs.web.stereotype.FunctionComponent
import org.springframework.beans.factory.annotation.Value
@FunctionComponent
class AppProperties(
@Value("\${cubetiq.app.name:CUBETIQ Web API}")
val appName: String,
@Value("\${cubetiq.app.description:CUBETIQ Web APIs Documentation}")
val appDescription: String,
@Value("\${cubetiq.app.version:v0.0.1}")
val appVersion: String,
@Value("\${cubetiq.app.license-url:https://cubetiqs.com}")
val appLicenseUrl: String,
)

View File

@@ -0,0 +1,20 @@
package com.cubetiqs.web.stereotype
import org.springframework.context.annotation.Lazy
import org.springframework.core.annotation.AliasFor
import org.springframework.stereotype.Component
/**
* @author sombochea <Sambo Chea>
* @email sombochea@cubetiqs.com
* @date 18/05/21
* @since 1.0
*/
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.ANNOTATION_CLASS, AnnotationTarget.CLASS)
@Lazy(value = true)
@Component
annotation class FunctionComponent(
@get: AliasFor(annotation = Component::class)
val value: String = ""
)

View File

@@ -0,0 +1,10 @@
package com.cubetiqs.web.util
object RouteConstants {
const val INDEX = "/"
const val ADMIN = "/admin"
}
object AppConstants {
val BASE_PACKAGE_API_DOCS get() = "com.cubetiqs.web"
}

View File

@@ -0,0 +1,2 @@
server:
port: 8080

View File

@@ -0,0 +1,22 @@
spring:
profiles:
active: ${APP_PROFILE:dev}
application:
name: cubetiq-api-service
cubetiq:
app:
data-dir: ${APP_DATA_DIR:${user.home}/${spring.application.name}}
name: CUBETIQ Web API
description: CUBETIQ Spring Web API's Documentation
logging:
file:
path: ${LOGGING_FILE_PATH:${cubetiq.app.data-dir}/logs/}
name: ${logging.file.path}/app.log
springdoc:
api-docs:
enabled: true
swagger-ui:
path: /swagger-ui

View File

@@ -0,0 +1,13 @@
package com.cubetiqs.web
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
@SpringBootTest
class ApiApplicationTests {
@Test
fun contextLoads() {
}
}