mirror of
https://github.com/strukturag/nextcloud-spreed-signaling
synced 2024-05-02 22:03:09 +02:00
Support separate permissions for publishing audio / video.
Clients with permission "publish-media" can publish any audio/video. Other clients need to have "publish-audio" and/or "publish-video" to publish the corresponding media types. For this the SDP in the offer is parsed to check what will be sent.
This commit is contained in:
parent
3b26003b12
commit
70b37364d3
|
@ -175,6 +175,7 @@ func (s *ClientSession) HasFeature(feature string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// HasPermission checks if the session has the passed permissions.
|
||||
func (s *ClientSession) HasPermission(permission Permission) bool {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
@ -182,6 +183,23 @@ func (s *ClientSession) HasPermission(permission Permission) bool {
|
|||
return s.hasPermissionLocked(permission)
|
||||
}
|
||||
|
||||
// HasAnyPermission checks if the session has one of the passed permissions.
|
||||
func (s *ClientSession) HasAnyPermission(permission ...Permission) bool {
|
||||
if len(permission) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
for _, p := range permission {
|
||||
if s.hasPermissionLocked(p) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *ClientSession) hasPermissionLocked(permission Permission) bool {
|
||||
if !s.supportsPermissions {
|
||||
// Old-style session that doesn't receive permissions from Nextcloud.
|
||||
|
|
1
go.mod
1
go.mod
|
@ -15,6 +15,7 @@ require (
|
|||
github.com/nats-io/nats.go v1.13.0
|
||||
github.com/notedit/janus-go v0.0.0-20200517101215-10eb8b95d1a0
|
||||
github.com/oschwald/maxminddb-golang v1.8.0
|
||||
github.com/pion/sdp v1.3.0
|
||||
github.com/prometheus/client_golang v1.11.0
|
||||
go.etcd.io/etcd v0.5.0-alpha.5.0.20210226220824-aa7126864d82
|
||||
go.uber.org/zap v1.13.0 // indirect
|
||||
|
|
2
go.sum
2
go.sum
|
@ -156,6 +156,8 @@ github.com/notedit/janus-go v0.0.0-20200517101215-10eb8b95d1a0/go.mod h1:BN/Txse
|
|||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||
github.com/oschwald/maxminddb-golang v1.8.0 h1:Uh/DSnGoxsyp/KYbY1AuP0tYEwfs0sCph9p/UMXK/Hk=
|
||||
github.com/oschwald/maxminddb-golang v1.8.0/go.mod h1:RXZtst0N6+FY/3qCNmZMBApR19cdQj43/NM9VkrNAis=
|
||||
github.com/pion/sdp v1.3.0 h1:21lpgEILHyolpsIrbCBagZaAPj4o057cFjzaFebkVOs=
|
||||
github.com/pion/sdp v1.3.0/go.mod h1:ceA2lTyftydQTuCIbUNoH77aAt6CiQJaRpssA4Gee8I=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
|
|
60
hub.go
60
hub.go
|
@ -42,6 +42,7 @@ import (
|
|||
"github.com/gorilla/mux"
|
||||
"github.com/gorilla/securecookie"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/pion/sdp"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -1374,8 +1375,8 @@ func (h *Hub) processMessageMsg(client *Client, message *ClientMessage) {
|
|||
if recipient != nil {
|
||||
// The recipient is connected to this instance, no need to go through NATS.
|
||||
if clientData != nil && clientData.Type == "sendoffer" {
|
||||
if !isAllowedToSend(session, clientData) {
|
||||
log.Printf("Session %s is not allowed to send offer for %s, ignoring", session.PublicId(), clientData.RoomType)
|
||||
if err := isAllowedToSend(session, clientData); err != nil {
|
||||
log.Printf("Session %s is not allowed to send offer for %s, ignoring (%s)", session.PublicId(), clientData.RoomType, err)
|
||||
sendNotAllowed(session, message, "Not allowed to send offer")
|
||||
return
|
||||
}
|
||||
|
@ -1651,14 +1652,51 @@ func (h *Hub) processInternalMsg(client *Client, message *ClientMessage) {
|
|||
}
|
||||
}
|
||||
|
||||
func isAllowedToSend(session *ClientSession, data *MessageClientMessageData) bool {
|
||||
var permission Permission
|
||||
func isAllowedToSend(session *ClientSession, data *MessageClientMessageData) error {
|
||||
if data.RoomType == "screen" {
|
||||
permission = PERMISSION_MAY_PUBLISH_SCREEN
|
||||
if session.HasPermission(PERMISSION_MAY_PUBLISH_SCREEN) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("permission \"%s\" not found", PERMISSION_MAY_PUBLISH_SCREEN)
|
||||
} else if session.HasPermission(PERMISSION_MAY_PUBLISH_MEDIA) {
|
||||
// Client is allowed to publish any media (audio / video).
|
||||
return nil
|
||||
} else if data != nil && data.Type == "offer" {
|
||||
// Parse SDP to check what user is trying to publish and check permissions accordingly.
|
||||
sdpValue, found := data.Payload["sdp"]
|
||||
if !found {
|
||||
return fmt.Errorf("offer does not contain a sdp")
|
||||
}
|
||||
sdpText, ok := sdpValue.(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("offer does not contain a valid sdp")
|
||||
}
|
||||
var s sdp.SessionDescription
|
||||
if err := s.Unmarshal(sdpText); err != nil {
|
||||
return fmt.Errorf("could not parse sdp: %w", err)
|
||||
}
|
||||
for _, md := range s.MediaDescriptions {
|
||||
switch md.MediaName.Media {
|
||||
case "audio":
|
||||
if !session.HasPermission(PERMISSION_MAY_PUBLISH_AUDIO) {
|
||||
return fmt.Errorf("permission \"%s\" not found", PERMISSION_MAY_PUBLISH_AUDIO)
|
||||
}
|
||||
case "video":
|
||||
if !session.HasPermission(PERMISSION_MAY_PUBLISH_VIDEO) {
|
||||
return fmt.Errorf("permission \"%s\" not found", PERMISSION_MAY_PUBLISH_VIDEO)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
permission = PERMISSION_MAY_PUBLISH_MEDIA
|
||||
// Candidate or unknown event, check if client is allowed to publish any media.
|
||||
if session.HasAnyPermission(PERMISSION_MAY_PUBLISH_AUDIO, PERMISSION_MAY_PUBLISH_VIDEO) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("permission check failed")
|
||||
}
|
||||
return session.HasPermission(permission)
|
||||
|
||||
}
|
||||
|
||||
func sendNotAllowed(session *ClientSession, message *ClientMessage, reason string) {
|
||||
|
@ -1733,8 +1771,8 @@ func (h *Hub) processMcuMessage(senderSession *ClientSession, session *ClientSes
|
|||
clientType = "subscriber"
|
||||
mc, err = session.GetOrCreateSubscriber(ctx, h.mcu, message.Recipient.SessionId, data.RoomType)
|
||||
case "offer":
|
||||
if !isAllowedToSend(session, data) {
|
||||
log.Printf("Session %s is not allowed to offer %s, ignoring", session.PublicId(), data.RoomType)
|
||||
if err := isAllowedToSend(session, data); err != nil {
|
||||
log.Printf("Session %s is not allowed to offer %s, ignoring (%s)", session.PublicId(), data.RoomType, err)
|
||||
sendNotAllowed(senderSession, client_message, "Not allowed to publish.")
|
||||
return
|
||||
}
|
||||
|
@ -1751,8 +1789,8 @@ func (h *Hub) processMcuMessage(senderSession *ClientSession, session *ClientSes
|
|||
mc = session.GetSubscriber(message.Recipient.SessionId, data.RoomType)
|
||||
default:
|
||||
if session.PublicId() == message.Recipient.SessionId {
|
||||
if !isAllowedToSend(session, data) {
|
||||
log.Printf("Session %s is not allowed to send candidate for %s, ignoring", session.PublicId(), data.RoomType)
|
||||
if err := isAllowedToSend(session, data); err != nil {
|
||||
log.Printf("Session %s is not allowed to send candidate for %s, ignoring (%s)", session.PublicId(), data.RoomType, err)
|
||||
sendNotAllowed(senderSession, client_message, "Not allowed to send candidate.")
|
||||
return
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ type Permission string
|
|||
|
||||
var (
|
||||
PERMISSION_MAY_PUBLISH_MEDIA Permission = "publish-media"
|
||||
PERMISSION_MAY_PUBLISH_AUDIO Permission = "publish-audio"
|
||||
PERMISSION_MAY_PUBLISH_VIDEO Permission = "publish-video"
|
||||
PERMISSION_MAY_PUBLISH_SCREEN Permission = "publish-screen"
|
||||
PERMISSION_MAY_CONTROL Permission = "control"
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue