Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
297 changes: 147 additions & 150 deletions auth/auth_test.go

Large diffs are not rendered by default.

188 changes: 95 additions & 93 deletions auth/collection_access_test.go

Large diffs are not rendered by default.

36 changes: 36 additions & 0 deletions auth/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright 2025-Present Couchbase, Inc.
//
// Use of this software is governed by the Business Source License included
// in the file licenses/BSL-Couchbase.txt. As of the Change Date specified
// in that file, in accordance with the Business Source License, use of this
// software will be governed by the Apache License, Version 2.0, included in
// the file licenses/APL2.txt.

package auth

import (
"fmt"
"net/http"

"github.com/couchbase/sync_gateway/base"
)

var (
errLoginRequired = base.HTTPErrorf(http.StatusUnauthorized, "login required")
// errUnauthorized is a generic error message
errUnauthorized = base.HTTPErrorf(http.StatusForbidden, "You are not allowed to see this")
// errUnauthorizedChannels is used when we cannot determine which channels are unauthorized
errUnauthorizedChannels = base.HTTPErrorf(http.StatusForbidden, "Unauthorized to see channels")
// errNotAllowedChannels is used when we can determine which channels are not allowed
errNotAllowedChannels = base.HTTPErrorf(http.StatusForbidden, "You are not allowed to see channels")
)

// newErrUnauthorizedChannels creates an error indicating the user is not authorized to see the specified channels. Used when we can not determine which channels are unauthorized.
func newErrUnauthorizedChannels(channels base.Set) error {
return fmt.Errorf("%w %v", errUnauthorizedChannels, channels)
}

// newErrNotAllowedChannels creates an error indicating the user is not allowed to see the specified channels. Used when we can determine which channels are not allowed.
func newErrNotAllowedChannels[T base.Set | []string](channels T) error {
return fmt.Errorf("%w %v", errNotAllowedChannels, channels)
}
2 changes: 1 addition & 1 deletion auth/principal.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ type Principal interface {

// Returns an appropriate HTTPError for unauthorized access -- a 401 if the receiver is
// the guest user, else 403.
UnauthError(message string) error
UnauthError(err error) error

DocID() string
accessViewKey() string
Expand Down
11 changes: 6 additions & 5 deletions auth/role.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,11 +363,12 @@ func (role *roleImpl) validate() error {

//////// CHANNEL AUTHORIZATION:

func (role *roleImpl) UnauthError(message string) error {
// UnauthError returns the underlying error unless Role is the guest user.
func (role *roleImpl) UnauthError(err error) error {
if role.Name_ == "" {
return base.HTTPErrorf(http.StatusUnauthorized, "login required: %s", message)
return errLoginRequired
}
return base.NewHTTPError(http.StatusForbidden, message)
return err
}

// Returns true if the Role is allowed to access the channel.
Expand Down Expand Up @@ -406,7 +407,7 @@ func authorizeAllChannels(princ Principal, channels base.Set) error {
}
}
if forbidden != nil {
return princ.UnauthError(fmt.Sprintf("You are not allowed to see channels %v", forbidden))
return princ.UnauthError(newErrNotAllowedChannels(forbidden))
}
return nil
}
Expand All @@ -423,5 +424,5 @@ func authorizeAnyChannel(princ Principal, channels base.Set) error {
} else if princ.Channels().Contains(ch.UserStarChannel) {
return nil
}
return princ.UnauthError("You are not allowed to see this")
return princ.UnauthError(errUnauthorized)
}
8 changes: 3 additions & 5 deletions auth/role_collection_access.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
package auth

import (
"fmt"

"github.com/couchbase/sync_gateway/base"
ch "github.com/couchbase/sync_gateway/channels"
)
Expand Down Expand Up @@ -195,11 +193,11 @@ func (role *roleImpl) authorizeAllCollectionChannels(scope, collection string, c
}
}
if forbidden != nil {
return role.UnauthError(fmt.Sprintf("You are not allowed to see channels %v", forbidden))
return role.UnauthError(newErrNotAllowedChannels(forbidden))
}
return nil
}
return role.UnauthError(fmt.Sprintf("Unauthorized to see channels %v", channels))
return role.UnauthError(newErrUnauthorizedChannels(channels))
}

// Returns an error if the Principal does not have access to any of the channels in the set.
Expand All @@ -219,7 +217,7 @@ func (role *roleImpl) AuthorizeAnyCollectionChannel(scope, collection string, ch
return nil
}
}
return role.UnauthError("You are not allowed to see this")
return role.UnauthError(errUnauthorized)
}

// initChannels grants the specified channels to the role as an admin grant, and performs
Expand Down
2 changes: 1 addition & 1 deletion auth/user_collection_access.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func (user *userImpl) AuthorizeAnyCollectionChannel(scope, collection string, ch
}
}

return user.UnauthError("You are not allowed to see this")
return user.UnauthError(errUnauthorized)
}

func (user *userImpl) canSeeCollectionChannelSince(scope, collection, channel string) uint64 {
Expand Down
3 changes: 1 addition & 2 deletions db/functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ package db
import (
"context"
"encoding/json"
"fmt"
"net/http"
"time"

Expand Down Expand Up @@ -130,6 +129,6 @@ func missingError(user auth.User, what string, name string) error {
if user == nil {
return base.HTTPErrorf(http.StatusNotFound, "no such %s %q", what, name)
} else {
return user.UnauthError(fmt.Sprintf("you are not allowed to call %s %q", what, name))
return user.UnauthError(base.HTTPErrorf(http.StatusForbidden, "you are not allowed to call %s %q", what, name))
}
}
2 changes: 1 addition & 1 deletion db/functions/function.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ func (fn *functionImpl) authorize(user auth.User, args map[string]any) error {
}
}
}
return user.UnauthError(fmt.Sprintf("you are not allowed to call %s %q", fn.typeName, fn.name))
return user.UnauthError(base.HTTPErrorf(http.StatusForbidden, "You are not allowed to call %s %q", fn.typeName, fn.name))
}

// Expands patterns of the form `${param}` in `pattern`, looking up each such
Expand Down