update for getDevice
- add get device in DeviceController - add get device in DeviceService - update logging - update and cleanup in README.md
This commit is contained in:
48
README.md
48
README.md
@@ -5,14 +5,14 @@ Classes crafted, identities bestowed, Each device recorded, their functions unfo
|
|||||||
## Properties for deployment
|
## Properties for deployment
|
||||||
|
|
||||||
| name | required | info |
|
| name | required | info |
|
||||||
|------------------------|----------|-------------------------|
|
|------------------------|:--------:|-------------------------|
|
||||||
| spring.profiles.active | * | Spring Boot environment |
|
| spring.profiles.active | ✓ | Spring Boot environment |
|
||||||
| spring.r2dbc.url | * | Postgres host url |
|
| spring.r2dbc.url | ✓ | Postgres host url |
|
||||||
| spring.r2dbc.username | * | Postgres username |
|
| spring.r2dbc.username | ✓ | Postgres username |
|
||||||
| spring.r2dbc.password | ** | Postgres password |
|
| spring.r2dbc.password | ✗ | Postgres password |
|
||||||
| jwt.private-key | | JWT private cert |
|
| jwt.private-key | ✓ | JWT private cert |
|
||||||
|
|
||||||
Required: * can be stored as text, and ** need to be stored as secret.
|
*Required: ✓ can be stored as text, and ✗ need to be stored as secret.*
|
||||||
|
|
||||||
## Releasing Service
|
## Releasing Service
|
||||||
|
|
||||||
@@ -20,34 +20,28 @@ Run `release.sh` script from `master` branch.
|
|||||||
|
|
||||||
## Development Information
|
## Development Information
|
||||||
|
|
||||||
### Generate Private and Public RSA Key
|
### Private RSA Key
|
||||||
|
|
||||||
OpenSSL Project is dedicated to providing a simple installation of OpenSSL for Microsoft Windows. [Download](https://slproweb.com/products/Win32OpenSSL.html)
|
This service uses RAS keys to create identities for devices. The private key is used here to generate identities, while the public key is used by **[Hlæja Device API](https://github.com/swordsteel/hlaeja-device-api)** to identify a device and accept data.
|
||||||
|
|
||||||
Generate an RSA private key, of size 2048, and output it to a file named `private_key.pem` in to `./keys`
|
*For instructions on how to set these up, please refer to our [generate RSA key](https://github.com/swordsteel/hlaeja-development/blob/master/doc/rsa_key.md) documentation.*
|
||||||
|
|
||||||
```shell
|
### Global Setting
|
||||||
openssl genrsa -out private_key.pem 2048
|
|
||||||
```
|
|
||||||
|
|
||||||
Extract the public key from `private_key.pem` from `./keys`, and output it to a file named `public_key.pem` in to `./keys`
|
The following global settings are used in Hlaeja Device Registry. You can configure these settings using either Gradle properties or alternatively environment variables.
|
||||||
|
|
||||||
```shell
|
*For instructions on how to set these up, please refer to our [set global settings](https://github.com/swordsteel/hlaeja-development/blob/master/doc/global_settings.md) documentation.*
|
||||||
openssl rsa -in private_key.pem -pubout -out public_key.pem
|
|
||||||
```
|
|
||||||
|
|
||||||
### Global gradle properties
|
#### Gradle Properties
|
||||||
|
|
||||||
To authenticate with Gradle to access repositories that require authentication, you can set your user and token in the `gradle.properties` file.
|
|
||||||
|
|
||||||
Here's how you can do it:
|
|
||||||
|
|
||||||
1. Open or create the `gradle.properties` file in your Gradle user home directory:
|
|
||||||
- On Unix-like systems (Linux, macOS), this directory is typically `~/.gradle/`.
|
|
||||||
- On Windows, this directory is typically `C:\Users\<YourUsername>\.gradle\`.
|
|
||||||
2. Add the following lines to the `gradle.properties` file:
|
|
||||||
```properties
|
```properties
|
||||||
repository.user=your_user
|
repository.user=your_user
|
||||||
repository.token=your_token_value
|
repository.token=your_token_value
|
||||||
```
|
```
|
||||||
or use environment variables `REPOSITORY_USER` and `REPOSITORY_TOKEN`
|
|
||||||
|
#### Environment Variables
|
||||||
|
|
||||||
|
```properties
|
||||||
|
REPOSITORY_USER=your_user
|
||||||
|
REPOSITORY_TOKEN=your_token_value
|
||||||
|
```
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
version=0.3.0-SNAPSHOT
|
version=0.3.0-SNAPSHOT
|
||||||
catalog=0.6.0
|
catalog=0.7.0-SNAPSHOT
|
||||||
container.port.host=9010
|
container.port.host=9010
|
||||||
|
|||||||
@@ -5,3 +5,6 @@ Content-Type: application/json
|
|||||||
{
|
{
|
||||||
"type": "00000000-0000-0000-0000-000000000000"
|
"type": "00000000-0000-0000-0000-000000000000"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
### register device for a type
|
||||||
|
GET {{hostname}}/device-00000000-0000-0000-0000-000000000000
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
package ltd.hlaeja.controller
|
package ltd.hlaeja.controller
|
||||||
|
|
||||||
|
import java.util.UUID
|
||||||
import ltd.hlaeja.library.deviceRegistry.Device
|
import ltd.hlaeja.library.deviceRegistry.Device
|
||||||
import ltd.hlaeja.service.DeviceService
|
import ltd.hlaeja.service.DeviceService
|
||||||
import ltd.hlaeja.service.JwtService
|
import ltd.hlaeja.service.JwtService
|
||||||
import ltd.hlaeja.util.toDeviceResponse
|
import ltd.hlaeja.util.toDeviceResponse
|
||||||
|
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.PostMapping
|
||||||
import org.springframework.web.bind.annotation.RequestBody
|
import org.springframework.web.bind.annotation.RequestBody
|
||||||
import org.springframework.web.bind.annotation.RestController
|
import org.springframework.web.bind.annotation.RestController
|
||||||
@@ -19,4 +22,10 @@ class DeviceController(
|
|||||||
@RequestBody request: Device.Request,
|
@RequestBody request: Device.Request,
|
||||||
): Device.Response = deviceService.addDevice(request.type)
|
): Device.Response = deviceService.addDevice(request.type)
|
||||||
.toDeviceResponse(jwtService)
|
.toDeviceResponse(jwtService)
|
||||||
|
|
||||||
|
@GetMapping("/device-{device}")
|
||||||
|
suspend fun getDevice(
|
||||||
|
@PathVariable device: UUID,
|
||||||
|
): Device.Response = deviceService.getDevice(device)
|
||||||
|
.toDeviceResponse(jwtService)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
package ltd.hlaeja.service
|
package ltd.hlaeja.service
|
||||||
|
|
||||||
|
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||||
import java.time.ZonedDateTime
|
import java.time.ZonedDateTime
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import ltd.hlaeja.entity.DeviceEntity
|
import ltd.hlaeja.entity.DeviceEntity
|
||||||
import ltd.hlaeja.repository.DeviceRepository
|
import ltd.hlaeja.repository.DeviceRepository
|
||||||
import mu.KotlinLogging
|
import org.springframework.http.HttpStatus.NOT_FOUND
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
|
import org.springframework.web.server.ResponseStatusException
|
||||||
|
|
||||||
private val log = KotlinLogging.logger {}
|
private val log = KotlinLogging.logger {}
|
||||||
|
|
||||||
@@ -18,4 +20,8 @@ class DeviceService(
|
|||||||
type: UUID,
|
type: UUID,
|
||||||
): DeviceEntity = deviceRepository.save(DeviceEntity(null, ZonedDateTime.now(), type))
|
): DeviceEntity = deviceRepository.save(DeviceEntity(null, ZonedDateTime.now(), type))
|
||||||
.also { log.debug { "Added device ${it.id}" } }
|
.also { log.debug { "Added device ${it.id}" } }
|
||||||
|
|
||||||
|
suspend fun getDevice(device: UUID): DeviceEntity = deviceRepository.findById(device)
|
||||||
|
?.also { log.debug { "Get device ${it.id}" } }
|
||||||
|
?: throw ResponseStatusException(NOT_FOUND)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package ltd.hlaeja.service
|
package ltd.hlaeja.service
|
||||||
|
|
||||||
|
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import ltd.hlaeja.entity.NodeEntity
|
import ltd.hlaeja.entity.NodeEntity
|
||||||
import ltd.hlaeja.repository.NodeRepository
|
import ltd.hlaeja.repository.NodeRepository
|
||||||
import mu.KotlinLogging
|
|
||||||
import org.springframework.http.HttpStatus.NOT_FOUND
|
import org.springframework.http.HttpStatus.NOT_FOUND
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
import org.springframework.web.server.ResponseStatusException
|
import org.springframework.web.server.ResponseStatusException
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package ltd.hlaeja.service
|
package ltd.hlaeja.service
|
||||||
|
|
||||||
|
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import ltd.hlaeja.entity.TypeEntity
|
import ltd.hlaeja.entity.TypeEntity
|
||||||
import ltd.hlaeja.repository.TypeRepository
|
import ltd.hlaeja.repository.TypeRepository
|
||||||
import mu.KotlinLogging
|
|
||||||
import org.springframework.dao.DuplicateKeyException
|
import org.springframework.dao.DuplicateKeyException
|
||||||
import org.springframework.http.HttpStatus
|
import org.springframework.http.HttpStatus
|
||||||
import org.springframework.stereotype.Service
|
import org.springframework.stereotype.Service
|
||||||
@@ -22,9 +22,9 @@ class TypeService(
|
|||||||
entity: TypeEntity,
|
entity: TypeEntity,
|
||||||
): TypeEntity = try {
|
): TypeEntity = try {
|
||||||
typeRepository.save(entity)
|
typeRepository.save(entity)
|
||||||
.also { log.debug("Added new type: {}", it.id) }
|
.also { log.debug { "Added new type: $it.id" } }
|
||||||
} catch (e: DuplicateKeyException) {
|
} catch (e: DuplicateKeyException) {
|
||||||
log.warn(e.localizedMessage)
|
log.warn { e.localizedMessage }
|
||||||
throw ResponseStatusException(HttpStatus.CONFLICT)
|
throw ResponseStatusException(HttpStatus.CONFLICT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import ltd.hlaeja.service.DeviceService
|
|||||||
import ltd.hlaeja.service.JwtService
|
import ltd.hlaeja.service.JwtService
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.BeforeEach
|
import org.junit.jupiter.api.BeforeEach
|
||||||
|
import org.junit.jupiter.api.Nested
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.assertThrows
|
import org.junit.jupiter.api.assertThrows
|
||||||
import org.springframework.web.server.ResponseStatusException
|
import org.springframework.web.server.ResponseStatusException
|
||||||
@@ -36,6 +37,9 @@ class DeviceControllerTest {
|
|||||||
controller = DeviceController(deviceService, jwtService)
|
controller = DeviceController(deviceService, jwtService)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
inner class AddDeviceTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `add device - success`() = runTest {
|
fun `add device - success`() = runTest {
|
||||||
// given
|
// given
|
||||||
@@ -68,3 +72,24 @@ class DeviceControllerTest {
|
|||||||
assertThat(exception.message).isEqualTo("417 EXPECTATION_FAILED")
|
assertThat(exception.message).isEqualTo("417 EXPECTATION_FAILED")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
inner class GetDeviceTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `get device - success`() = runTest {
|
||||||
|
// given
|
||||||
|
coEvery { deviceService.getDevice(any()) } returns DeviceEntity(uuid, timestamp, uuid)
|
||||||
|
coEvery { jwtService.makeIdentity(any()) } returns PAYLOAD
|
||||||
|
|
||||||
|
// when
|
||||||
|
val response = controller.getDevice(uuid)
|
||||||
|
|
||||||
|
// then
|
||||||
|
coVerify(exactly = 1) { deviceService.getDevice(any()) }
|
||||||
|
coVerify(exactly = 1) { jwtService.makeIdentity(any()) }
|
||||||
|
|
||||||
|
assertThat(response.identity).isEqualTo(PAYLOAD)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ import org.assertj.core.api.Assertions.assertThat
|
|||||||
import org.junit.jupiter.api.AfterEach
|
import org.junit.jupiter.api.AfterEach
|
||||||
import org.junit.jupiter.api.BeforeEach
|
import org.junit.jupiter.api.BeforeEach
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
|
import org.junit.jupiter.api.assertThrows
|
||||||
|
import org.springframework.web.server.ResponseStatusException
|
||||||
|
|
||||||
class DeviceServiceTest {
|
class DeviceServiceTest {
|
||||||
companion object {
|
companion object {
|
||||||
@@ -42,7 +44,7 @@ class DeviceServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `add new type success`() = runTest {
|
fun `add new device success`() = runTest {
|
||||||
// given
|
// given
|
||||||
coEvery { repository.save(any()) } answers { call ->
|
coEvery { repository.save(any()) } answers { call ->
|
||||||
(call.invocation.args[0] as DeviceEntity).copy(id = device)
|
(call.invocation.args[0] as DeviceEntity).copy(id = device)
|
||||||
@@ -58,4 +60,37 @@ class DeviceServiceTest {
|
|||||||
assertThat(result.timestamp.toString()).isEqualTo("2000-01-01T00:00:00.001Z[UTC]")
|
assertThat(result.timestamp.toString()).isEqualTo("2000-01-01T00:00:00.001Z[UTC]")
|
||||||
assertThat(result.type).isEqualTo(type)
|
assertThat(result.type).isEqualTo(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `get device - success`() = runTest {
|
||||||
|
// given
|
||||||
|
val device = UUID.fromString("00000000-0000-0000-0000-000000000000")
|
||||||
|
val entity: DeviceEntity = mockk()
|
||||||
|
|
||||||
|
coEvery { repository.findById(any()) } returns entity
|
||||||
|
coEvery { entity.id } returns device
|
||||||
|
|
||||||
|
// when
|
||||||
|
val result = service.getDevice(type)
|
||||||
|
|
||||||
|
// then
|
||||||
|
coVerify(exactly = 1) { repository.findById(any()) }
|
||||||
|
assertThat(result.id).isEqualTo(device)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `get device - fail not found`() = runTest {
|
||||||
|
// given
|
||||||
|
val device = UUID.fromString("00000000-0000-0000-0000-000000000000")
|
||||||
|
|
||||||
|
coEvery { repository.findById(any()) } returns null
|
||||||
|
|
||||||
|
// when
|
||||||
|
val exception = assertThrows<ResponseStatusException> {
|
||||||
|
service.getDevice(device)
|
||||||
|
}
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertThat(exception.message).isEqualTo("404 NOT_FOUND")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user