Merge pull request #1911 from ishank011/gh-ocis-1825

This commit is contained in:
Alex Unger
2021-04-13 15:57:40 +02:00
committed by GitHub
6 changed files with 175 additions and 25 deletions
+14
View File
@@ -19,6 +19,8 @@ import (
ocsm "github.com/owncloud/ocis/ocs/pkg/middleware"
"github.com/owncloud/ocis/ocs/pkg/service/v0/data"
"github.com/owncloud/ocis/ocs/pkg/service/v0/response"
"github.com/owncloud/ocis/proxy/pkg/cs3"
"github.com/owncloud/ocis/proxy/pkg/user/backend"
settings "github.com/owncloud/ocis/settings/pkg/proto/v0"
)
@@ -57,6 +59,10 @@ func NewService(opts ...Option) Service {
logger: options.Logger,
}
if svc.config.AccountBackend == "" {
svc.config.AccountBackend = "accounts"
}
requireUser := ocsm.RequireUser()
requireAdmin := ocsm.RequireAdmin(
@@ -154,6 +160,14 @@ func (o Ocs) getAccountService() accounts.AccountsService {
return accounts.NewAccountsService("com.owncloud.api.accounts", grpc.DefaultClient)
}
func (o Ocs) getCS3Backend() backend.UserBackend {
revaClient, err := cs3.GetGatewayServiceClient(o.config.RevaAddress)
if err != nil {
o.logger.Fatal().Msgf("could not get reva client at address %s", o.config.RevaAddress)
}
return backend.NewCS3UserBackend(revaClient, nil, revaClient, o.logger)
}
func (o Ocs) getGroupsService() accounts.GroupsService {
return accounts.NewGroupsService("com.owncloud.api.accounts", grpc.DefaultClient)
}
+127 -14
View File
@@ -17,6 +17,7 @@ import (
"google.golang.org/protobuf/types/known/fieldmaskpb"
merrors "github.com/asim/go-micro/v3/errors"
cs3 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
accounts "github.com/owncloud/ocis/accounts/pkg/proto/v0"
"github.com/owncloud/ocis/ocs/pkg/service/v0/data"
"github.com/owncloud/ocis/ocs/pkg/service/v0/response"
@@ -42,13 +43,14 @@ func (o Ocs) GetSelf(w http.ResponseWriter, r *http.Request) {
// TODO(someone) this fix is in place because if the user backend (PROXY_ACCOUNT_BACKEND_TYPE) is set to, for instance,
// cs3, we cannot count with the accounts service.
if u != nil {
uid, gid := o.extractUIDAndGID(u)
d := &data.User{
UserID: u.Username,
DisplayName: u.DisplayName,
LegacyDisplayName: u.DisplayName,
Email: u.Mail,
UIDNumber: u.UidNumber,
GIDNumber: u.GidNumber,
UIDNumber: uid,
GIDNumber: gid,
}
mustNotFail(render.Render(w, r, response.DataRender(d)))
return
@@ -81,11 +83,17 @@ func (o Ocs) GetUser(w http.ResponseWriter, r *http.Request) {
var account *accounts.Account
var err error
if userid == "" {
switch {
case userid == "":
mustNotFail(render.Render(w, r, response.ErrRender(data.MetaBadRequest.StatusCode, "missing user in context")))
} else {
case o.config.AccountBackend == "accounts":
account, err = o.fetchAccountByUsername(r.Context(), userid)
case o.config.AccountBackend == "cs3":
account, err = o.fetchAccountFromCS3Backend(r.Context(), userid)
default:
o.logger.Fatal().Msgf("Invalid accounts backend type '%s'", o.config.AccountBackend)
}
if err != nil {
merr := merrors.FromError(err)
if merr.Code == http.StatusNotFound {
@@ -188,9 +196,19 @@ func (o Ocs) AddUser(w http.ResponseWriter, r *http.Request) {
newAccount.GidNumber = gidNumber
}
account, err := o.getAccountService().CreateAccount(r.Context(), &accounts.CreateAccountRequest{
Account: newAccount,
})
var account *accounts.Account
switch o.config.AccountBackend {
case "accounts":
account, err = o.getAccountService().CreateAccount(r.Context(), &accounts.CreateAccountRequest{
Account: newAccount,
})
case "cs3":
o.logger.Fatal().Msg("cs3 backend doesn't support adding users")
default:
o.logger.Fatal().Msgf("Invalid accounts backend type '%s'", o.config.AccountBackend)
}
if err != nil {
merr := merrors.FromError(err)
switch merr.Code {
@@ -239,7 +257,18 @@ func (o Ocs) AddUser(w http.ResponseWriter, r *http.Request) {
// EditUser creates a new user account
func (o Ocs) EditUser(w http.ResponseWriter, r *http.Request) {
userid := chi.URLParam(r, "userid")
account, err := o.fetchAccountByUsername(r.Context(), userid)
var account *accounts.Account
var err error
switch o.config.AccountBackend {
case "accounts":
account, err = o.fetchAccountByUsername(r.Context(), userid)
case "cs3":
o.logger.Fatal().Msg("cs3 backend doesn't support editing users")
default:
o.logger.Fatal().Msgf("Invalid accounts backend type '%s'", o.config.AccountBackend)
}
if err != nil {
merr := merrors.FromError(err)
if merr.Code == http.StatusNotFound {
@@ -306,7 +335,18 @@ func (o Ocs) EditUser(w http.ResponseWriter, r *http.Request) {
// DeleteUser deletes a user
func (o Ocs) DeleteUser(w http.ResponseWriter, r *http.Request) {
userid := chi.URLParam(r, "userid")
account, err := o.fetchAccountByUsername(r.Context(), userid)
var account *accounts.Account
var err error
switch o.config.AccountBackend {
case "accounts":
account, err = o.fetchAccountByUsername(r.Context(), userid)
case "cs3":
o.logger.Fatal().Msg("cs3 backend doesn't support deleting users")
default:
o.logger.Fatal().Msgf("Invalid accounts backend type '%s'", o.config.AccountBackend)
}
if err != nil {
merr := merrors.FromError(err)
if merr.Code == http.StatusNotFound {
@@ -341,7 +381,18 @@ func (o Ocs) DeleteUser(w http.ResponseWriter, r *http.Request) {
// EnableUser enables a user
func (o Ocs) EnableUser(w http.ResponseWriter, r *http.Request) {
userid := chi.URLParam(r, "userid")
account, err := o.fetchAccountByUsername(r.Context(), userid)
var account *accounts.Account
var err error
switch o.config.AccountBackend {
case "accounts":
account, err = o.fetchAccountByUsername(r.Context(), userid)
case "cs3":
o.logger.Fatal().Msg("cs3 backend doesn't support enabling users")
default:
o.logger.Fatal().Msgf("Invalid accounts backend type '%s'", o.config.AccountBackend)
}
if err != nil {
merr := merrors.FromError(err)
if merr.Code == http.StatusNotFound {
@@ -381,7 +432,18 @@ func (o Ocs) EnableUser(w http.ResponseWriter, r *http.Request) {
// DisableUser disables a user
func (o Ocs) DisableUser(w http.ResponseWriter, r *http.Request) {
userid := chi.URLParam(r, "userid")
account, err := o.fetchAccountByUsername(r.Context(), userid)
var account *accounts.Account
var err error
switch o.config.AccountBackend {
case "accounts":
account, err = o.fetchAccountByUsername(r.Context(), userid)
case "cs3":
o.logger.Fatal().Msg("cs3 backend doesn't support disabling users")
default:
o.logger.Fatal().Msgf("Invalid accounts backend type '%s'", o.config.AccountBackend)
}
if err != nil {
merr := merrors.FromError(err)
if merr.Code == http.StatusNotFound {
@@ -498,9 +560,20 @@ func (o Ocs) ListUsers(w http.ResponseWriter, r *http.Request) {
query = fmt.Sprintf("on_premises_sam_account_name eq '%s'", escapeValue(search))
}
res, err := o.getAccountService().ListAccounts(r.Context(), &accounts.ListAccountsRequest{
Query: query,
})
var res *accounts.ListAccountsResponse
var err error
switch o.config.AccountBackend {
case "accounts":
res, err = o.getAccountService().ListAccounts(r.Context(), &accounts.ListAccountsRequest{
Query: query,
})
case "cs3":
// TODO
o.logger.Fatal().Msg("cs3 backend doesn't support listing users")
default:
o.logger.Fatal().Msgf("Invalid accounts backend type '%s'", o.config.AccountBackend)
}
if err != nil {
o.logger.Err(err).Msg("could not list users")
mustNotFail(render.Render(w, r, response.ErrRender(data.MetaServerError.StatusCode, "could not list users")))
@@ -533,3 +606,43 @@ func (o Ocs) fetchAccountByUsername(ctx context.Context, name string) (*accounts
}
return nil, merrors.NotFound("", "The requested user could not be found")
}
func (o Ocs) fetchAccountFromCS3Backend(ctx context.Context, name string) (*accounts.Account, error) {
backend := o.getCS3Backend()
u, err := backend.GetUserByClaims(ctx, "username", name, false)
if err != nil {
return nil, err
}
uid, gid := o.extractUIDAndGID(u)
return &accounts.Account{
OnPremisesSamAccountName: u.Username,
DisplayName: u.DisplayName,
Mail: u.Mail,
UidNumber: uid,
GidNumber: gid,
}, nil
}
func (o Ocs) extractUIDAndGID(u *cs3.User) (int64, int64) {
var uid, gid int64
var err error
if u.Opaque != nil && u.Opaque.Map != nil {
if uidObj, ok := u.Opaque.Map["uid"]; ok {
if uidObj.Decoder == "plain" {
uid, err = strconv.ParseInt(string(uidObj.Value), 10, 64)
if err != nil {
o.logger.Error().Err(err).Interface("user", u).Msg("could not extract uid for user")
}
}
}
if gidObj, ok := u.Opaque.Map["gid"]; ok {
if gidObj.Decoder == "plain" {
gid, err = strconv.ParseInt(string(gidObj.Value), 10, 64)
if err != nil {
o.logger.Error().Err(err).Interface("user", u).Msg("could not extract gid for user")
}
}
}
}
return uid, gid
}