Repository: owncloud/ocis
Pull request #5735 (2023-03-06 09:46:41)

add common part, make the logic theme name agnostic
## Description

- Make `common` logo key also replacable
- Make the logic theme name agnostic

## Related Issue
<!--- This project only accepts pull requests related to open issues -->
<!--- If suggesting a new feature or change, please discuss it in an issue first -->
<!--- If fixing a bug, there should be an issue describing it with steps to reproduce -->
<!--- Please link to the issue here: -->
- Fixes <issue_link>

## Motivation and Context
<!--- Why is this change required? What problem does it solve? -->

## How Has This Been Tested?
<!--- Please describe in detail how you tested your changes. -->
<!--- Include details of your testing environment, and the tests you ran to -->
<!--- see how your change affects other areas of the code, etc. -->
- test environment:
- test case 1:
- test case 2:
- ...

## Screenshots (if appropriate):

## Types of changes
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
- [ ] Technical debt
- [ ] Tests only (no source changes)

## Checklist:
<!-- Tick the checkboxes when done. -->
<!-- Raise documentation ticket in owncloud.github.io/ -->
- [x] Code changes
- [ ] Unit tests added
- [ ] Acceptance tests added
- [ ] Documentation ticket raised: <link> 


sonarcloud[bot]: SonarCloud Quality Gate failed.&nbsp; &nbsp; [![Quality Gate failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/failed-16px.png 'Quality Gate failed')](https://sonarcloud.io/dashboard?id=owncloud_ocis&pullRequest=5735)

[![Bug](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/bug-16px.png 'Bug')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5735&resolved=false&types=BUG) [![C](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/C-16px.png 'C')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5735&resolved=false&types=BUG) [1 Bug](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5735&resolved=false&types=BUG)  
[![Vulnerability](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/vulnerability-16px.png 'Vulnerability')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5735&resolved=false&types=VULNERABILITY) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5735&resolved=false&types=VULNERABILITY) [0 Vulnerabilities](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5735&resolved=false&types=VULNERABILITY)  
[![Security Hotspot](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/security_hotspot-16px.png 'Security Hotspot')](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=5735&resolved=false&types=SECURITY_HOTSPOT) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=5735&resolved=false&types=SECURITY_HOTSPOT) [0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=owncloud_ocis&pullRequest=5735&resolved=false&types=SECURITY_HOTSPOT)  
[![Code Smell](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/code_smell-16px.png 'Code Smell')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5735&resolved=false&types=CODE_SMELL) [![A](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/RatingBadge/A-16px.png 'A')](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5735&resolved=false&types=CODE_SMELL) [0 Code Smells](https://sonarcloud.io/project/issues?id=owncloud_ocis&pullRequest=5735&resolved=false&types=CODE_SMELL)

[![0.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/CoverageChart/0-16px.png '0.0%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5735&metric=new_coverage&view=list) [0.0% Coverage](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5735&metric=new_coverage&view=list)  
[![0.0%](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/Duplications/3-16px.png '0.0%')](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5735&metric=new_duplicated_lines_density&view=list) [0.0% Duplication](https://sonarcloud.io/component_measures?id=owncloud_ocis&pullRequest=5735&metric=new_duplicated_lines_density&view=list)



Patch:
diff --git a/changelog/unreleased/branding-api.md b/changelog/unreleased/branding-api.md
index 3722cb523ea..ab675019c49 100644
--- a/changelog/unreleased/branding-api.md
+++ b/changelog/unreleased/branding-api.md
@@ -3,4 +3,5 @@ Enhancement: Add endpoints to upload a custom logo
 Added endpoints to upload and reset custom logos. The files are stored under the `WEB_ASSET_PATH`
 which defaults to `$OCIS_BASE_DATA_PATH/web/assets`.
 
+https://github.com/owncloud/ocis/pull/5735
 https://github.com/owncloud/ocis/pull/5559
diff --git a/services/graph/pkg/middleware/token.go b/ocis-pkg/middleware/token.go
similarity index 72%
rename from services/graph/pkg/middleware/token.go
rename to ocis-pkg/middleware/token.go
index b75f4be849c..1039ab0402b 100644
--- a/services/graph/pkg/middleware/token.go
+++ b/ocis-pkg/middleware/token.go
@@ -3,14 +3,13 @@ package middleware
 import (
 	"crypto/sha256"
 	"crypto/subtle"
+	"errors"
 	"net/http"
-
-	"github.com/owncloud/ocis/v2/services/graph/pkg/service/v0/errorcode"
 )
 
 var (
 	// ErrInvalidToken is returned when the request token is invalid.
-	ErrInvalidToken = "invalid or missing token"
+	ErrInvalidToken = errors.New("invalid or missing token")
 )
 
 // Token provides a middleware to check access secured by a static token.
@@ -27,7 +26,7 @@ func Token(token string) func(http.Handler) http.Handler {
 			header := r.Header.Get("Authorization")
 
 			if header == "" {
-				errorcode.InvalidAuthenticationToken.Render(w, r, http.StatusUnauthorized, ErrInvalidToken)
+				http.Error(w, ErrInvalidToken.Error(), http.StatusUnauthorized)
 				return
 			}
 
@@ -35,7 +34,7 @@ func Token(token string) func(http.Handler) http.Handler {
 			providedTokenHash := h.Sum([]byte(header))
 
 			if subtle.ConstantTimeCompare(requiredTokenHash, providedTokenHash) == 0 {
-				errorcode.InvalidAuthenticationToken.Render(w, r, http.StatusUnauthorized, ErrInvalidToken)
+				http.Error(w, ErrInvalidToken.Error(), http.StatusUnauthorized)
 				return
 			}
 
diff --git a/services/graph/pkg/middleware/token_test.go b/ocis-pkg/middleware/token_test.go
similarity index 100%
rename from services/graph/pkg/middleware/token_test.go
rename to ocis-pkg/middleware/token_test.go
diff --git a/ocis-pkg/service/debug/service.go b/ocis-pkg/service/debug/service.go
index a0432b86525..4a73742204a 100644
--- a/ocis-pkg/service/debug/service.go
+++ b/ocis-pkg/service/debug/service.go
@@ -8,7 +8,6 @@ import (
 	"github.com/justinas/alice"
 	"github.com/owncloud/ocis/v2/ocis-pkg/cors"
 	"github.com/owncloud/ocis/v2/ocis-pkg/middleware"
-	graphMiddleware "github.com/owncloud/ocis/v2/services/graph/pkg/middleware"
 	"github.com/prometheus/client_golang/prometheus/promhttp"
 	"go.opencensus.io/zpages"
 )
@@ -19,7 +18,7 @@ func NewService(opts ...Option) *http.Server {
 	mux := http.NewServeMux()
 
 	mux.Handle("/metrics", alice.New(
-		graphMiddleware.Token(
+		middleware.Token(
 			dopts.Token,
 		),
 	).Then(
diff --git a/services/graph/pkg/command/server.go b/services/graph/pkg/command/server.go
index 44a9600bf57..e962eb29a2d 100644
--- a/services/graph/pkg/command/server.go
+++ b/services/graph/pkg/command/server.go
@@ -60,7 +60,7 @@ func Server(cfg *config.Config) *cli.Command {
 				)
 
 				if err != nil {
-					logger.Error().Err(err).Str("transport", "http").Msg("Failed to initialize server")
+					logger.Info().Err(err).Str("transport", "http").Msg("Failed to initialize server")
 					return err
 				}
 
diff --git a/services/graph/pkg/config/config.go b/services/graph/pkg/config/config.go
index 385de2bab52..cd2c8be5c75 100644
--- a/services/graph/pkg/config/config.go
+++ b/services/graph/pkg/config/config.go
@@ -62,8 +62,6 @@ type LDAP struct {
 	UserNameAttribute        string `yaml:"user_name_attribute" env:"LDAP_USER_SCHEMA_USERNAME;GRAPH_LDAP_USER_NAME_ATTRIBUTE" desc:"LDAP Attribute to use for username of users."`
 	UserIDAttribute          string `yaml:"user_id_attribute" env:"LDAP_USER_SCHEMA_ID;GRAPH_LDAP_USER_UID_ATTRIBUTE" desc:"LDAP Attribute to use as the unique ID for users. This should be a stable globally unique ID like a UUID."`
 	UserEnabledAttribute     string `yaml:"user_enabled_attribute" env:"LDAP_USER_ENABLED_ATTRIBUTE;GRAPH_USER_ENABLED_ATTRIBUTE" desc:"LDAP Attribute to use as a flag telling if the user is enabled or disabled."`
-	DisableUserMechanism     string `yaml:"disable_user_mechanism" env:"LDAP_DISABLE_USER_MECHANISM;GRAPH_DISABLE_USER_MECHANISM" desc:"An option to control the behavior for disabling users. Valid options are 'none', 'attribute' and 'group'. If set to 'group', disabling a user via API will add the user to the configured group for disabled users, if set to 'attribute' this will be done in the ldap user entry, if set to 'none' the disable request is not processed. Default is 'attribute'."`
-	LdapDisabledUsersGroupDN string `yaml:"ldap_disabled_users_group_dn" env:"LDAP_DISABLED_USERS_GROUP_DN;GRAPH_DISABLED_USERS_GROUP_DN" desc:"The distinguished name of the group to which added users will be classified as disabled when 'disable_user_mechanism' is set to 'group'."`
 
 	GroupBaseDN        string `yaml:"group_base_dn" env:"LDAP_GROUP_BASE_DN;GRAPH_LDAP_GROUP_BASE_DN" desc:"Search base DN for looking up LDAP groups."`
 	GroupSearchScope   string `yaml:"group_search_scope" env:"LDAP_GROUP_SCOPE;GRAPH_LDAP_GROUP_SEARCH_SCOPE" desc:"LDAP search scope to use when looking up groups. Supported scopes are 'base', 'one' and 'sub'."`
diff --git a/services/graph/pkg/config/defaults/defaultconfig.go b/services/graph/pkg/config/defaults/defaultconfig.go
index 7b9a4563db5..0819334ebaf 100644
--- a/services/graph/pkg/config/defaults/defaultconfig.go
+++ b/services/graph/pkg/config/defaults/defaultconfig.go
@@ -69,8 +69,6 @@ func DefaultConfig() *config.Config {
 				//        ideally this needs to	be constant for the lifetime of a users
 				UserIDAttribute:           "owncloudUUID",
 				UserEnabledAttribute:      "ownCloudUserEnabled",
-				DisableUserMechanism:      "attribute",
-				LdapDisabledUsersGroupDN:  "cn=DisabledUsersGroup,ou=groups,o=libregraph-idm",
 				GroupBaseDN:               "ou=groups,o=libregraph-idm",
 				GroupSearchScope:          "sub",
 				GroupFilter:               "",
diff --git a/services/graph/pkg/identity/ldap.go b/services/graph/pkg/identity/ldap.go
index 7d1d19e5f27..b126204b5cb 100644
--- a/services/graph/pkg/identity/ldap.go
+++ b/services/graph/pkg/identity/ldap.go
@@ -20,29 +20,10 @@ import (
 )
 
 const (
-	_givenNameAttribute        = "givenname"
-	_surNameAttribute          = "sn"
-	_ldapGroupOfNamesAttribute = "(objectClass=groupOfNames)"
-	_ldapGroupMemberAttribute  = "member"
+	givenNameAttribute = "givenname"
+	surNameAttribute   = "sn"
 )
 
-// DisableUserMechanismType is used instead of directly using the string values from the configuration.
-type DisableUserMechanismType int64
-
-// The different DisableMechanism* constants are used for managing the enabling/disabling of users.
-const (
-	DisableMechanismNone DisableUserMechanismType = iota
-	DisableMechanismAttribute
-	DisableMechanismGroup
-)
-
-var mechanismMap = map[string]DisableUserMechanismType{
-	"":          DisableMechanismNone,
-	"none":      DisableMechanismNone,
-	"attribute": DisableMechanismAttribute,
-	"group":     DisableMechanismGroup,
-}
-
 type LDAP struct {
 	useServerUUID   bool
 	writeEnabled    bool
@@ -55,9 +36,6 @@ type LDAP struct {
 	userScope        int
 	userAttributeMap userAttributeMap
 
-	disableUserMechanism    DisableUserMechanismType
-	localUserDisableGroupDN string
-
 	groupBaseDN       string
 	groupFilter       string
 	groupObjectClass  string
@@ -82,17 +60,6 @@ type userAttributeMap struct {
 
 type ldapAttributeValues map[string][]string
 
-// ParseDisableMechanismType checks that the configuration option for how to disable users is correct.
-func ParseDisableMechanismType(disableMechanism string) (DisableUserMechanismType, error) {
-	disableMechanism = strings.ToLower(disableMechanism)
-	t, ok := mechanismMap[disableMechanism]
-	if !ok {
-		return -1, errors.New("invalid configuration option for disable user mechanism")
-	}
-
-	return t, nil
-}
-
 func NewLDAPBackend(lc ldap.Client, config config.LDAP, logger *log.Logger) (*LDAP, error) {
 	if config.UserDisplayNameAttribute == "" || config.UserIDAttribute == "" ||
 		config.UserEmailAttribute == "" || config.UserNameAttribute == "" {
@@ -104,8 +71,8 @@ func NewLDAPBackend(lc ldap.Client, config config.LDAP, logger *log.Logger) (*LD
 		mail:           config.UserEmailAttribute,
 		userName:       config.UserNameAttribute,
 		accountEnabled: config.UserEnabledAttribute,
-		givenName:      _givenNameAttribute,
-		surname:        _surNameAttribute,
+		givenName:      givenNameAttribute,
+		surname:        surNameAttribute,
 	}
 
 	if config.GroupNameAttribute == "" || config.GroupIDAttribute == "" {
@@ -114,7 +81,7 @@ func NewLDAPBackend(lc ldap.Client, config config.LDAP, logger *log.Logger) (*LD
 	gam := groupAttributeMap{
 		name:         config.GroupNameAttribute,
 		id:           config.GroupIDAttribute,
-		member:       _ldapGroupMemberAttribute,
+		member:       "member",
 		memberSyntax: "dn",
 	}
 
@@ -133,31 +100,24 @@ func NewLDAPBackend(lc ldap.Client, config config.LDAP, logger *log.Logger) (*LD
 		return nil, fmt.Errorf("error setting up education resource config: %w", err)
 	}
 
-	disableMechanismType, err := ParseDisableMechanismType(config.DisableUserMechanism)
-	if err != nil {
-		return nil, fmt.Errorf("error configuring disable user mechanism: %w", err)
-	}
-
 	return &LDAP{
-		useServerUUID:           config.UseServerUUID,
-		usePwModifyExOp:         config.UsePasswordModExOp,
-		userBaseDN:              config.UserBaseDN,
-		userFilter:              config.UserFilter,
-		userObjectClass:         config.UserObjectClass,
-		userScope:               userScope,
-		userAttributeMap:        uam,
-		groupBaseDN:             config.GroupBaseDN,
-		groupFilter:             config.GroupFilter,
-		groupObjectClass:        config.GroupObjectClass,
-		groupScope:              groupScope,
-		groupAttributeMap:       gam,
-		educationConfig:         educationConfig,
-		disableUserMechanism:    disableMechanismType,
-		localUserDisableGroupDN: config.LdapDisabledUsersGroupDN,
-		logger:                  logger,
-		conn:                    lc,
-		writeEnabled:            config.WriteEnabled,
-		refintEnabled:           config.RefintEnabled,
+		useServerUUID:     config.UseServerUUID,
+		usePwModifyExOp:   config.UsePasswordModExOp,
+		userBaseDN:        config.UserBaseDN,
+		userFilter:        config.UserFilter,
+		userObjectClass:   config.UserObjectClass,
+		userScope:         userScope,
+		userAttributeMap:  uam,
+		groupBaseDN:       config.GroupBaseDN,
+		groupFilter:       config.GroupFilter,
+		groupObjectClass:  config.GroupObjectClass,
+		groupScope:        groupScope,
+		groupAttributeMap: gam,
+		educationConfig:   educationConfig,
+		logger:            logger,
+		conn:              lc,
+		writeEnabled:      config.WriteEnabled,
+		refintEnabled:     config.RefintEnabled,
 	}, nil
 }
 
@@ -171,10 +131,6 @@ func (i *LDAP) CreateUser(ctx context.Context, user libregraph.User) (*libregrap
 		return nil, ErrReadOnly
 	}
 
-	if user.AccountEnabled != nil && i.disableUserMechanism == DisableMechanismNone {
-		return nil, errors.New("accountEnabled option not compatible with backend disable user mechanism")
-	}
-
 	ar, err := i.userToAddRequest(user)
 	if err != nil {
 		return nil, err
@@ -298,34 +254,14 @@ func (i *LDAP) UpdateUser(ctx context.Context, nameOrID string, user libregraph.
 		}
 	}
 
-	// Behavior of enabling/disabling of users depends on the "disableUserMechanism" config option:
-	//
-	// "attribute": For the upstream user management service which modifies accountEnabled on the user entry
-	// "group": Makes it possible for local admins to disable users by adding them to a special group
 	if user.AccountEnabled != nil {
-		switch i.disableUserMechanism {
-		case DisableMechanismNone:
-			return nil, errors.New("accountEnabled option not compatible with backend disable user mechanism")
-		case DisableMechanismAttribute:
-			boolString := strings.ToUpper(strconv.FormatBool(user.GetAccountEnabled()))
-			ldapValue := e.GetEqualFoldAttributeValue(i.userAttributeMap.accountEnabled)
-			if ldapValue != "" {
-				mr.Replace(i.userAttributeMap.accountEnabled, []string{boolString})
-			} else {
-				mr.Add(i.userAttributeMap.accountEnabled, []string{boolString})
-			}
-			updateNeeded = true
-		case DisableMechanismGroup:
-			if user.GetAccountEnabled() {
-				err = i.enableUser(logger, e.DN)
-			} else {
-				err = i.disableUser(logger, e.DN)
-			}
-
-			if err != nil {
-				return nil, err
-			}
-			updateNeeded = true
+		boolString := strings.ToUpper(strconv.FormatBool(*user.AccountEnabled))
+		ldapValue := e.GetEqualFoldAttributeValue(i.userAttributeMap.accountEnabled)
+		updateNeeded = true
+		if ldapValue != "" {
+			mr.Replace(i.userAttributeMap.accountEnabled, []string{boolString})
+		} else {
+			mr.Add(i.userAttributeMap.accountEnabled, []string{boolString})
 		}
 	}
 
@@ -340,16 +276,7 @@ func (i *LDAP) UpdateUser(ctx context.Context, nameOrID string, user libregraph.
 	if err != nil {
 		return nil, err
 	}
-
-	returnUser := i.createUserModelFromLDAP(e)
-
-	// To avoid an ldap lookup for group membership, set the enabled flag to same as input value
-	// since this would have been updated with group membership from the input anyway.
-	if user.AccountEnabled != nil && i.disableUserMechanism != DisableMechanismNone {
-		returnUser.AccountEnabled = user.AccountEnabled
-	}
-
-	return returnUser, nil
+	return i.createUserModelFromLDAP(e), nil
 }
 
 func (i *LDAP) getUserByDN(dn string) (*ldap.Entry, error) {
@@ -393,7 +320,7 @@ func (i *LDAP) getEntryByDN(dn string, attrs []string, filter string) (*ldap.Ent
 		Msg("getEntryByDN")
 	res, err := i.conn.Search(searchRequest)
 	if err != nil {
-		i.logger.Error().Err(err).Str("backend", "ldap").Str("dn", dn).Msg("Search ldap by DN failed")
+		i.logger.Error().Err(err).Str("backend", "ldap").Str("dn", dn).Msg("Search user by DN failed")
 		return nil, errorcode.New(errorcode.ItemNotFound, err.Error())
 	}
 	if len(res.Entries) == 0 {
@@ -477,13 +404,6 @@ func (i *LDAP) GetUser(ctx context.Context, nameOrID string, oreq *godata.GoData
 		return nil, ErrNotFound
 	}
 
-	if i.disableUserMechanism != DisableMechanismNone {
-		userEnabled, err := i.UserEnabled(e)
-		if err == nil {
-			u.AccountEnabled = &userEnabled
-		}
-	}
-
 	exp, err := GetExpandValues(oreq.Query)
 	if err != nil {
 		return nil, err
@@ -552,10 +472,6 @@ func (i *LDAP) GetUsers(ctx context.Context, oreq *godata.GoDataRequest) ([]*lib
 	}
 
 	users := make([]*libregraph.User, 0, len(res.Entries))
-	usersEnabledState, err := i.usersEnabledState(res.Entries)
-	if err != nil {
-		return nil, err
-	}
 
 	for _, e := range res.Entries {
 		u := i.createUserModelFromLDAP(e)
@@ -563,12 +479,6 @@ func (i *LDAP) GetUsers(ctx context.Context, oreq *godata.GoDataRequest) ([]*lib
 		if u == nil {
 			continue
 		}
-
-		if i.disableUserMechanism != DisableMechanismNone {
-			userEnabled := usersEnabledState[e.DN]
-			u.AccountEnabled = &userEnabled
-		}
-
 		if slices.Contains(exp, "memberOf") {
 			userGroups, err := i.getGroupsForUser(e.DN)
 			if err != nil {
@@ -892,135 +802,3 @@ func replaceDN(fullDN *ldap.DN, newDN string) (string, error) {
 
 	return newDN, nil
 }
-
-// CreateLDAPGroupByDN is a helper method specifically intended for creating a "system" group
-// for managing locally disabled users on service startup
-func (i *LDAP) CreateLDAPGroupByDN(dn string) error {
-	ar := ldap.NewAddRequest(dn, nil)
-
-	attrs := map[string][]string{
-		"objectClass": {"groupOfNames", "top"},
-		"member":      {""},
-	}
-
-	for attrType, values := range attrs {
-		ar.Attribute(attrType, values)
-	}
-
-	return i.conn.Add(ar)
-}
-
-func (i *LDAP) disableUser(logger log.Logger, userDN string) (err error) {
-	group, err := i.getEntryByDN(i.localUserDisableGroupDN, []string{_ldapGroupMemberAttribute}, _ldapGroupOfNamesAttribute)
-
-	if err != nil {
-		return err
-	}
-
-	mr := ldap.ModifyRequest{DN: group.DN}
-	mr.Add(_ldapGroupMemberAttribute, []string{userDN})
-
-	err = i.conn.Modify(&mr)
-	var lerr *ldap.Error
-	if errors.As(err, &lerr) {
-		// If the user is already in the group, just log a message and return
-		if lerr.ResultCode == ldap.LDAPResultAttributeOrValueExists {
-			logger.Info().Msg("User already in group for disabled users")
-			return nil
-		}
-	}
-
-	return err
-}
-
-func (i *LDAP) enableUser(logger log.Logger, userDN string) (err error) {
-	group, err := i.getEntryByDN(i.localUserDisableGroupDN, []string{_ldapGroupMemberAttribute}, _ldapGroupOfNamesAttribute)
-
-	if err != nil {
-		return err
-	}
-
-	mr := ldap.ModifyRequest{DN: group.DN}
-	mr.Delete(_ldapGroupMemberAttribute, []string{userDN})
-
-	err = i.conn.Modify(&mr)
-	var lerr *ldap.Error
-	if errors.As(err, &lerr) {
-		// If the user is not in the group, just log a message and return
-		if lerr.ResultCode == ldap.LDAPResultNoSuchAttribute {
-			logger.Info().Msg("User was not in group for disabled users")
-			return nil
-		}
-	}
-
-	return err
-}
-
-func (i *LDAP) userEnabledByAttribute(user *ldap.Entry) bool {
-	enabledAttribute := booleanOrNil(user.GetEqualFoldAttributeValue(i.userAttributeMap.accountEnabled))
-
-	if enabledAttribute == nil {
-		return true
-	}
-
-	return *enabledAttribute
-}
-
-func (i *LDAP) usersEnabledStateFromGroup(users []string) (usersEnabledState map[string]bool, err error) {
-	group, err := i.getEntryByDN(i.localUserDisableGroupDN, []string{_ldapGroupMemberAttribute}, _ldapGroupOfNamesAttribute)
-
-	if err != nil {
-		return nil, err
-	}
-
-	usersEnabledState = make(map[string]bool, len(users))
-	for _, user := range users {
-		usersEnabledState[user] = true
-	}
-
-	for _, memberDN := range group.GetEqualFoldAttributeValues(_ldapGroupMemberAttribute) {
-		usersEnabledState[memberDN] = false
-	}
-
-	return usersEnabledState, err
-}
-
-// UserEnabled returns if a user is enabled. This can depend on a flag in the user entry or group membership
-func (i *LDAP) UserEnabled(user *ldap.Entry) (bool, error) {
-	usersEnabledState, err := i.usersEnabledState([]*ldap.Entry{user})
-
-	if err != nil {
-		return false, err
-	}
-
-	return usersEnabledState[user.DN], nil
-}
-
-func (i *LDAP) usersEnabledState(users []*ldap.Entry) (usersEnabledState map[string]bool, err error) {
-	usersEnabledState = make(map[string]bool, len(users))
-	keys := make([]string, len(users))
-	for index, user := range users {
-		usersEnabledState[user.DN] = true
-		keys[index] = user.DN
-	}
-
-	switch i.disableUserMechanism {
-	case DisableMechanismAttribute:
-		for _, user := range users {
-			usersEnabledState[user.DN] = i.userEnabledByAttribute(user)
-		}
-
-	case DisableMechanismGroup:
-		userDisabledGroupState, err := i.usersEnabledStateFromGroup(keys)
-
-		if err != nil {
-			return nil, err
-		}
-
-		for _, user := range keys {
-			usersEnabledState[user] = userDisabledGroupState[user]
-		}
-	}
-
-	return usersEnabledState, nil
-}
diff --git a/services/graph/pkg/server/http/server.go b/services/graph/pkg/server/http/server.go
index 6f6965630f1..02a7f177a44 100644
--- a/services/graph/pkg/server/http/server.go
+++ b/services/graph/pkg/server/http/server.go
@@ -114,7 +114,7 @@ func Server(opts ...Option) (http.Service, error) {
 			return http.Service{}, errors.Wrap(err, "could not initialize gateway client")
 		}
 	} else {
-		middlewares = append(middlewares, graphMiddleware.Token(options.Config.HTTP.APIToken))
+		middlewares = append(middlewares, middleware.Token(options.Config.HTTP.APIToken))
 		// use a dummy admin middleware for the chi router
 		requireAdminMiddleware = func(next stdhttp.Handler) stdhttp.Handler {
 			return next
diff --git a/services/graph/pkg/service/v0/service.go b/services/graph/pkg/service/v0/service.go
index e1233661336..9cc30c0ba90 100644
--- a/services/graph/pkg/service/v0/service.go
+++ b/services/graph/pkg/service/v0/service.go
@@ -3,7 +3,6 @@ package svc
 import (
 	"crypto/tls"
 	"crypto/x509"
-	"errors"
 	"fmt"
 	"net/http"
 	"os"
@@ -13,7 +12,6 @@ import (
 
 	"github.com/go-chi/chi/v5"
 	"github.com/go-chi/chi/v5/middleware"
-	ldapv3 "github.com/go-ldap/ldap/v3"
 	"github.com/jellydator/ttlcache/v3"
 	libregraph "github.com/owncloud/libre-graph-api-go"
 	ocisldap "github.com/owncloud/ocis/v2/ocis-pkg/ldap"
@@ -368,35 +366,6 @@ func setIdentityBackends(options Options, svc *Graph) error {
 					svc.identityEducationBackend = errEduBackend
 				}
 			}
-
-			disableMechanismType, err := identity.ParseDisableMechanismType(options.Config.Identity.LDAP.DisableUserMechanism)
-			if err != nil {
-				options.Logger.Error().Err(err).Msg("Error initializing LDAP Backend")
-				return err
-			}
-
-			if disableMechanismType == identity.DisableMechanismGroup {
-				options.Logger.Info().Msg("LocalUserDisable is true, will create group if not exists")
-				err := lb.CreateLDAPGroupByDN(options.Config.Identity.LDAP.LdapDisabledUsersGroupDN)
-				if err != nil {
-					isAnError := false
-					var lerr *ldapv3.Error
-					if errors.As(err, &lerr) {
-						if lerr.ResultCode != ldapv3.LDAPResultEntryAlreadyExists {
-							isAnError = true
-						}
-					} else {
-						isAnError = true
-					}
-
-					if isAnError {
-						msg := "error adding group for disabling users"
-						options.Logger.Error().Err(err).Str("local_user_disable", options.Config.Identity.LDAP.LdapDisabledUsersGroupDN).Msg(msg)
-						return err
-					}
-				}
-			}
-
 		default:
 			err := fmt.Errorf("unknown identity backend: '%s'", options.Config.Identity.Backend)
 			options.Logger.Err(err)
diff --git a/services/web/pkg/service/v0/branding.go b/services/web/pkg/service/v0/branding.go
index afc8592df85..25a2746a4ed 100644
--- a/services/web/pkg/service/v0/branding.go
+++ b/services/web/pkg/service/v0/branding.go
@@ -167,37 +167,34 @@ func (p Web) updateLogoThemeConfig(logoPath string) error {
 	var m map[string]interface{}
 	_ = json.NewDecoder(f).Decode(&m)
 
-	webCfg, ok := m["web"].(map[string]interface{})
-	if !ok {
-		return errInvalidThemeConfig
-	}
-
-	defaultCfg, ok := webCfg["default"].(map[string]interface{})
+	// change logo in common part
+	commonCfg, ok := m["common"].(map[string]interface{})
 	if !ok {
 		return errInvalidThemeConfig
 	}
+	commonCfg["logo"] = logoPath
 
-	logoCfg, ok := defaultCfg["logo"].(map[string]interface{})
+	webCfg, ok := m["web"].(map[string]interface{})
 	if !ok {
 		return errInvalidThemeConfig
 	}
 
-	logoCfg["login"] = logoPath
-	logoCfg["topbar"] = logoPath
+	// iterate over all possible themes and replace logo
+	for theme := range webCfg {
+		themeCfg, ok := webCfg[theme].(map[string]interface{})
+		if !ok {
+			return errInvalidThemeConfig
+		}
 
-	defaultDarkCfg, ok := webCfg["default-dark"].(map[string]interface{})
-	if !ok {
-		return errInvalidThemeConfig
-	}
+		logoCfg, ok := themeCfg["logo"].(map[string]interface{})
+		if !ok {
+			return errInvalidThemeConfig
+		}
 
-	logoDarkCfg, ok := defaultDarkCfg["logo"].(map[string]interface{})
-	if !ok {
-		return errInvalidThemeConfig
+		logoCfg["login"] = logoPath
+		logoCfg["topbar"] = logoPath
 	}
 
-	logoDarkCfg["login"] = logoPath
-	logoDarkCfg["topbar"] = logoPath
-
 	dst, err := p.fs.Create(_themesConfigPath)
 	if err != nil {
 		return err


Test patch:
diff --git a/services/graph/pkg/identity/ldap_test.go b/services/graph/pkg/identity/ldap_test.go
index bf99dca8160..04f5f479f23 100644
--- a/services/graph/pkg/identity/ldap_test.go
+++ b/services/graph/pkg/identity/ldap_test.go
@@ -21,11 +21,6 @@ func getMockedBackend(l ldap.Client, lc config.LDAP, logger *log.Logger) (*LDAP,
 	return NewLDAPBackend(l, lc, logger)
 }
 
-const (
-	disableUsersGroup = "cn=DisabledUsersGroup,ou=groups,o=testing"
-	groupSearchFilter = "(objectClass=groupOfNames)"
-)
-
 var lconfig = config.LDAP{
 	UserBaseDN:               "ou=people,dc=test",
 	UserObjectClass:          "inetOrgPerson",
@@ -36,8 +31,6 @@ var lconfig = config.LDAP{
 	UserEmailAttribute:       "mail",
 	UserNameAttribute:        "uid",
 	UserEnabledAttribute:     "userEnabledAttribute",
-	LdapDisabledUsersGroupDN: disableUsersGroup,
-	DisableUserMechanism:     "attribute",
 
 	GroupBaseDN:        "ou=groups,dc=test",
 	GroupObjectClass:   "groupOfNames",
@@ -292,20 +285,16 @@ func TestGetUsers(t *testing.T) {
 }
 
 func TestUpdateUser(t *testing.T) {
-	falseBool := false
-	trueBool := true
-
 	type userProps struct {
 		id                       string
 		mail                     string
 		displayName              string
 		onPremisesSamAccountName string
-		accountEnabled           *bool
+		accountEnabled           bool
 	}
 	type args struct {
-		nameOrID             string
-		userProps            userProps
-		disableUserMechanism string
+		nameOrID  string
+		userProps userProps
 	}
 	type mockInputs struct {
 		funcName string
@@ -370,7 +359,7 @@ func TestUpdateUser(t *testing.T) {
 				mail:                     "testuser@example.org",
 				displayName:              "testUser",
 				onPremisesSamAccountName: "testUser",
-				accountEnabled:           nil,
+				accountEnabled:           true,
 			},
 			assertion: func(t assert.TestingT, err error, args ...interface{}) bool {
 				return assert.Nil(t, err, args...)
@@ -408,7 +397,7 @@ func TestUpdateUser(t *testing.T) {
 										},
 										{
 											Name:   lconfig.UserEnabledAttribute,
-											Values: []string{""},
+											Values: []string{"TRUE"},
 										},
 									},
 								},
@@ -456,7 +445,7 @@ func TestUpdateUser(t *testing.T) {
 										},
 										{
 											Name:   lconfig.UserEnabledAttribute,
-											Values: []string{""},
+											Values: []string{"TRUE"},
 										},
 									},
 								},
@@ -499,7 +488,7 @@ func TestUpdateUser(t *testing.T) {
 				mail:                     "testuser@example.org",
 				displayName:              "newName",
 				onPremisesSamAccountName: "testUser",
-				accountEnabled:           nil,
+				accountEnabled:           true,
 			},
 			assertion: func(t assert.TestingT, err error, args ...interface{}) bool {
 				return assert.Nil(t, err, args...)
@@ -537,7 +526,7 @@ func TestUpdateUser(t *testing.T) {
 										},
 										{
 											Name:   lconfig.UserEnabledAttribute,
-											Values: []string{""},
+											Values: []string{"TRUE"},
 										},
 									},
 								},
@@ -585,7 +574,7 @@ func TestUpdateUser(t *testing.T) {
 										},
 										{
 											Name:   lconfig.UserEnabledAttribute,
-											Values: []string{""},
+											Values: []string{"TRUE"},
 										},
 									},
 								},
@@ -628,7 +617,7 @@ func TestUpdateUser(t *testing.T) {
 				mail:                     "testuser@example.org",
 				displayName:              "newName",
 				onPremisesSamAccountName: "newName",
-				accountEnabled:           nil,
+				accountEnabled:           true,
 			},
 			assertion: func(t assert.TestingT, err error, args ...interface{}) bool {
 				return assert.Nil(t, err, args...)
@@ -670,7 +659,7 @@ func TestUpdateUser(t *testing.T) {
 										},
 										{
 											Name:   lconfig.UserEnabledAttribute,
-											Values: []string{""},
+											Values: []string{"TRUE"},
 										},
 									},
 								},
@@ -766,7 +755,7 @@ func TestUpdateUser(t *testing.T) {
 										},
 										{
 											Name:   lconfig.UserEnabledAttribute,
-											Values: []string{""},
+											Values: []string{"TRUE"},
 										},
 									},
 								},
@@ -808,16 +797,15 @@ func TestUpdateUser(t *testing.T) {
 			args: args{
 				nameOrID: "testUser",
 				userProps: userProps{
-					accountEnabled: &falseBool,
+					accountEnabled: false,
 				},
-				disableUserMechanism: "attribute",
 			},
 			want: &userProps{
 				id:                       "testUser",
 				mail:                     "testuser@example.org",
 				displayName:              "testUser",
 				onPremisesSamAccountName: "testUser",
-				accountEnabled:           &falseBool,
+				accountEnabled:           false,
 			},
 			assertion: func(t assert.TestingT, err error, args ...interface{}) bool {
 				return assert.Nil(t, err, args...)
@@ -933,338 +921,6 @@ func TestUpdateUser(t *testing.T) {
 				},
 			},
 		},
-		{
-			name: "Test disabling user as local admin",
-			args: args{
-				nameOrID: "testUser",
-				userProps: userProps{
-					accountEnabled: &falseBool,
-				},
-				disableUserMechanism: "group",
-			},
-			want: &userProps{
-				id:                       "testUser",
-				mail:                     "testuser@example.org",
-				displayName:              "testUser",
-				onPremisesSamAccountName: "testUser",
-				accountEnabled:           &falseBool,
-			},
-			assertion: func(t assert.TestingT, err error, args ...interface{}) bool {
-				return assert.Nil(t, err, args...)
-			},
-			ldapMocks: []mockInputs{
-				{
-					funcName: "Search",
-					args: []interface{}{
-						ldap.NewSearchRequest(
-							"ou=people,dc=test",
-							ldap.ScopeWholeSubtree,
-							ldap.NeverDerefAliases, 1, 0, false,
-							"(&(objectClass=inetOrgPerson)(|(uid=testUser)(entryUUID=testUser)))",
-							[]string{"displayname", "entryUUID", "mail", "uid", "sn", "givenname", "userEnabledAttribute"},
-							nil,
-						),
-					},
-					returns: []interface{}{
-						&ldap.SearchResult{
-							Entries: []*ldap.Entry{
-								{
-									DN: "uid=name",
-									Attributes: []*ldap.EntryAttribute{
-										{
-											Name:   "displayname",
-											Values: []string{"testuser@example.org"},
-										},
-										{
-											Name:   "entryUUID",
-											Values: []string{"testUser"},
-										},
-										{
-											Name:   "mail",
-											Values: []string{"testuser@example.org"},
-										},
-										{
-											Name:   lconfig.UserEnabledAttribute,
-											Values: []string{"TRUE"},
-										},
-									},
-								},
-							},
-						},
-						nil,
-					},
-				},
-				{
-					funcName: "Search",
-					args: []interface{}{
-						&ldap.SearchRequest{
-							BaseDN:       disableUsersGroup,
-							Scope:        0,
-							DerefAliases: 0,
-							SizeLimit:    1,
-							TimeLimit:    0,
-							TypesOnly:    false,
-							Filter:       groupSearchFilter,
-							Attributes:   []string{"member"},
-							Controls:     []ldap.Control(nil),
-						},
-					},
-					returns: []interface{}{
-						&ldap.SearchResult{
-							Entries: []*ldap.Entry{
-								{
-									DN: "uid=name",
-									Attributes: []*ldap.EntryAttribute{
-										{
-											Name:   "member",
-											Values: []string{""},
-										},
-									},
-								},
-							},
-						},
-						nil,
-					},
-				},
-				{
-					funcName: "Modify",
-					args: []interface{}{
-						&ldap.ModifyRequest{
-							DN: "uid=name",
-							Changes: []ldap.Change{
-								{
-									Operation: ldap.AddAttribute,
-									Modification: ldap.PartialAttribute{
-										Type: "member",
-										Vals: []string{"uid=name"},
-									},
-								},
-							},
-							Controls: []ldap.Control(nil),
-						},
-					},
-					returns: []interface{}{nil},
-				},
-				{
-					funcName: "Modify",
-					args: []interface{}{
-						&ldap.ModifyRequest{
-							DN:       "uid=name",
-							Changes:  []ldap.Change(nil),
-							Controls: []ldap.Control(nil),
-						},
-					},
-					returns: []interface{}{nil},
-				},
-				{
-					funcName: "Search",
-					args: []interface{}{
-						ldap.NewSearchRequest(
-							"uid=name",
-							ldap.ScopeBaseObject,
-							ldap.NeverDerefAliases, 1, 0, false,
-							"(objectClass=inetOrgPerson)",
-							[]string{"displayname", "entryUUID", "mail", "uid", "sn", "givenname", "userEnabledAttribute"},
-							[]ldap.Control(nil),
-						),
-					},
-					returns: []interface{}{
-						&ldap.SearchResult{
-							Entries: []*ldap.Entry{
-								{
-									DN: "uid=name",
-									Attributes: []*ldap.EntryAttribute{
-										{
-											Name:   "uid",
-											Values: []string{"testUser"},
-										},
-										{
-											Name:   "displayname",
-											Values: []string{"testUser"},
-										},
-										{
-											Name:   "entryUUID",
-											Values: []string{"testUser"},
-										},
-										{
-											Name:   "mail",
-											Values: []string{"testuser@example.org"},
-										},
-									},
-								},
-							},
-						},
-						nil,
-					},
-				},
-			},
-		},
-		{
-			name: "Test enabling user as local admin",
-			args: args{
-				nameOrID: "testUser",
-				userProps: userProps{
-					accountEnabled: &trueBool,
-				},
-				disableUserMechanism: "group",
-			},
-			want: &userProps{
-				id:                       "testUser",
-				mail:                     "testuser@example.org",
-				displayName:              "testUser",
-				onPremisesSamAccountName: "testUser",
-				accountEnabled:           &trueBool,
-			},
-			assertion: func(t assert.TestingT, err error, args ...interface{}) bool {
-				return assert.Nil(t, err, args...)
-			},
-			ldapMocks: []mockInputs{
-				{
-					funcName: "Search",
-					args: []interface{}{
-						ldap.NewSearchRequest(
-							"ou=people,dc=test",
-							ldap.ScopeWholeSubtree,
-							ldap.NeverDerefAliases, 1, 0, false,
-							"(&(objectClass=inetOrgPerson)(|(uid=testUser)(entryUUID=testUser)))",
-							[]string{"displayname", "entryUUID", "mail", "uid", "sn", "givenname", "userEnabledAttribute"},
-							nil,
-						),
-					},
-					returns: []interface{}{
-						&ldap.SearchResult{
-							Entries: []*ldap.Entry{
-								{
-									DN: "uid=name",
-									Attributes: []*ldap.EntryAttribute{
-										{
-											Name:   "displayname",
-											Values: []string{"testuser@example.org"},
-										},
-										{
-											Name:   "entryUUID",
-											Values: []string{"testUser"},
-										},
-										{
-											Name:   "mail",
-											Values: []string{"testuser@example.org"},
-										},
-										{
-											Name:   lconfig.UserEnabledAttribute,
-											Values: []string{"TRUE"},
-										},
-									},
-								},
-							},
-						},
-						nil,
-					},
-				},
-				{
-					funcName: "Search",
-					args: []interface{}{
-						&ldap.SearchRequest{
-							BaseDN:       disableUsersGroup,
-							Scope:        0,
-							DerefAliases: 0,
-							SizeLimit:    1,
-							TimeLimit:    0,
-							TypesOnly:    false,
-							Filter:       groupSearchFilter,
-							Attributes:   []string{"member"},
-							Controls:     []ldap.Control(nil),
-						},
-					},
-					returns: []interface{}{
-						&ldap.SearchResult{
-							Entries: []*ldap.Entry{
-								{
-									DN: "uid=name",
-									Attributes: []*ldap.EntryAttribute{
-										{
-											Name:   "member",
-											Values: []string{""},
-										},
-									},
-								},
-							},
-						},
-						nil,
-					},
-				},
-				{
-					funcName: "Modify",
-					args: []interface{}{
-						&ldap.ModifyRequest{
-							DN: "uid=name",
-							Changes: []ldap.Change{
-								{
-									Operation: ldap.DeleteAttribute,
-									Modification: ldap.PartialAttribute{
-										Type: "member",
-										Vals: []string{"uid=name"},
-									},
-								},
-							},
-							Controls: []ldap.Control(nil),
-						},
-					},
-					returns: []interface{}{nil},
-				},
-				{
-					funcName: "Modify",
-					args: []interface{}{
-						&ldap.ModifyRequest{
-							DN:       "uid=name",
-							Changes:  []ldap.Change(nil),
-							Controls: []ldap.Control(nil),
-						},
-					},
-					returns: []interface{}{nil},
-				},
-				{
-					funcName: "Search",
-					args: []interface{}{
-						ldap.NewSearchRequest(
-							"uid=name",
-							ldap.ScopeBaseObject,
-							ldap.NeverDerefAliases, 1, 0, false,
-							"(objectClass=inetOrgPerson)",
-							[]string{"displayname", "entryUUID", "mail", "uid", "sn", "givenname", "userEnabledAttribute"},
-							[]ldap.Control(nil),
-						),
-					},
-					returns: []interface{}{
-						&ldap.SearchResult{
-							Entries: []*ldap.Entry{
-								{
-									DN: "uid=name",
-									Attributes: []*ldap.EntryAttribute{
-										{
-											Name:   "uid",
-											Values: []string{"testUser"},
-										},
-										{
-											Name:   "displayname",
-											Values: []string{"testUser"},
-										},
-										{
-											Name:   "entryUUID",
-											Values: []string{"testUser"},
-										},
-										{
-											Name:   "mail",
-											Values: []string{"testuser@example.org"},
-										},
-									},
-								},
-							},
-						},
-						nil,
-					},
-				},
-			},
-		},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
@@ -1272,17 +928,13 @@ func TestUpdateUser(t *testing.T) {
 			for _, mock := range tt.ldapMocks {
 				lm.On(mock.funcName, mock.args...).Return(mock.returns...)
 			}
-
-			ldapConfig := lconfig
-			ldapConfig.DisableUserMechanism = tt.args.disableUserMechanism
-			i, _ := getMockedBackend(lm, ldapConfig, &logger)
+			i, _ := getMockedBackend(lm, lconfig, &logger)
 
 			user := libregraph.User{
 				Id:                       &tt.args.userProps.id,
 				Mail:                     &tt.args.userProps.mail,
 				DisplayName:              &tt.args.userProps.displayName,
 				OnPremisesSamAccountName: &tt.args.userProps.onPremisesSamAccountName,
-				AccountEnabled:           tt.args.userProps.accountEnabled,
 			}
 
 			emptyString := ""
@@ -1295,10 +947,7 @@ func TestUpdateUser(t *testing.T) {
 					OnPremisesSamAccountName: &tt.want.onPremisesSamAccountName,
 					Surname:                  &emptyString,
 					GivenName:                &emptyString,
-				}
-
-				if tt.want.accountEnabled != nil {
-					want.AccountEnabled = *&tt.want.accountEnabled
+					AccountEnabled:           &tt.want.accountEnabled,
 				}
 			}
 
@@ -1308,214 +957,3 @@ func TestUpdateUser(t *testing.T) {
 		})
 	}
 }
-
-func TestUsersEnabledState(t *testing.T) {
-	aliceEnabled := ldap.Entry{
-		DN: "alice",
-		Attributes: []*ldap.EntryAttribute{
-			{
-				Name:   lconfig.UserEnabledAttribute,
-				Values: []string{"TRUE"},
-			},
-		},
-	}
-
-	bobDisabled := ldap.Entry{
-		DN: "bob",
-		Attributes: []*ldap.EntryAttribute{
-			{
-				Name:   lconfig.UserEnabledAttribute,
-				Values: []string{"FALSE"},
-			},
-		},
-	}
-
-	carolImplicitlyEnabled := ldap.Entry{
-		DN: "carol",
-		Attributes: []*ldap.EntryAttribute{
-			{
-				Name: lconfig.UserEnabledAttribute,
-			},
-		},
-	}
-
-	type args struct {
-		usersToCheck         []*ldap.Entry
-		expectedUsers        map[string]bool
-		disableUserMechanism string
-	}
-	type mockInputs struct {
-		funcName string
-		args     []interface{}
-		returns  []interface{}
-	}
-	tests := []struct {
-		name      string
-		args      args
-		want      map[string]bool
-		assertion assert.ErrorAssertionFunc
-		ldapMocks []mockInputs
-	}{
-		{
-			name: "Test no users",
-			args: args{
-				usersToCheck:         []*ldap.Entry{},
-				expectedUsers:        map[string]bool{},
-				disableUserMechanism: "attribute",
-			},
-			want: map[string]bool{},
-			assertion: func(t assert.TestingT, err error, args ...interface{}) bool {
-				return assert.Nil(t, err, args...)
-			},
-			ldapMocks: []mockInputs{},
-		},
-		{
-			name: "Test attribute enabled users",
-			args: args{
-				usersToCheck:         []*ldap.Entry{&aliceEnabled, &bobDisabled, &carolImplicitlyEnabled},
-				expectedUsers:        map[string]bool{"alice": true, "bob": false, "carol": true},
-				disableUserMechanism: "attribute",
-			},
-			want: map[string]bool{"alice": true, "bob": false, "carol": true},
-			assertion: func(t assert.TestingT, err error, args ...interface{}) bool {
-				return assert.Nil(t, err, args...)
-			},
-			ldapMocks: []mockInputs{},
-		},
-		{
-			name: "Test attribute enabled users not in disabled group",
-			args: args{
-				usersToCheck:         []*ldap.Entry{&aliceEnabled, &bobDisabled, &carolImplicitlyEnabled},
-				expectedUsers:        map[string]bool{"alice": true, "bob": false, "carol": true},
-				disableUserMechanism: "group",
-			},
-			want: map[string]bool{"alice": true, "bob": true, "carol": true},
-			assertion: func(t assert.TestingT, err error, args ...interface{}) bool {
-				return assert.Nil(t, err, args...)
-			},
-			ldapMocks: []mockInputs{
-				{
-					funcName: "Search",
-					args: []interface{}{
-						ldap.NewSearchRequest(
-							disableUsersGroup,
-							ldap.ScopeBaseObject,
-							ldap.NeverDerefAliases, 1, 0, false,
-							groupSearchFilter,
-							[]string{"member"},
-							[]ldap.Control(nil),
-						),
-					},
-					returns: []interface{}{
-						&ldap.SearchResult{
-							Entries: []*ldap.Entry{
-								{
-									DN: "cn=DisabledGroup",
-									Attributes: []*ldap.EntryAttribute{
-										{
-											Name:   "member",
-											Values: []string{""},
-										},
-									},
-								},
-							},
-						},
-						nil,
-					},
-				},
-			},
-		},
-		{
-			name: "Test attribute enabled users in disabled group",
-			args: args{
-				usersToCheck:         []*ldap.Entry{&aliceEnabled, &bobDisabled, &carolImplicitlyEnabled},
-				expectedUsers:        map[string]bool{"alice": true, "bob": false, "carol": true},
-				disableUserMechanism: "group",
-			},
-			want: map[string]bool{"alice": false, "bob": true, "carol": false},
-			assertion: func(t assert.TestingT, err error, args ...interface{}) bool {
-				return assert.Nil(t, err, args...)
-			},
-			ldapMocks: []mockInputs{
-				{
-					funcName: "Search",
-					args: []interface{}{
-						ldap.NewSearchRequest(
-							disableUsersGroup,
-							ldap.ScopeBaseObject,
-							ldap.NeverDerefAliases, 1, 0, false,
-							groupSearchFilter,
-							[]string{"member"},
-							[]ldap.Control(nil),
-						),
-					},
-					returns: []interface{}{
-						&ldap.SearchResult{
-							Entries: []*ldap.Entry{
-								{
-									DN: "cn=DisabledGroup",
-									Attributes: []*ldap.EntryAttribute{
-										{
-											Name:   "member",
-											Values: []string{"alice", "carol"},
-										},
-									},
-								},
-							},
-						},
-						nil,
-					},
-				},
-			},
-		},
-		{
-			name: "Test local group disable when ldap is throwing error",
-			args: args{
-				usersToCheck:         []*ldap.Entry{&aliceEnabled, &bobDisabled, &carolImplicitlyEnabled},
-				expectedUsers:        map[string]bool{"alice": true, "bob": false, "carol": true},
-				disableUserMechanism: "group",
-			},
-			want: nil,
-			assertion: func(t assert.TestingT, err error, args ...interface{}) bool {
-				return assert.NotNil(t, err, args...)
-			},
-			ldapMocks: []mockInputs{
-				{
-					funcName: "Search",
-					args: []interface{}{
-						ldap.NewSearchRequest(
-							disableUsersGroup,
-							ldap.ScopeBaseObject,
-							ldap.NeverDerefAliases, 1, 0, false,
-							groupSearchFilter,
-							[]string{"member"},
-							[]ldap.Control(nil),
-						),
-					},
-					returns: []interface{}{
-						nil,
-						&ldap.Error{
-							Err: fmt.Errorf("Very Problematic Problems"),
-						},
-					},
-				},
-			},
-		},
-	}
-	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			lm := &mocks.Client{}
-			for _, mock := range tt.ldapMocks {
-				lm.On(mock.funcName, mock.args...).Return(mock.returns...)
-			}
-
-			ldapConfig := lconfig
-			ldapConfig.DisableUserMechanism = tt.args.disableUserMechanism
-			i, _ := getMockedBackend(lm, ldapConfig, &logger)
-
-			got, err := i.usersEnabledState(tt.args.usersToCheck)
-			tt.assertion(t, err)
-			assert.Equal(t, tt.want, got)
-		})
-	}
-}