diff --git a/xesar-connect/src/main/kotlin/com/open200/xesar/connect/Topics.kt b/xesar-connect/src/main/kotlin/com/open200/xesar/connect/Topics.kt index 49f5958d..763ee31b 100644 --- a/xesar-connect/src/main/kotlin/com/open200/xesar/connect/Topics.kt +++ b/xesar-connect/src/main/kotlin/com/open200/xesar/connect/Topics.kt @@ -480,6 +480,10 @@ class Topics(vararg val topics: String) { /** MQTT topic string for the "ChangePersonMetadataValueMapi" command. */ val CHANGE_PERSON_METADATA_VALUE = "xs3/1/cmd/ChangePersonMetadataValueMapi" + + /** MQTT topic string for the "ChangeAuthorizationProfileMetadataValueMapi" command. */ + val CHANGE_AUTHORIZATION_PROFILE_METADATA_VALUE = + "xs3/1/cmd/ChangeAuthorizationProfileMetadataValueMapi" } } diff --git a/xesar-connect/src/main/kotlin/com/open200/xesar/connect/extension/XesarConnectAuthorizationProfileExt.kt b/xesar-connect/src/main/kotlin/com/open200/xesar/connect/extension/XesarConnectAuthorizationProfileExt.kt index fa92df0e..8553adc7 100644 --- a/xesar-connect/src/main/kotlin/com/open200/xesar/connect/extension/XesarConnectAuthorizationProfileExt.kt +++ b/xesar-connect/src/main/kotlin/com/open200/xesar/connect/extension/XesarConnectAuthorizationProfileExt.kt @@ -162,6 +162,38 @@ suspend fun XesarConnect.changeAuthorizationProfileAsync( ) } +/** + * Changes the value of custom data field of an authorization profile asynchronously. + * + * @param id The ID of the authorization profile + * @param metadataId The metadataID of the data field. + * @param value The new value of the field. + * @param requestConfig The request configuration (optional). + */ +suspend fun XesarConnect.changeAuthorizationProfileMetadataValueAsync( + id: UUID, + metadataId: UUID, + value: String, + requestConfig: XesarConnect.RequestConfig = buildRequestConfig(), +): SingleEventResult { + return sendCommandAsync< + ChangeAuthorizationProfileMetadataValueMapi, + AuthorizationProfileInfoChanged, + >( + Topics.Command.CHANGE_AUTHORIZATION_PROFILE_METADATA_VALUE, + Topics.Event.AUTHORIZATION_PROFILE_INFO_CHANGED, + true, + ChangeAuthorizationProfileMetadataValueMapi( + config.uuidGenerator.generateId(), + id, + metadataId, + value, + token, + ), + requestConfig, + ) +} + /** * Retrieves a cold stream of [AuthorizationProfile] objects, fetching them incrementally in * smaller,more manageable chunks rather than retrieving the entire dataset at once. Use diff --git a/xesar-connect/src/main/kotlin/com/open200/xesar/connect/messages/command/ChangeAuthorizationProfileMetadataValueMapi.kt b/xesar-connect/src/main/kotlin/com/open200/xesar/connect/messages/command/ChangeAuthorizationProfileMetadataValueMapi.kt new file mode 100644 index 00000000..a45b9696 --- /dev/null +++ b/xesar-connect/src/main/kotlin/com/open200/xesar/connect/messages/command/ChangeAuthorizationProfileMetadataValueMapi.kt @@ -0,0 +1,23 @@ +package com.open200.xesar.connect.messages.command + +import com.open200.xesar.connect.utils.UUIDSerializer +import java.util.* +import kotlinx.serialization.Serializable + +/** + * Represents a command POJO to change a custom data field value for an authorization profile. + * + * @param commandId The id of the command. + * @param id The id of the authorization profile. + * @param metadataId The id of the custom data field. + * @param value The new value of the custom data field. + * @param token The token of the command. + */ +@Serializable +data class ChangeAuthorizationProfileMetadataValueMapi( + override val commandId: @Serializable(with = UUIDSerializer::class) UUID, + val id: @Serializable(with = UUIDSerializer::class) UUID? = null, + val metadataId: @Serializable(with = UUIDSerializer::class) UUID, + val value: String, + val token: String, +) : Command diff --git a/xesar-connect/src/main/kotlin/com/open200/xesar/connect/messages/event/AuthorizationProfileInfoChanged.kt b/xesar-connect/src/main/kotlin/com/open200/xesar/connect/messages/event/AuthorizationProfileInfoChanged.kt index aa00ea9e..b6ddc322 100644 --- a/xesar-connect/src/main/kotlin/com/open200/xesar/connect/messages/event/AuthorizationProfileInfoChanged.kt +++ b/xesar-connect/src/main/kotlin/com/open200/xesar/connect/messages/event/AuthorizationProfileInfoChanged.kt @@ -1,5 +1,6 @@ package com.open200.xesar.connect.messages.event +import com.open200.xesar.connect.messages.EntityMetadata import com.open200.xesar.connect.utils.UUIDSerializer import java.util.* import kotlinx.serialization.Serializable @@ -11,10 +12,13 @@ import kotlinx.serialization.Serializable * @param name The name of the authorization profile. * @param description The description of the authorization profile. * @param id The id of the authorization profile. + * @param entityMetadata Contains the information for all defined custom data fields for the + * authorization profile. */ @Serializable data class AuthorizationProfileInfoChanged( val name: String? = null, val description: String? = null, val id: @Serializable(with = UUIDSerializer::class) UUID? = null, + val entityMetadata: List? = null, ) : Event diff --git a/xesar-connect/src/main/kotlin/com/open200/xesar/connect/messages/query/AuthorizationProfile.kt b/xesar-connect/src/main/kotlin/com/open200/xesar/connect/messages/query/AuthorizationProfile.kt index 23558550..34c5ceca 100644 --- a/xesar-connect/src/main/kotlin/com/open200/xesar/connect/messages/query/AuthorizationProfile.kt +++ b/xesar-connect/src/main/kotlin/com/open200/xesar/connect/messages/query/AuthorizationProfile.kt @@ -1,5 +1,6 @@ package com.open200.xesar.connect.messages.query +import com.open200.xesar.connect.messages.EntityMetadata import com.open200.xesar.connect.utils.UUIDSerializer import java.util.* import kotlinx.serialization.Serializable @@ -17,6 +18,8 @@ import kotlinx.serialization.Serializable * @param anyAuthorizations Indicates if the authorization profile allows any authorizations. * @param standardTimeProfile The used standard time profile id or null for an all-day time profile. * (optional). + * @param entityMetadata Contains the information for all defined custom data fields for the + * authorization profile. */ @Serializable data class AuthorizationProfile( @@ -28,6 +31,7 @@ data class AuthorizationProfile( val manualOfficeMode: Boolean, val anyAuthorizations: Boolean, @Serializable(with = UUIDSerializer::class) val standardTimeProfile: UUID? = null, + val entityMetadata: List? = null, ) : QueryListResource, QueryElementResource { /** diff --git a/xesar-connect/src/test/kotlin/com/open200/xesar/connect/encodingDecoding/query/AuthorizationProfileElementTest.kt b/xesar-connect/src/test/kotlin/com/open200/xesar/connect/encodingDecoding/query/AuthorizationProfileElementTest.kt index 59f26206..53bba639 100644 --- a/xesar-connect/src/test/kotlin/com/open200/xesar/connect/encodingDecoding/query/AuthorizationProfileElementTest.kt +++ b/xesar-connect/src/test/kotlin/com/open200/xesar/connect/encodingDecoding/query/AuthorizationProfileElementTest.kt @@ -32,7 +32,8 @@ class AuthorizationProfileElementTest : "\"timeProfileId\":\"532534ef-d5aa-4cca-acfb-e558c623b00a\"}]," + "\"manualOfficeMode\":true," + "\"anyAuthorizations\":true," + - "\"standardTimeProfile\":\"a58e45f8-7bff-4b3a-bd0e-a831b3fa8053\"}}" + "\"standardTimeProfile\":\"a58e45f8-7bff-4b3a-bd0e-a831b3fa8053\"," + + "\"entityMetadata\":[{\"id\":\"123e4567-e89b-12d3-a456-426614174000\",\"name\":\"type\",\"value\":\"authorization type 1\"},{\"id\":\"0f8fad5b-d9cb-469f-a165-70867728950e\",\"name\":\"number\",\"value\":null}]}}" test("encoding QueryListElement for an authorization profile") { val authorizationProfileEncoded = encodeQueryElement(authorizationProfileTest) diff --git a/xesar-connect/src/test/kotlin/com/open200/xesar/connect/encodingDecoding/query/AuthorizationProfileListTest.kt b/xesar-connect/src/test/kotlin/com/open200/xesar/connect/encodingDecoding/query/AuthorizationProfileListTest.kt index c159809f..1f6dd502 100644 --- a/xesar-connect/src/test/kotlin/com/open200/xesar/connect/encodingDecoding/query/AuthorizationProfileListTest.kt +++ b/xesar-connect/src/test/kotlin/com/open200/xesar/connect/encodingDecoding/query/AuthorizationProfileListTest.kt @@ -45,7 +45,8 @@ class AuthorizationProfileListTest : "\"timeProfileId\":\"532534ef-d5aa-4cca-acfb-e558c623b00a\"}]," + "\"manualOfficeMode\":true," + "\"anyAuthorizations\":true," + - "\"standardTimeProfile\":\"a58e45f8-7bff-4b3a-bd0e-a831b3fa8053\"}," + + "\"standardTimeProfile\":\"a58e45f8-7bff-4b3a-bd0e-a831b3fa8053\"," + + "\"entityMetadata\":[{\"id\":\"123e4567-e89b-12d3-a456-426614174000\",\"name\":\"type\",\"value\":\"authorization type 1\"},{\"id\":\"0f8fad5b-d9cb-469f-a165-70867728950e\",\"name\":\"number\",\"value\":null}]}," + "{\"id\":\"555e7d1a-54f1-432a-ade7-80d20a63ee2d\"," + "\"name\":\"authorization profile 2 String\"," + "\"description\":\"description profile 2 String\"," + @@ -53,7 +54,8 @@ class AuthorizationProfileListTest : "\"zones\":[]," + "\"manualOfficeMode\":true," + "\"anyAuthorizations\":true," + - "\"standardTimeProfile\":\"a58e45f8-7bff-4b3a-bd0e-a831b3fa8053\"}]," + + "\"standardTimeProfile\":\"a58e45f8-7bff-4b3a-bd0e-a831b3fa8053\"," + + "\"entityMetadata\":[{\"id\":\"123e4567-e89b-12d3-a456-426614174000\",\"name\":\"type\",\"value\":\"authorization type 1\"},{\"id\":\"0f8fad5b-d9cb-469f-a165-70867728950e\",\"name\":\"number\",\"value\":null}]}]," + "\"totalCount\":2," + "\"filterCount\":2}}" diff --git a/xesar-connect/src/test/kotlin/com/open200/xesar/connect/it/command/ChangeAuthorizationProfileMetadataValueTest.kt b/xesar-connect/src/test/kotlin/com/open200/xesar/connect/it/command/ChangeAuthorizationProfileMetadataValueTest.kt new file mode 100644 index 00000000..cc413a01 --- /dev/null +++ b/xesar-connect/src/test/kotlin/com/open200/xesar/connect/it/command/ChangeAuthorizationProfileMetadataValueTest.kt @@ -0,0 +1,106 @@ +package com.open200.xesar.connect.it.command + +import com.open200.xesar.connect.Topics +import com.open200.xesar.connect.XesarConnect +import com.open200.xesar.connect.XesarMqttClient +import com.open200.xesar.connect.extension.changeAuthorizationProfileMetadataValueAsync +import com.open200.xesar.connect.it.MosquittoContainer +import com.open200.xesar.connect.messages.EntityMetadata +import com.open200.xesar.connect.messages.event.ApiEvent +import com.open200.xesar.connect.messages.event.AuthorizationProfileInfoChanged +import com.open200.xesar.connect.messages.event.encodeEvent +import io.kotest.common.runBlocking +import io.kotest.core.spec.style.FunSpec +import io.kotest.extensions.testcontainers.perProject +import io.kotest.matchers.equals.shouldBeEqual +import io.mockk.coEvery +import java.util.* +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.launch + +class ChangeAuthorizationProfileMetadataValueTest : + FunSpec({ + val container = MosquittoContainer.container() + val config = MosquittoContainer.config(container) + listener(container.perProject()) + + test("change authorization profile metadata value") { + coEvery { config.uuidGenerator.generateId() } + .returns(UUID.fromString("00000000-1281-40ae-89d7-5c541d77a757")) + + val authorizationProfileId = UUID.fromString("11111111-2222-3333-4444-555555555555") + val metadataId = UUID.fromString("aaaaaaaa-0000-0000-0000-000000000001") + + runBlocking { + val simulatedBackendReady = CompletableDeferred() + val commandReceived = CompletableDeferred() + + launch { + XesarMqttClient.connectAsync(config).await().use { client -> + client.subscribeAsync(arrayOf(Topics.ALL_TOPICS)).await() + + client.onMessage = { topic, payload -> + when (topic) { + Topics.Command.CHANGE_AUTHORIZATION_PROFILE_METADATA_VALUE -> { + commandReceived.complete(payload.decodeToString()) + } + } + } + + simulatedBackendReady.complete(Unit) + + val commandContent = commandReceived.await() + + commandContent.shouldBeEqual( + "{\"commandId\":\"00000000-1281-40ae-89d7-5c541d77a757\",\"id\":\"11111111-2222-3333-4444-555555555555\",\"metadataId\":\"aaaaaaaa-0000-0000-0000-000000000001\",\"value\":\"Test Value\",\"token\":\"JDJhJDEwJDFSNEljZ2FaRUNXUXBTQ25XN05KbE9qRzFHQ1VjMzkvWTBVcFpZb1M4Vmt0dnJYZ0tJVFBx\"}" + ) + + val apiEvent = + ApiEvent( + UUID.fromString("00000000-1281-40ae-89d7-5c541d77a757"), + AuthorizationProfileInfoChanged( + id = authorizationProfileId, + entityMetadata = + listOf( + EntityMetadata( + id = metadataId, + name = "test", + value = "Test Value", + ) + ), + ), + ) + + client + .publishAsync( + Topics.Event.AUTHORIZATION_PROFILE_INFO_CHANGED, + encodeEvent(apiEvent), + ) + .await() + } + } + + launch { + simulatedBackendReady.await() + + val api = XesarConnect.connectAndLoginAsync(config).await() + api.subscribeAsync(Topics(Topics.Event.AUTHORIZATION_PROFILE_INFO_CHANGED)) + .await() + + val result = + api.changeAuthorizationProfileMetadataValueAsync( + id = authorizationProfileId, + metadataId = metadataId, + value = "Test Value", + ) + .await() + + result.id?.shouldBeEqual(authorizationProfileId) + result.entityMetadata!! + .single { it.id == metadataId } + .value + ?.shouldBeEqual("Test Value") + } + } + } + }) diff --git a/xesar-connect/src/test/kotlin/com/open200/xesar/connect/util/fixture/AuthorizationProfileFixture.kt b/xesar-connect/src/test/kotlin/com/open200/xesar/connect/util/fixture/AuthorizationProfileFixture.kt index 8ab63a46..fc75df45 100644 --- a/xesar-connect/src/test/kotlin/com/open200/xesar/connect/util/fixture/AuthorizationProfileFixture.kt +++ b/xesar-connect/src/test/kotlin/com/open200/xesar/connect/util/fixture/AuthorizationProfileFixture.kt @@ -1,5 +1,6 @@ package com.open200.xesar.connect.util.fixture +import com.open200.xesar.connect.messages.EntityMetadata import com.open200.xesar.connect.messages.query.AuthorizationProfile import java.util.* @@ -27,5 +28,18 @@ object AuthorizationProfileFixture { manualOfficeMode = true, anyAuthorizations = true, standardTimeProfile = UUID.fromString("a58e45f8-7bff-4b3a-bd0e-a831b3fa8053"), + entityMetadata = + listOf( + EntityMetadata( + id = UUID.fromString("123e4567-e89b-12d3-a456-426614174000"), + name = "type", + value = "authorization type 1", + ), + EntityMetadata( + id = UUID.fromString("0f8fad5b-d9cb-469f-a165-70867728950e"), + name = "number", + value = null, + ), + ), ) }