github.com/livekit/protocol@v1.16.1-0.20240517185851-47e4c6bba773/auth/grants.go (about)

     1  // Copyright 2023 LiveKit, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package auth
    16  
    17  import (
    18  	"strings"
    19  
    20  	"golang.org/x/exp/slices"
    21  
    22  	"github.com/livekit/protocol/livekit"
    23  )
    24  
    25  type VideoGrant struct {
    26  	// actions on rooms
    27  	RoomCreate bool `json:"roomCreate,omitempty"`
    28  	RoomList   bool `json:"roomList,omitempty"`
    29  	RoomRecord bool `json:"roomRecord,omitempty"`
    30  
    31  	// actions on a particular room
    32  	RoomAdmin bool   `json:"roomAdmin,omitempty"`
    33  	RoomJoin  bool   `json:"roomJoin,omitempty"`
    34  	Room      string `json:"room,omitempty"`
    35  
    36  	// permissions within a room, if none of the permissions are set explicitly
    37  	// it will be granted with all publish and subscribe permissions
    38  	CanPublish     *bool `json:"canPublish,omitempty"`
    39  	CanSubscribe   *bool `json:"canSubscribe,omitempty"`
    40  	CanPublishData *bool `json:"canPublishData,omitempty"`
    41  	// TrackSource types that a participant may publish.
    42  	// When set, it supersedes CanPublish. Only sources explicitly set here can be published
    43  	CanPublishSources []string `json:"canPublishSources,omitempty"` // keys keep track of each source
    44  	// by default, a participant is not allowed to update its own metadata
    45  	CanUpdateOwnMetadata *bool `json:"canUpdateOwnMetadata,omitempty"`
    46  
    47  	// actions on ingresses
    48  	IngressAdmin bool `json:"ingressAdmin,omitempty"` // applies to all ingress
    49  
    50  	// participant is not visible to other participants
    51  	Hidden bool `json:"hidden,omitempty"`
    52  	// indicates to the room that current participant is a recorder
    53  	Recorder bool `json:"recorder,omitempty"`
    54  	// indicates that the holder can register as an Agent framework worker
    55  	// it is also set on all participants that are joining as Agent
    56  	Agent bool `json:"agent,omitempty"`
    57  }
    58  
    59  type ClaimGrants struct {
    60  	Identity string      `json:"-"`
    61  	Name     string      `json:"name,omitempty"`
    62  	Kind     string      `json:"kind,omitempty"`
    63  	Video    *VideoGrant `json:"video,omitempty"`
    64  	// for verifying integrity of the message body
    65  	Sha256   string `json:"sha256,omitempty"`
    66  	Metadata string `json:"metadata,omitempty"`
    67  }
    68  
    69  func (c *ClaimGrants) SetParticipantKind(kind livekit.ParticipantInfo_Kind) {
    70  	c.Kind = kindFromProto(kind)
    71  }
    72  
    73  func (c *ClaimGrants) GetParticipantKind() livekit.ParticipantInfo_Kind {
    74  	return kindToProto(c.Kind)
    75  }
    76  
    77  func (c *ClaimGrants) Clone() *ClaimGrants {
    78  	if c == nil {
    79  		return nil
    80  	}
    81  
    82  	clone := *c
    83  	clone.Video = c.Video.Clone()
    84  
    85  	return &clone
    86  }
    87  
    88  func (v *VideoGrant) SetCanPublish(val bool) {
    89  	v.CanPublish = &val
    90  }
    91  
    92  func (v *VideoGrant) SetCanPublishData(val bool) {
    93  	v.CanPublishData = &val
    94  }
    95  
    96  func (v *VideoGrant) SetCanSubscribe(val bool) {
    97  	v.CanSubscribe = &val
    98  }
    99  
   100  func (v *VideoGrant) SetCanPublishSources(sources []livekit.TrackSource) {
   101  	v.CanPublishSources = make([]string, 0, len(sources))
   102  	for _, s := range sources {
   103  		v.CanPublishSources = append(v.CanPublishSources, sourceToString(s))
   104  	}
   105  }
   106  
   107  func (v *VideoGrant) SetCanUpdateOwnMetadata(val bool) {
   108  	v.CanUpdateOwnMetadata = &val
   109  }
   110  
   111  func (v *VideoGrant) GetCanPublish() bool {
   112  	if v.CanPublish == nil {
   113  		return true
   114  	}
   115  	return *v.CanPublish
   116  }
   117  
   118  func (v *VideoGrant) GetCanPublishSource(source livekit.TrackSource) bool {
   119  	if !v.GetCanPublish() {
   120  		return false
   121  	}
   122  	// don't differentiate between nil and unset, since that distinction doesn't survive serialization
   123  	if len(v.CanPublishSources) == 0 {
   124  		return true
   125  	}
   126  	sourceStr := sourceToString(source)
   127  	for _, s := range v.CanPublishSources {
   128  		if s == sourceStr {
   129  			return true
   130  		}
   131  	}
   132  	return false
   133  }
   134  
   135  func (v *VideoGrant) GetCanPublishSources() []livekit.TrackSource {
   136  	if len(v.CanPublishSources) == 0 {
   137  		return nil
   138  	}
   139  
   140  	sources := make([]livekit.TrackSource, 0, len(v.CanPublishSources))
   141  	for _, s := range v.CanPublishSources {
   142  		sources = append(sources, sourceToProto(s))
   143  	}
   144  	return sources
   145  }
   146  
   147  func (v *VideoGrant) GetCanPublishData() bool {
   148  	if v.CanPublishData == nil {
   149  		return v.GetCanPublish()
   150  	}
   151  	return *v.CanPublishData
   152  }
   153  
   154  func (v *VideoGrant) GetCanSubscribe() bool {
   155  	if v.CanSubscribe == nil {
   156  		return true
   157  	}
   158  	return *v.CanSubscribe
   159  }
   160  
   161  func (v *VideoGrant) GetCanUpdateOwnMetadata() bool {
   162  	if v.CanUpdateOwnMetadata == nil {
   163  		return false
   164  	}
   165  	return *v.CanUpdateOwnMetadata
   166  }
   167  
   168  func (v *VideoGrant) MatchesPermission(permission *livekit.ParticipantPermission) bool {
   169  	if permission == nil {
   170  		return false
   171  	}
   172  
   173  	if v.GetCanPublish() != permission.CanPublish {
   174  		return false
   175  	}
   176  	if v.GetCanPublishData() != permission.CanPublishData {
   177  		return false
   178  	}
   179  	if v.GetCanSubscribe() != permission.CanSubscribe {
   180  		return false
   181  	}
   182  	if v.GetCanUpdateOwnMetadata() != permission.CanUpdateMetadata {
   183  		return false
   184  	}
   185  	if v.Hidden != permission.Hidden {
   186  		return false
   187  	}
   188  	if v.Recorder != permission.Recorder {
   189  		return false
   190  	}
   191  	if v.Agent != permission.Agent {
   192  		return false
   193  	}
   194  	if !slices.Equal(v.GetCanPublishSources(), permission.CanPublishSources) {
   195  		return false
   196  	}
   197  
   198  	return true
   199  }
   200  
   201  func (v *VideoGrant) UpdateFromPermission(permission *livekit.ParticipantPermission) {
   202  	if permission == nil {
   203  		return
   204  	}
   205  
   206  	v.SetCanPublish(permission.CanPublish)
   207  	v.SetCanPublishData(permission.CanPublishData)
   208  	v.SetCanPublishSources(permission.CanPublishSources)
   209  	v.SetCanSubscribe(permission.CanSubscribe)
   210  	v.SetCanUpdateOwnMetadata(permission.CanUpdateMetadata)
   211  	v.Hidden = permission.Hidden
   212  	v.Recorder = permission.Recorder
   213  	v.Agent = permission.Agent
   214  }
   215  
   216  func (v *VideoGrant) ToPermission() *livekit.ParticipantPermission {
   217  	pp := &livekit.ParticipantPermission{
   218  		CanPublish:        v.GetCanPublish(),
   219  		CanPublishData:    v.GetCanPublishData(),
   220  		CanSubscribe:      v.GetCanSubscribe(),
   221  		CanPublishSources: v.GetCanPublishSources(),
   222  		CanUpdateMetadata: v.GetCanUpdateOwnMetadata(),
   223  		Hidden:            v.Hidden,
   224  		Recorder:          v.Recorder,
   225  		Agent:             v.Agent,
   226  	}
   227  	return pp
   228  }
   229  
   230  func (v *VideoGrant) Clone() *VideoGrant {
   231  	if v == nil {
   232  		return nil
   233  	}
   234  
   235  	clone := *v
   236  
   237  	if v.CanPublish != nil {
   238  		canPublish := *v.CanPublish
   239  		clone.CanPublish = &canPublish
   240  	}
   241  
   242  	if v.CanSubscribe != nil {
   243  		canSubscribe := *v.CanSubscribe
   244  		clone.CanSubscribe = &canSubscribe
   245  	}
   246  
   247  	if v.CanPublishData != nil {
   248  		canPublishData := *v.CanPublishData
   249  		clone.CanPublishData = &canPublishData
   250  	}
   251  
   252  	if v.CanPublishSources != nil {
   253  		clone.CanPublishSources = make([]string, len(v.CanPublishSources))
   254  		copy(clone.CanPublishSources, v.CanPublishSources)
   255  	}
   256  
   257  	if v.CanUpdateOwnMetadata != nil {
   258  		canUpdateOwnMetadata := *v.CanUpdateOwnMetadata
   259  		clone.CanUpdateOwnMetadata = &canUpdateOwnMetadata
   260  	}
   261  
   262  	return &clone
   263  }
   264  
   265  func sourceToString(source livekit.TrackSource) string {
   266  	return strings.ToLower(source.String())
   267  }
   268  
   269  func sourceToProto(sourceStr string) livekit.TrackSource {
   270  	switch sourceStr {
   271  	case "camera":
   272  		return livekit.TrackSource_CAMERA
   273  	case "microphone":
   274  		return livekit.TrackSource_MICROPHONE
   275  	case "screen_share":
   276  		return livekit.TrackSource_SCREEN_SHARE
   277  	case "screen_share_audio":
   278  		return livekit.TrackSource_SCREEN_SHARE_AUDIO
   279  	default:
   280  		return livekit.TrackSource_UNKNOWN
   281  	}
   282  }
   283  
   284  func kindFromProto(source livekit.ParticipantInfo_Kind) string {
   285  	return strings.ToLower(source.String())
   286  }
   287  
   288  func kindToProto(sourceStr string) livekit.ParticipantInfo_Kind {
   289  	switch sourceStr {
   290  	case "", "standard":
   291  		return livekit.ParticipantInfo_STANDARD
   292  	case "ingress":
   293  		return livekit.ParticipantInfo_INGRESS
   294  	case "egress":
   295  		return livekit.ParticipantInfo_EGRESS
   296  	case "sip":
   297  		return livekit.ParticipantInfo_SIP
   298  	case "agent":
   299  		return livekit.ParticipantInfo_AGENT
   300  	default:
   301  		return livekit.ParticipantInfo_STANDARD
   302  	}
   303  }