github.com/whoyao/protocol@v0.0.0-20230519045905-2d8ace718ca5/auth/grants.go (about)

     1  package auth
     2  
     3  import (
     4  	"strings"
     5  
     6  	"golang.org/x/exp/slices"
     7  
     8  	"github.com/whoyao/protocol/livekit"
     9  )
    10  
    11  type VideoGrant struct {
    12  	// actions on rooms
    13  	RoomCreate bool `json:"roomCreate,omitempty"`
    14  	RoomList   bool `json:"roomList,omitempty"`
    15  	RoomRecord bool `json:"roomRecord,omitempty"`
    16  
    17  	// actions on a particular room
    18  	RoomAdmin bool   `json:"roomAdmin,omitempty"`
    19  	RoomJoin  bool   `json:"roomJoin,omitempty"`
    20  	Room      string `json:"room,omitempty"`
    21  
    22  	// permissions within a room, if none of the permissions are set explicitly
    23  	// it will be granted with all publish and subscribe permissions
    24  	CanPublish     *bool `json:"canPublish,omitempty"`
    25  	CanSubscribe   *bool `json:"canSubscribe,omitempty"`
    26  	CanPublishData *bool `json:"canPublishData,omitempty"`
    27  	// TrackSource types that a participant may publish.
    28  	// When set, it supersedes CanPublish. Only sources explicitly set here can be published
    29  	CanPublishSources []string `json:"canPublishSources,omitempty"` // keys keep track of each source
    30  	// by default, a participant is not allowed to update its own metadata
    31  	CanUpdateOwnMetadata *bool `json:"canUpdateOwnMetadata,omitempty"`
    32  
    33  	// actions on ingresses
    34  	IngressAdmin bool `json:"ingressAdmin,omitempty"` // applies to all ingress
    35  
    36  	// participant is not visible to other participants
    37  	Hidden bool `json:"hidden,omitempty"`
    38  	// indicates to the room that current participant is a recorder
    39  	Recorder bool `json:"recorder,omitempty"`
    40  }
    41  
    42  type ClaimGrants struct {
    43  	Identity string      `json:"-"`
    44  	Name     string      `json:"name,omitempty"`
    45  	Video    *VideoGrant `json:"video,omitempty"`
    46  	// for verifying integrity of the message body
    47  	Sha256   string `json:"sha256,omitempty"`
    48  	Metadata string `json:"metadata,omitempty"`
    49  }
    50  
    51  func (c *ClaimGrants) Clone() *ClaimGrants {
    52  	if c == nil {
    53  		return nil
    54  	}
    55  
    56  	clone := *c
    57  	clone.Video = c.Video.Clone()
    58  
    59  	return &clone
    60  }
    61  
    62  func (v *VideoGrant) SetCanPublish(val bool) {
    63  	v.CanPublish = &val
    64  }
    65  
    66  func (v *VideoGrant) SetCanPublishData(val bool) {
    67  	v.CanPublishData = &val
    68  }
    69  
    70  func (v *VideoGrant) SetCanSubscribe(val bool) {
    71  	v.CanSubscribe = &val
    72  }
    73  
    74  func (v *VideoGrant) SetCanPublishSources(sources []livekit.TrackSource) {
    75  	v.CanPublishSources = make([]string, 0, len(sources))
    76  	for _, s := range sources {
    77  		v.CanPublishSources = append(v.CanPublishSources, sourceToString(s))
    78  	}
    79  }
    80  
    81  func (v *VideoGrant) SetCanUpdateOwnMetadata(val bool) {
    82  	v.CanUpdateOwnMetadata = &val
    83  }
    84  
    85  func (v *VideoGrant) GetCanPublish() bool {
    86  	if v.CanPublish == nil {
    87  		return true
    88  	}
    89  	return *v.CanPublish
    90  }
    91  
    92  func (v *VideoGrant) GetCanPublishSource(source livekit.TrackSource) bool {
    93  	if !v.GetCanPublish() {
    94  		return false
    95  	}
    96  	// don't differentiate between nil and unset, since that distinction doesn't survive serialization
    97  	if len(v.CanPublishSources) == 0 {
    98  		return true
    99  	}
   100  	sourceStr := sourceToString(source)
   101  	for _, s := range v.CanPublishSources {
   102  		if s == sourceStr {
   103  			return true
   104  		}
   105  	}
   106  	return false
   107  }
   108  
   109  func (v *VideoGrant) GetCanPublishSources() []livekit.TrackSource {
   110  	if len(v.CanPublishSources) == 0 {
   111  		return nil
   112  	}
   113  
   114  	sources := make([]livekit.TrackSource, 0, len(v.CanPublishSources))
   115  	for _, s := range v.CanPublishSources {
   116  		sources = append(sources, sourceToProto(s))
   117  	}
   118  	return sources
   119  }
   120  
   121  func (v *VideoGrant) GetCanPublishData() bool {
   122  	if v.CanPublishData == nil {
   123  		return v.GetCanPublish()
   124  	}
   125  	return *v.CanPublishData
   126  }
   127  
   128  func (v *VideoGrant) GetCanSubscribe() bool {
   129  	if v.CanSubscribe == nil {
   130  		return true
   131  	}
   132  	return *v.CanSubscribe
   133  }
   134  
   135  func (v *VideoGrant) GetCanUpdateOwnMetadata() bool {
   136  	if v.CanUpdateOwnMetadata == nil {
   137  		return false
   138  	}
   139  	return *v.CanUpdateOwnMetadata
   140  }
   141  
   142  func (v *VideoGrant) MatchesPermission(permission *livekit.ParticipantPermission) bool {
   143  	if permission == nil {
   144  		return false
   145  	}
   146  
   147  	if v.GetCanPublish() != permission.CanPublish {
   148  		return false
   149  	}
   150  	if v.GetCanPublishData() != permission.CanPublishData {
   151  		return false
   152  	}
   153  	if v.GetCanSubscribe() != permission.CanSubscribe {
   154  		return false
   155  	}
   156  	if v.GetCanUpdateOwnMetadata() != permission.CanUpdateMetadata {
   157  		return false
   158  	}
   159  	if v.Hidden != permission.Hidden {
   160  		return false
   161  	}
   162  	if v.Recorder != permission.Recorder {
   163  		return false
   164  	}
   165  	if !slices.Equal(v.GetCanPublishSources(), permission.CanPublishSources) {
   166  		return false
   167  	}
   168  
   169  	return true
   170  }
   171  
   172  func (v *VideoGrant) UpdateFromPermission(permission *livekit.ParticipantPermission) {
   173  	if permission == nil {
   174  		return
   175  	}
   176  
   177  	v.SetCanPublish(permission.CanPublish)
   178  	v.SetCanPublishData(permission.CanPublishData)
   179  	v.SetCanPublishSources(permission.CanPublishSources)
   180  	v.SetCanSubscribe(permission.CanSubscribe)
   181  	v.SetCanUpdateOwnMetadata(permission.CanUpdateMetadata)
   182  	v.Hidden = permission.Hidden
   183  	v.Recorder = permission.Recorder
   184  }
   185  
   186  func (v *VideoGrant) ToPermission() *livekit.ParticipantPermission {
   187  	pp := &livekit.ParticipantPermission{
   188  		CanPublish:        v.GetCanPublish(),
   189  		CanPublishData:    v.GetCanPublishData(),
   190  		CanSubscribe:      v.GetCanSubscribe(),
   191  		CanPublishSources: v.GetCanPublishSources(),
   192  		CanUpdateMetadata: v.GetCanUpdateOwnMetadata(),
   193  		Hidden:            v.Hidden,
   194  		Recorder:          v.Recorder,
   195  	}
   196  	return pp
   197  }
   198  
   199  func (v *VideoGrant) Clone() *VideoGrant {
   200  	if v == nil {
   201  		return nil
   202  	}
   203  
   204  	clone := *v
   205  
   206  	if v.CanPublish != nil {
   207  		canPublish := *v.CanPublish
   208  		clone.CanPublish = &canPublish
   209  	}
   210  
   211  	if v.CanSubscribe != nil {
   212  		canSubscribe := *v.CanSubscribe
   213  		clone.CanSubscribe = &canSubscribe
   214  	}
   215  
   216  	if v.CanPublishData != nil {
   217  		canPublishData := *v.CanPublishData
   218  		clone.CanPublishData = &canPublishData
   219  	}
   220  
   221  	if v.CanPublishSources != nil {
   222  		clone.CanPublishSources = make([]string, len(v.CanPublishSources))
   223  		copy(clone.CanPublishSources, v.CanPublishSources)
   224  	}
   225  
   226  	if v.CanUpdateOwnMetadata != nil {
   227  		canUpdateOwnMetadata := *v.CanUpdateOwnMetadata
   228  		clone.CanUpdateOwnMetadata = &canUpdateOwnMetadata
   229  	}
   230  
   231  	return &clone
   232  }
   233  
   234  func sourceToString(source livekit.TrackSource) string {
   235  	return strings.ToLower(source.String())
   236  }
   237  
   238  func sourceToProto(sourceStr string) livekit.TrackSource {
   239  	switch sourceStr {
   240  	case "camera":
   241  		return livekit.TrackSource_CAMERA
   242  	case "microphone":
   243  		return livekit.TrackSource_MICROPHONE
   244  	case "screen_share":
   245  		return livekit.TrackSource_SCREEN_SHARE
   246  	case "screen_share_audio":
   247  		return livekit.TrackSource_SCREEN_SHARE_AUDIO
   248  	default:
   249  		return livekit.TrackSource_UNKNOWN
   250  	}
   251  }