Adding Type and App endpoints
This commit is contained in:
@@ -0,0 +1,90 @@
|
|||||||
|
package net.xintanalabs.rssotto.controller.app
|
||||||
|
|
||||||
|
import net.xintanalabs.rssotto.constants.Constants
|
||||||
|
import net.xintanalabs.rssotto.model.App
|
||||||
|
import net.xintanalabs.rssotto.service.AppService
|
||||||
|
import org.springframework.http.HttpStatus
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam
|
||||||
|
import org.springframework.web.bind.annotation.RestController
|
||||||
|
import org.springframework.web.server.ResponseStatusException
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("${Constants.API_BASE_PATH}/app")
|
||||||
|
class AppController(
|
||||||
|
private val appService: AppService
|
||||||
|
) {
|
||||||
|
@PostMapping
|
||||||
|
fun createApp(@RequestBody app: AppRequest): AppResponse? =
|
||||||
|
appService.createApp(app.toModel())
|
||||||
|
?.toResponse()
|
||||||
|
?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Cannot create app")
|
||||||
|
|
||||||
|
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
fun getApp(@PathVariable id: String): AppResponse? =
|
||||||
|
appService.getAppById(id)
|
||||||
|
?.toResponse()
|
||||||
|
?: throw ResponseStatusException(HttpStatus.NOT_FOUND, "App not found")
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
fun getAllApps(): List<AppResponse> =
|
||||||
|
appService.getAllApps()
|
||||||
|
.map { it.toResponse() }
|
||||||
|
|
||||||
|
@GetMapping("/versions")
|
||||||
|
fun getAppsVersions(@RequestParam version: List<String>): List<AppVersionResponse> {
|
||||||
|
return appService.getAppsByVersions(version).map { it.toVersionResponse() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/search")
|
||||||
|
fun searchApps(@RequestParam q: String): List<AppResponse> {
|
||||||
|
return appService.searchApps(q).map { it.toResponse() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun App.toVersionResponse(): AppVersionResponse {
|
||||||
|
return AppVersionResponse(
|
||||||
|
id = this.id,
|
||||||
|
latestVersion = this.latestVersion,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun App.toResponse(): AppResponse {
|
||||||
|
return AppResponse(
|
||||||
|
id = this.id,
|
||||||
|
uid = this.uid,
|
||||||
|
name = this.name,
|
||||||
|
type = this.type,
|
||||||
|
source = this.source,
|
||||||
|
params = this.params,
|
||||||
|
fields = this.fields,
|
||||||
|
downloadUrl = this.downloadUrl,
|
||||||
|
latestVersion = this.latestVersion,
|
||||||
|
createdAt = this.createdAt,
|
||||||
|
updatedAt = this.updatedAt,
|
||||||
|
lastCheckedAt = this.lastCheckedAt,
|
||||||
|
active = this.active
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun AppRequest.toModel(): App {
|
||||||
|
return App(
|
||||||
|
uid = this.uid,
|
||||||
|
name = this.name,
|
||||||
|
type = this.type,
|
||||||
|
source = this.source,
|
||||||
|
params = this.params,
|
||||||
|
fields = this.fields,
|
||||||
|
downloadUrl = this.downloadUrl,
|
||||||
|
latestVersion = this.latestVersion,
|
||||||
|
createdAt = System.currentTimeMillis(),
|
||||||
|
updatedAt = System.currentTimeMillis(),
|
||||||
|
lastCheckedAt = 0,
|
||||||
|
active = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,16 @@
|
|||||||
|
package net.xintanalabs.rssotto.controller.app
|
||||||
|
|
||||||
|
data class AppRequest(
|
||||||
|
val uid: String,
|
||||||
|
val name: String,
|
||||||
|
val type: String = "",
|
||||||
|
val source: String,
|
||||||
|
val params: Map<String, String>,
|
||||||
|
val fields: Map<String, String>,
|
||||||
|
val downloadUrl: String,
|
||||||
|
val latestVersion: String? = null,
|
||||||
|
val createdAt: Long = 0,
|
||||||
|
val updatedAt: Long = 0,
|
||||||
|
val lastCheckedAt: Long = 0,
|
||||||
|
val active: Boolean = true
|
||||||
|
)
|
@@ -0,0 +1,17 @@
|
|||||||
|
package net.xintanalabs.rssotto.controller.app
|
||||||
|
|
||||||
|
data class AppResponse(
|
||||||
|
val id: String? = null,
|
||||||
|
val uid: String,
|
||||||
|
val name: String,
|
||||||
|
val type: String = "",
|
||||||
|
val source: String,
|
||||||
|
val params: Map<String, String>,
|
||||||
|
val fields: Map<String, String>,
|
||||||
|
val downloadUrl: String,
|
||||||
|
val latestVersion: String? = null,
|
||||||
|
val createdAt: Long = 0,
|
||||||
|
val updatedAt: Long = 0,
|
||||||
|
val lastCheckedAt: Long = 0,
|
||||||
|
val active: Boolean = true
|
||||||
|
)
|
@@ -0,0 +1,8 @@
|
|||||||
|
package net.xintanalabs.rssotto.controller.app
|
||||||
|
|
||||||
|
import org.springframework.data.annotation.Id
|
||||||
|
|
||||||
|
data class AppVersionResponse(
|
||||||
|
@Id val id: String? = null,
|
||||||
|
val latestVersion: String? = null
|
||||||
|
)
|
@@ -25,9 +25,9 @@ class SourceController(private val sourceService: SourceService) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
fun getAll(): List<Source> {
|
fun getAll(): List<SourceResponse> {
|
||||||
return try {
|
return try {
|
||||||
sourceService.findALl()
|
sourceService.findALl().map { it.toResponse() }
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
throw ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Cannot retrieve sources: ${e.message}", e)
|
throw ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Cannot retrieve sources: ${e.message}", e)
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,60 @@
|
|||||||
|
package net.xintanalabs.rssotto.controller.type
|
||||||
|
|
||||||
|
import net.xintanalabs.rssotto.constants.Constants
|
||||||
|
import net.xintanalabs.rssotto.model.Type
|
||||||
|
import net.xintanalabs.rssotto.service.TypeService
|
||||||
|
import org.springframework.http.HttpStatus
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping
|
||||||
|
import org.springframework.web.bind.annotation.RestController
|
||||||
|
import org.springframework.web.server.ResponseStatusException
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("${Constants.API_BASE_PATH}/type")
|
||||||
|
class TypeController(
|
||||||
|
private val typeService: TypeService
|
||||||
|
) {
|
||||||
|
@PostMapping
|
||||||
|
fun createType(@RequestBody type: TypeRequest): TypeResponse? {
|
||||||
|
return typeService.create(type.toModel())
|
||||||
|
?.toResponse()
|
||||||
|
?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Cannot create user")
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
fun getAllTypes(): List<TypeResponse> {
|
||||||
|
return typeService.findAll().map{ it.toResponse() }
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{id}")
|
||||||
|
fun getType(@PathVariable id: String): TypeResponse? {
|
||||||
|
return typeService.findById(id)
|
||||||
|
?.toResponse()
|
||||||
|
?: throw ResponseStatusException(HttpStatus.NOT_FOUND, "User not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun TypeRequest.toModel(): Type =
|
||||||
|
Type(
|
||||||
|
id = null,
|
||||||
|
shortName = this.shortName,
|
||||||
|
name = this.name,
|
||||||
|
configFields = this.configFields,
|
||||||
|
appFields = this.appFields
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun Type.toResponse(): TypeResponse =
|
||||||
|
TypeResponse(
|
||||||
|
id = this.id,
|
||||||
|
shortName = this.shortName,
|
||||||
|
name = this.name,
|
||||||
|
configFields = this.configFields,
|
||||||
|
appFields = this.appFields
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@@ -0,0 +1,10 @@
|
|||||||
|
package net.xintanalabs.rssotto.controller.type
|
||||||
|
|
||||||
|
import net.xintanalabs.rssotto.model.Field
|
||||||
|
|
||||||
|
data class TypeRequest(
|
||||||
|
val shortName: String,
|
||||||
|
val name: String,
|
||||||
|
val configFields: List<Field>,
|
||||||
|
val appFields: List<Field>
|
||||||
|
)
|
@@ -0,0 +1,11 @@
|
|||||||
|
package net.xintanalabs.rssotto.controller.type
|
||||||
|
|
||||||
|
import net.xintanalabs.rssotto.model.Field
|
||||||
|
|
||||||
|
data class TypeResponse(
|
||||||
|
val id: String? = null,
|
||||||
|
val shortName: String,
|
||||||
|
val name: String,
|
||||||
|
val configFields: List<Field>,
|
||||||
|
val appFields: List<Field>
|
||||||
|
)
|
@@ -26,8 +26,8 @@ class UserController(private val userService: UserService) {
|
|||||||
?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Cannot create user")
|
?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Cannot create user")
|
||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
fun listAll(): List<UserResponse> = listOf()
|
fun listAll(): List<UserResponse> =
|
||||||
//userService.findAll().map { it.toResponse() }
|
userService.findAll().map { it.toResponse() }
|
||||||
|
|
||||||
@GetMapping("/{uuid}")
|
@GetMapping("/{uuid}")
|
||||||
fun findById(@PathVariable uuid: UUID): UserResponse {
|
fun findById(@PathVariable uuid: UUID): UserResponse {
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package net.xintanalabs.rssotto.db.mongodb
|
package net.xintanalabs.rssotto.db.mongodb
|
||||||
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
import org.springframework.beans.factory.annotation.Autowired
|
||||||
|
import org.springframework.data.mongodb.core.query.Criteria
|
||||||
|
|
||||||
abstract class MongoDBAbstract<T: Any> (
|
abstract class MongoDBAbstract<T: Any> (
|
||||||
private val mongoDBClient: MongoDBClient
|
private val mongoDBClient: MongoDBClient
|
||||||
@@ -28,4 +29,8 @@ abstract class MongoDBAbstract<T: Any> (
|
|||||||
protected fun update(id: String, updateFields: Map<String, Any>): Long {
|
protected fun update(id: String, updateFields: Map<String, Any>): Long {
|
||||||
return mongoDBClient.updateOne(collection, idField, id, updateFields, entityClass)
|
return mongoDBClient.updateOne(collection, idField, id, updateFields, entityClass)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected fun findByCriteria(criteria: Criteria): List<T> {
|
||||||
|
return mongoDBClient.findByFilter(collection, criteria, entityClass)
|
||||||
|
}
|
||||||
}
|
}
|
22
src/main/kotlin/net/xintanalabs/rssotto/model/App.kt
Normal file
22
src/main/kotlin/net/xintanalabs/rssotto/model/App.kt
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package net.xintanalabs.rssotto.model
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude
|
||||||
|
import org.springframework.data.annotation.Id
|
||||||
|
|
||||||
|
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
data class App(
|
||||||
|
@Id val id: String? = null,
|
||||||
|
val uid: String,
|
||||||
|
val name: String,
|
||||||
|
val type: String = "",
|
||||||
|
val source: String,
|
||||||
|
val params: Map<String, String>,
|
||||||
|
val fields: Map<String, String>,
|
||||||
|
val downloadUrl: String,
|
||||||
|
val latestVersion: String? = null,
|
||||||
|
val createdAt: Long = 0,
|
||||||
|
val updatedAt: Long = 0,
|
||||||
|
val lastCheckedAt: Long = 0,
|
||||||
|
val active: Boolean = true
|
||||||
|
)
|
@@ -0,0 +1,40 @@
|
|||||||
|
package net.xintanalabs.rssotto.repository
|
||||||
|
|
||||||
|
import net.xintanalabs.rssotto.constants.Constants
|
||||||
|
import net.xintanalabs.rssotto.db.mongodb.MongoDBAbstract
|
||||||
|
import net.xintanalabs.rssotto.db.mongodb.MongoDBClient
|
||||||
|
import net.xintanalabs.rssotto.model.App
|
||||||
|
import org.springframework.data.mongodb.core.query.Criteria
|
||||||
|
import org.springframework.stereotype.Repository
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
class AppRepository(
|
||||||
|
mongoDBClient: MongoDBClient
|
||||||
|
): MongoDBAbstract<App>(mongoDBClient) {
|
||||||
|
override val collection: String = Constants.COLLECTION_APPS
|
||||||
|
override val entityClass: Class<App> = App::class.java
|
||||||
|
|
||||||
|
fun createApp(app: App): App {
|
||||||
|
return create(app)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAllApps(): List<App> {
|
||||||
|
return getAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAppById(id: String): App? {
|
||||||
|
return getById(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteApp(id: String): Long {
|
||||||
|
return delete(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateApp(id: String, updateFields: Map<String, Any>): Long {
|
||||||
|
return update(id, updateFields)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun findAppsByCriteria(criteria: Criteria): List<App> {
|
||||||
|
return findByCriteria(criteria)
|
||||||
|
}
|
||||||
|
}
|
@@ -25,4 +25,5 @@ class SourceRepository (
|
|||||||
fun getSourceById(id: String): Source? {
|
fun getSourceById(id: String): Source? {
|
||||||
return getById(id)
|
return getById(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -7,19 +7,21 @@ import net.xintanalabs.rssotto.model.Type
|
|||||||
import org.springframework.stereotype.Repository
|
import org.springframework.stereotype.Repository
|
||||||
|
|
||||||
@Repository
|
@Repository
|
||||||
class TypeRepository(mongoDBClient: MongoDBClient): MongoDBAbstract<Type>(mongoDBClient) {
|
class TypeRepository(
|
||||||
|
mongoDBClient: MongoDBClient
|
||||||
|
): MongoDBAbstract<Type>(mongoDBClient) {
|
||||||
override val collection: String = Constants.COLLECTION_TYPES
|
override val collection: String = Constants.COLLECTION_TYPES
|
||||||
override val entityClass: Class<Type> = Type::class.java
|
override val entityClass: Class<Type> = Type::class.java
|
||||||
|
|
||||||
suspend fun createType(type: Type): Type {
|
fun createType(type: Type): Type {
|
||||||
return create(type)
|
return create(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getAllTypes(): List<Type> {
|
fun getAllTypes(): List<Type> {
|
||||||
return getAll()
|
return getAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getTypeById(id: String): Type? {
|
fun getTypeById(id: String): Type? {
|
||||||
return getById(id)
|
return getById(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -0,0 +1,58 @@
|
|||||||
|
package net.xintanalabs.rssotto.service
|
||||||
|
|
||||||
|
import net.xintanalabs.rssotto.model.App
|
||||||
|
import net.xintanalabs.rssotto.repository.AppRepository
|
||||||
|
import org.springframework.data.mongodb.core.query.Criteria
|
||||||
|
import org.springframework.stereotype.Service
|
||||||
|
|
||||||
|
@Service
|
||||||
|
class AppService(
|
||||||
|
private val appRepository: AppRepository
|
||||||
|
) {
|
||||||
|
|
||||||
|
|
||||||
|
fun createApp(app: App): App? {
|
||||||
|
return appRepository.createApp(app)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAllApps(): List<App> {
|
||||||
|
return appRepository.getAllApps()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAppById(id: String): App? {
|
||||||
|
return appRepository.getAppById(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteApp(id: String): Long {
|
||||||
|
return appRepository.deleteApp(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateApp(id: String, updateFields: Map<String, Any>): Long {
|
||||||
|
return appRepository.updateApp(id, updateFields)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateAppDetails(id: String, newName: String?): Long {
|
||||||
|
val updateFields = mutableMapOf<String, Any>()
|
||||||
|
newName?.let { updateFields["name"] = it }
|
||||||
|
updateFields["updatedAt"] = System.currentTimeMillis()
|
||||||
|
return appRepository.updateApp(id, updateFields)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateLatestVersion(appId: String, latestVersion: String): Long {
|
||||||
|
val updateFields = mapOf<String, Any>(
|
||||||
|
"latestVersion" to latestVersion
|
||||||
|
)
|
||||||
|
return appRepository.updateApp(appId, updateFields)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAppsByVersions(versions: List<String>): List<App> {
|
||||||
|
val criteria = Criteria.where("latestVersion").`in`(versions)
|
||||||
|
return appRepository.findAppsByCriteria(criteria)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun searchApps(query: String): List<App> {
|
||||||
|
val regex = ".*${Regex.escape(query)}.*"
|
||||||
|
val criteria = Criteria.where("name").regex(regex, "i")
|
||||||
|
return appRepository.findAppsByCriteria(criteria)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,22 @@
|
|||||||
|
package net.xintanalabs.rssotto.service
|
||||||
|
|
||||||
|
import net.xintanalabs.rssotto.model.Type
|
||||||
|
import net.xintanalabs.rssotto.repository.TypeRepository
|
||||||
|
import org.springframework.stereotype.Service
|
||||||
|
|
||||||
|
@Service
|
||||||
|
class TypeService(
|
||||||
|
private val typeRepository: TypeRepository
|
||||||
|
) {
|
||||||
|
fun create(type: Type): Type? {
|
||||||
|
return typeRepository.createType(type)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun findAll(): List<Type> {
|
||||||
|
return typeRepository.getAllTypes()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun findById(id: String): Type? {
|
||||||
|
return typeRepository.getTypeById(id)
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user