mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-22 12:59:23 -05:00
External users, when logging in for the first time, have no role assigned and are unable to create their home because that requires the create-space permission. This assigns users that don't have a role assigned to the default user role and persists that assignment in the settings service so that CreateHome can pick it up when checking permissions later. This also disables the auto creation of the user's home in the reva auth provider (i.e. when using basic auth) as the role assignement has not happenend at that point. So the home creation will now always happen in the CreateHome middleware in the proxy.
123 lines
3.9 KiB
Go
123 lines
3.9 KiB
Go
package backend
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
|
|
cs3 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
|
rpcv1beta1 "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
|
|
types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
|
|
"github.com/owncloud/ocis/ocis-pkg/log"
|
|
settingssvc "github.com/owncloud/ocis/protogen/gen/ocis/services/settings/v0"
|
|
settingsService "github.com/owncloud/ocis/settings/pkg/service/v0"
|
|
)
|
|
|
|
type cs3backend struct {
|
|
settingsRoleService settingssvc.RoleService
|
|
authProvider RevaAuthenticator
|
|
machineAuthAPIKey string
|
|
logger log.Logger
|
|
}
|
|
|
|
// NewCS3UserBackend creates a user-provider which fetches users from a CS3 UserBackend
|
|
func NewCS3UserBackend(rs settingssvc.RoleService, ap RevaAuthenticator, machineAuthAPIKey string, logger log.Logger) UserBackend {
|
|
return &cs3backend{
|
|
settingsRoleService: rs,
|
|
authProvider: ap,
|
|
machineAuthAPIKey: machineAuthAPIKey,
|
|
logger: logger,
|
|
}
|
|
}
|
|
|
|
func (c *cs3backend) GetUserByClaims(ctx context.Context, claim, value string, withRoles bool) (*cs3.User, string, error) {
|
|
res, err := c.authProvider.Authenticate(ctx, &gateway.AuthenticateRequest{
|
|
Type: "machine",
|
|
ClientId: claim + ":" + value,
|
|
ClientSecret: c.machineAuthAPIKey,
|
|
})
|
|
|
|
switch {
|
|
case err != nil:
|
|
return nil, "", fmt.Errorf("could not get user by claim %v with value %v: %w", claim, value, err)
|
|
case res.Status.Code != rpcv1beta1.Code_CODE_OK:
|
|
if res.Status.Code == rpcv1beta1.Code_CODE_NOT_FOUND {
|
|
return nil, "", ErrAccountNotFound
|
|
}
|
|
return nil, "", fmt.Errorf("could not get user by claim %v with value %v : %w ", claim, value, err)
|
|
}
|
|
|
|
user := res.User
|
|
|
|
if !withRoles {
|
|
return user, res.Token, nil
|
|
}
|
|
|
|
var roleIDs []string
|
|
if user.Id.Type != cs3.UserType_USER_TYPE_LIGHTWEIGHT {
|
|
roleIDs, err = loadRolesIDs(ctx, user.Id.OpaqueId, c.settingsRoleService)
|
|
if err != nil {
|
|
c.logger.Error().Err(err).Msgf("Could not load roles")
|
|
}
|
|
}
|
|
|
|
// if roles are empty, assume we haven't seen the user before and assign a
|
|
// default user role. At least until proper roles are provided. See
|
|
// https://github.com/owncloud/ocis/issues/1825 for more context.
|
|
if len(roleIDs) == 0 {
|
|
if user.Id.Type == cs3.UserType_USER_TYPE_PRIMARY {
|
|
c.logger.Info().Str("userid", user.Id.OpaqueId).Msg("user has no role assigned, assigning default user role")
|
|
_, err := c.settingsRoleService.AssignRoleToUser(ctx, &settingssvc.AssignRoleToUserRequest{
|
|
AccountUuid: user.Id.OpaqueId,
|
|
RoleId: settingsService.BundleUUIDRoleUser,
|
|
})
|
|
if err != nil {
|
|
c.logger.Error().Err(err).Msg("Could not add default role")
|
|
}
|
|
roleIDs = append(roleIDs, settingsService.BundleUUIDRoleUser)
|
|
}
|
|
}
|
|
|
|
enc, err := encodeRoleIDs(roleIDs)
|
|
if err != nil {
|
|
c.logger.Error().Err(err).Msg("Could not encode loaded roles")
|
|
}
|
|
|
|
if user.Opaque == nil {
|
|
user.Opaque = &types.Opaque{
|
|
Map: map[string]*types.OpaqueEntry{
|
|
"roles": enc,
|
|
},
|
|
}
|
|
} else {
|
|
user.Opaque.Map["roles"] = enc
|
|
}
|
|
|
|
return user, res.Token, nil
|
|
}
|
|
|
|
func (c *cs3backend) Authenticate(ctx context.Context, username string, password string) (*cs3.User, string, error) {
|
|
res, err := c.authProvider.Authenticate(ctx, &gateway.AuthenticateRequest{
|
|
Type: "basic",
|
|
ClientId: username,
|
|
ClientSecret: password,
|
|
})
|
|
|
|
switch {
|
|
case err != nil:
|
|
return nil, "", fmt.Errorf("could not authenticate with username and password user: %s, %w", username, err)
|
|
case res.Status.Code != rpcv1beta1.Code_CODE_OK:
|
|
return nil, "", fmt.Errorf("could not authenticate with username and password user: %s, got code: %d", username, res.Status.Code)
|
|
}
|
|
|
|
return res.User, res.Token, nil
|
|
}
|
|
|
|
func (c *cs3backend) CreateUserFromClaims(ctx context.Context, claims map[string]interface{}) (*cs3.User, error) {
|
|
return nil, fmt.Errorf("CS3 Backend does not support creating users from claims")
|
|
}
|
|
|
|
func (c cs3backend) GetUserGroups(ctx context.Context, userID string) {
|
|
panic("implement me")
|
|
}
|