From c893a050650aefe9d867acec768616e539454c17 Mon Sep 17 00:00:00 2001 From: davidliu Date: Thu, 20 Jun 2024 14:30:26 +0900 Subject: [PATCH 1/4] Bump version to 0.6.2-SNAPSHOT --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 67d1432..fc00265 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ kotlin.code.style=official ############################################################### GROUP=io.livekit -VERSION_NAME=0.6.1 +VERSION_NAME=0.6.2-SNAPSHOT POM_NAME=LiveKit Server SDK POM_ARTIFACT_ID=livekit-server From 5d67c390e10baa476d85c3674bafeedb7aaa4ec9 Mon Sep 17 00:00:00 2001 From: davidliu Date: Sun, 28 Jul 2024 17:44:40 +0900 Subject: [PATCH 2/4] Add sip grants and attributes support to access tokens (#69) --- .../kotlin/io/livekit/server/AccessToken.kt | 45 ++++++++++++++++++- src/main/kotlin/io/livekit/server/SIPGrant.kt | 31 +++++++++++++ .../kotlin/io/livekit/server/VideoGrant.kt | 5 +++ .../io/livekit/server/AccessTokenTest.kt | 9 +++- 4 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 src/main/kotlin/io/livekit/server/SIPGrant.kt diff --git a/src/main/kotlin/io/livekit/server/AccessToken.kt b/src/main/kotlin/io/livekit/server/AccessToken.kt index 0253a34..0d66efa 100644 --- a/src/main/kotlin/io/livekit/server/AccessToken.kt +++ b/src/main/kotlin/io/livekit/server/AccessToken.kt @@ -20,7 +20,7 @@ import com.auth0.jwt.JWT import com.auth0.jwt.JWTCreator import com.auth0.jwt.algorithms.Algorithm import java.time.Instant -import java.util.* +import java.util.Date import java.util.concurrent.TimeUnit /** @@ -36,6 +36,7 @@ class AccessToken( private val secret: String ) { private val videoGrants = mutableSetOf() + private val sipGrants = mutableSetOf() /** * Amount of time in milliseconds the created token is valid for. @@ -78,6 +79,11 @@ class AccessToken( */ var sha256: String? = null + /** + * Key/value attributes to attach to the participant + */ + val attributes = mutableMapOf() + /** * Add [VideoGrant] to this token. */ @@ -96,10 +102,38 @@ class AccessToken( } } + /** + * Clear all previously added [VideoGrant]s. + */ fun clearGrants() { videoGrants.clear() } + /** + * Add [VideoGrant] to this token. + */ + fun addSIPGrants(vararg grants: SIPGrant) { + for (grant in grants) { + sipGrants.add(grant) + } + } + + /** + * Add [VideoGrant] to this token. + */ + fun addSIPGrants(grants: Iterable) { + for (grant in grants) { + sipGrants.add(grant) + } + } + + /** + * Clear all previously added [SIPGrant]s. + */ + fun clearSIPGrants() { + sipGrants.clear() + } + fun toJwt(): String { return with(JWT.create()) { withIssuer(apiKey) @@ -127,13 +161,20 @@ class AccessToken( } val claimsMap = mutableMapOf() val videoGrantsMap = videoGrants.associate { grant -> grant.toPair() } + val sipGrantsMap = sipGrants.associate { grant -> grant.toPair() } name?.let { claimsMap["name"] = it } metadata?.let { claimsMap["metadata"] = it } sha256?.let { claimsMap["sha256"] = it } + attributes.toMap().let { attributesCopy -> + if (attributesCopy.isNotEmpty()) { + claimsMap["attributes"] = attributesCopy + } + } claimsMap["video"] = videoGrantsMap + claimsMap["sip"] = sipGrantsMap - claimsMap.forEach { key, value -> + claimsMap.forEach { (key, value) -> withClaimAny(key, value) } diff --git a/src/main/kotlin/io/livekit/server/SIPGrant.kt b/src/main/kotlin/io/livekit/server/SIPGrant.kt new file mode 100644 index 0000000..b169316 --- /dev/null +++ b/src/main/kotlin/io/livekit/server/SIPGrant.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2024 LiveKit, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.livekit.server + +/** + * @link https://docs.livekit.io/guides/access-tokens/#video-grant + */ +sealed class SIPGrant(val key: String, val value: Any) { + fun toPair() = key to value +} + + +/** Can manage sip resources */ +class SIPAdmin(value: Boolean) : SIPGrant("admin", value) + +/** Can make outbound calls */ +class SIPCall(value: Boolean) : SIPGrant("call", value) \ No newline at end of file diff --git a/src/main/kotlin/io/livekit/server/VideoGrant.kt b/src/main/kotlin/io/livekit/server/VideoGrant.kt index ea095d6..43515ff 100644 --- a/src/main/kotlin/io/livekit/server/VideoGrant.kt +++ b/src/main/kotlin/io/livekit/server/VideoGrant.kt @@ -109,3 +109,8 @@ class Hidden(value: Boolean) : VideoGrant("hidden", value) * indicates this participant is recording the room */ class Recorder(value: Boolean) : VideoGrant("recorder", value) + +/** + * indicates this participant is allowed to connect to LiveKit as an Agent Framework worker + */ +class Agent(value: Boolean) : VideoGrant("agent", value) \ No newline at end of file diff --git a/src/test/kotlin/io/livekit/server/AccessTokenTest.kt b/src/test/kotlin/io/livekit/server/AccessTokenTest.kt index 243de70..d5a7c86 100644 --- a/src/test/kotlin/io/livekit/server/AccessTokenTest.kt +++ b/src/test/kotlin/io/livekit/server/AccessTokenTest.kt @@ -19,7 +19,7 @@ package io.livekit.server import com.auth0.jwt.JWT import com.auth0.jwt.algorithms.Algorithm import org.junit.jupiter.api.Test -import java.util.* +import java.util.Date import kotlin.test.assertEquals import kotlin.test.assertNotNull @@ -39,9 +39,11 @@ class AccessTokenTest { token.identity = "identity" token.metadata = "metadata" token.sha256 = "gfedcba" + token.attributes["key"] = "value" token.addGrants(RoomName("room_name")) token.addGrants(CanPublishSources(listOf("camera", "microphone"))) + token.addSIPGrants(SIPAdmin(true)) val jwt = token.toJwt() @@ -59,10 +61,15 @@ class AccessTokenTest { assertEquals(token.metadata, claims["metadata"]?.asString()) assertEquals(token.sha256, claims["sha256"]?.asString()) assertEquals(token.expiration, decodedJWT.expiresAt) + assertEquals(token.attributes["key"], claims["attributes"]?.asMap()?.get("key")) val videoGrants = claims["video"]?.asMap() assertNotNull(videoGrants) assertEquals("room_name", videoGrants["room"]) assertEquals(listOf("camera", "microphone"), videoGrants["canPublishSources"]) + + val sipGrants = claims["sip"]?.asMap() + assertNotNull(sipGrants) + assertEquals(true, sipGrants["admin"]) } } From bbe5da2303750db23ef25f734e4ca047b5699cd8 Mon Sep 17 00:00:00 2001 From: davidliu Date: Sun, 28 Jul 2024 17:54:40 +0900 Subject: [PATCH 3/4] Change signatures to return Call (#70) Allows usage of Call.await() --- src/main/kotlin/io/livekit/server/RoomService.kt | 8 ++++---- src/main/kotlin/io/livekit/server/RoomServiceClient.kt | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/io/livekit/server/RoomService.kt b/src/main/kotlin/io/livekit/server/RoomService.kt index 245e9a4..924e204 100644 --- a/src/main/kotlin/io/livekit/server/RoomService.kt +++ b/src/main/kotlin/io/livekit/server/RoomService.kt @@ -41,7 +41,7 @@ interface RoomService { @Headers("Content-Type: application/protobuf") @POST("/twirp/livekit.RoomService/DeleteRoom") - fun deleteRoom(@Body request: LivekitRoom.DeleteRoomRequest, @Header("Authorization") authorization: String): Call + fun deleteRoom(@Body request: LivekitRoom.DeleteRoomRequest, @Header("Authorization") authorization: String): Call @Headers("Content-Type: application/protobuf") @POST("/twirp/livekit.RoomService/UpdateRoomMetadata") @@ -66,7 +66,7 @@ interface RoomService { @Headers("Content-Type: application/protobuf") @POST("/twirp/livekit.RoomService/RemoveParticipant") - fun removeParticipant(@Body request: LivekitRoom.RoomParticipantIdentity, @Header("Authorization") authorization: String): Call + fun removeParticipant(@Body request: LivekitRoom.RoomParticipantIdentity, @Header("Authorization") authorization: String): Call @Headers("Content-Type: application/protobuf") @POST("/twirp/livekit.RoomService/MutePublishedTrack") @@ -87,9 +87,9 @@ interface RoomService { fun updateSubscriptions( @Body request: LivekitRoom.UpdateSubscriptionsRequest, @Header("Authorization") authorization: String - ): Call + ): Call @Headers("Content-Type: application/protobuf") @POST("/twirp/livekit.RoomService/SendData") - fun sendData(@Body request: LivekitRoom.SendDataRequest, @Header("Authorization") authorization: String): Call + fun sendData(@Body request: LivekitRoom.SendDataRequest, @Header("Authorization") authorization: String): Call } diff --git a/src/main/kotlin/io/livekit/server/RoomServiceClient.kt b/src/main/kotlin/io/livekit/server/RoomServiceClient.kt index 151b1d2..78b4391 100644 --- a/src/main/kotlin/io/livekit/server/RoomServiceClient.kt +++ b/src/main/kotlin/io/livekit/server/RoomServiceClient.kt @@ -103,7 +103,7 @@ class RoomServiceClient( } } - fun deleteRoom(roomName: String): Call { + fun deleteRoom(roomName: String): Call { val request = LivekitRoom.DeleteRoomRequest.newBuilder() .setRoom(roomName) .build() @@ -170,7 +170,7 @@ class RoomServiceClient( * @param roomName * @param identity */ - fun removeParticipant(roomName: String, identity: String): Call { + fun removeParticipant(roomName: String, identity: String): Call { val request = LivekitRoom.RoomParticipantIdentity.newBuilder() .setRoom(roomName) .setIdentity(identity) @@ -260,7 +260,7 @@ class RoomServiceClient( identity: String, trackSids: List, subscribe: Boolean, - ): Call { + ): Call { val request = with(LivekitRoom.UpdateSubscriptionsRequest.newBuilder()) { this.room = roomName this.identity = identity @@ -291,7 +291,7 @@ class RoomServiceClient( destinationSids: List = emptyList(), destinationIdentities: List = emptyList(), topic: String? = null, - ): Call { + ): Call { val request = with(LivekitRoom.SendDataRequest.newBuilder()) { this.room = roomName this.data = ByteString.copyFrom(data) From d973353cc3e253531872de916343c98b36e2b666 Mon Sep 17 00:00:00 2001 From: davidliu Date: Sun, 28 Jul 2024 17:55:28 +0900 Subject: [PATCH 4/4] v0.6.2 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index fc00265..16959dd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ kotlin.code.style=official ############################################################### GROUP=io.livekit -VERSION_NAME=0.6.2-SNAPSHOT +VERSION_NAME=0.6.2 POM_NAME=LiveKit Server SDK POM_ARTIFACT_ID=livekit-server