Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
699e9a5
Merge pull request #6926 from devtron-labs/release-candidate-v0.45.0
vikramdevtron Feb 27, 2026
27e592f
vendor files
prkhrkat Feb 27, 2026
e3ddc14
Merge pull request #6927 from devtron-labs/main-vendor
prkhrkat Feb 27, 2026
37b07f1
feat: auto assign permission group (#6923)
SATYAsasini Feb 27, 2026
634eb59
fix: global auth apis wire register for ea mode (#6929)
SATYAsasini Mar 3, 2026
96ccd33
release: PR for v2.1.0 (#6928)
systemsdt Mar 3, 2026
001eaae
add support of container name in cronjob
Mar 11, 2026
e1cfcd6
fix: clusterId check for modifying triggers for cluster level notific…
SATYAsasini Mar 11, 2026
1188d0b
fix: auto assign permission group related fixes (#6934)
SATYAsasini Mar 17, 2026
83d6f9d
Merge branch 'main' into cronjob-chart_1-6-0
ajaydevtron Mar 18, 2026
ca36db6
Merge pull request #6931 from devtron-labs/cronjob-chart_1-6-0
ajaydevtron Mar 19, 2026
29cc689
feat: update app listing tag filter payload and operators
mayank-devtron Mar 16, 2026
f2e20a3
feat: refine tag negative operators behavior
mayank-devtron Mar 16, 2026
6b00aa2
jsontag
mayank-devtron Mar 18, 2026
ab2c0e0
migration renaming
mayank-devtron Mar 18, 2026
c0b293d
refactor app list tag-filter validation
mayank-devtron Mar 18, 2026
c13898f
feat: add tag filter support in app listing
mayank-devtron Mar 20, 2026
2b40f10
chore: add logs for app listing query builder errors
mayank-devtron Mar 20, 2026
0548faf
fix: correct app label filter migration sequence
mayank-devtron Mar 23, 2026
684875d
rename migration no
mayank-devtron Mar 24, 2026
8c52e28
release: PR for v2.1.1 (#6940)
systemsdt Mar 24, 2026
249bf41
sync: migration seq (#6942)
SATYAsasini Mar 25, 2026
dad89c0
renamed migration no
mayank-devtron Mar 25, 2026
2eb0efe
Merge branch 'main' into feat/app-filter-enhancement
mayank-devtron Mar 25, 2026
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
14 changes: 14 additions & 0 deletions CHANGELOG/release-notes-v2.1.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
## v2.1.0

## Enhancements
- feat: auto assign permission group ( https://github.com/devtron-labs/devtron/issues/6911 )
## Bugs
- fix: prevent exposure of internal-only attributes in API responses and requests (#6917)
- fix: append filtered cluster details to the cluster detail list in capacity handler (#6915)
- fix: enhance cluster overview response with raw cluster capacity details and caching support (#6914)
- fix: Handle cluster capacity fetch errors by returning detailed connection failure status (#6912)
## Others
- sync: main (#6920)
- chore: Adds scarf pixel (#6918)
- misc: add clientIP in audit log (#6908)
- misc: Refactor vulnerability query implementation and cleanup unused code (#6907)
5 changes: 5 additions & 0 deletions CHANGELOG/release-notes-v2.1.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## v2.1.1

## Bugs
- fix: auto assign permission group related fixes (#6934)
- fix: clusterId check for modifying triggers for cluster level notific… (#6932)
4 changes: 3 additions & 1 deletion Wire.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
appStoreDiscover "github.com/devtron-labs/devtron/api/appStore/discover"
appStoreValues "github.com/devtron-labs/devtron/api/appStore/values"
"github.com/devtron-labs/devtron/api/argoApplication"
"github.com/devtron-labs/devtron/api/auth/authorisation/globalConfig"
"github.com/devtron-labs/devtron/api/auth/sso"
"github.com/devtron-labs/devtron/api/auth/user"
chartRepo "github.com/devtron-labs/devtron/api/chartRepo"
Expand Down Expand Up @@ -192,6 +193,7 @@ func InitializeApp() (*App, error) {
externalLink.ExternalLinkWireSet,
team.TeamsWireSet,
AuthWireSet,
globalConfig.GlobalConfigWireSet,
util4.GetRuntimeConfig,
util4.NewK8sUtil,
wire.Bind(new(util4.K8sService), new(*util4.K8sServiceImpl)),
Expand Down Expand Up @@ -993,7 +995,7 @@ func InitializeApp() (*App, error) {

router.NewOverviewRouterImpl,
wire.Bind(new(router.OverviewRouter), new(*router.OverviewRouterImpl)),

restHandler.NewInfraOverviewRestHandlerImpl,
wire.Bind(new(restHandler.InfraOverviewRestHandler), new(*restHandler.InfraOverviewRestHandlerImpl)),

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2024. Devtron Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package globalConfig

import "github.com/gorilla/mux"

type AuthorisationConfigRouter interface {
InitAuthorisationConfigRouter(router *mux.Router)
}

type AuthorisationConfigRouterImpl struct {
handler AuthorisationConfigRestHandler
}

func NewGlobalConfigAuthorisationRouterImpl(handler AuthorisationConfigRestHandler) *AuthorisationConfigRouterImpl {
return &AuthorisationConfigRouterImpl{handler: handler}
}

func (router *AuthorisationConfigRouterImpl) InitAuthorisationConfigRouter(authorisationConfigRouter *mux.Router) {
authorisationConfigRouter.Path("/global-config").
HandlerFunc(router.handler.CreateOrUpdateAuthorisationConfig).Methods("POST")
authorisationConfigRouter.Path("/global-config").
HandlerFunc(router.handler.GetAllActiveAuthorisationConfig).Methods("GET")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
* Copyright (c) 2024. Devtron Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package globalConfig

import (
"encoding/json"
"errors"
"net/http"

"github.com/devtron-labs/devtron/api/restHandler/common"
"github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin"
auth "github.com/devtron-labs/devtron/pkg/auth/authorisation/globalConfig"
"github.com/devtron-labs/devtron/pkg/auth/authorisation/globalConfig/bean"
"github.com/devtron-labs/devtron/pkg/auth/user"
"github.com/devtron-labs/devtron/util/commonEnforcementFunctionsUtil"
"go.uber.org/zap"
"gopkg.in/go-playground/validator.v9"
)

type AuthorisationConfigRestHandler interface {
CreateOrUpdateAuthorisationConfig(w http.ResponseWriter, r *http.Request)
GetAllActiveAuthorisationConfig(w http.ResponseWriter, r *http.Request)
}

type AuthorisationConfigRestHandlerImpl struct {
validator *validator.Validate
logger *zap.SugaredLogger
enforcer casbin.Enforcer
userService user.UserService
userCommonService user.UserCommonService
globalAuthorisationConfigService auth.GlobalAuthorisationConfigService
rbacEnforcementUtil commonEnforcementFunctionsUtil.CommonEnforcementUtil
}

func NewGlobalAuthorisationConfigRestHandlerImpl(validator *validator.Validate,
logger *zap.SugaredLogger, enforcer casbin.Enforcer,
userService user.UserService,
globalAuthorisationConfigService auth.GlobalAuthorisationConfigService,
userCommonService user.UserCommonService,
rbacEnforcementUtil commonEnforcementFunctionsUtil.CommonEnforcementUtil,
) *AuthorisationConfigRestHandlerImpl {
return &AuthorisationConfigRestHandlerImpl{
validator: validator,
logger: logger,
enforcer: enforcer,
userService: userService,
globalAuthorisationConfigService: globalAuthorisationConfigService,
userCommonService: userCommonService,
rbacEnforcementUtil: rbacEnforcementUtil,
}
}

func (handler *AuthorisationConfigRestHandlerImpl) CreateOrUpdateAuthorisationConfig(w http.ResponseWriter, r *http.Request) {
userId, err := handler.userService.GetLoggedInUser(r)
if userId == 0 || err != nil {
common.HandleUnauthorized(w, r)
return
}
decoder := json.NewDecoder(r.Body)
var globalConfigPayload bean.GlobalAuthorisationConfig
err = decoder.Decode(&globalConfigPayload)
if err != nil {
handler.logger.Errorw("request err, CreateOrUpdateAuthorisationConfig", "err", err, "payload", globalConfigPayload)
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
token := r.Header.Get("token")
if ok := handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionCreate, "*"); !ok {
common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden)
return
}
isValidationError, err := handler.validateGlobalAuthorisationConfigPayload(globalConfigPayload)
if err != nil {
handler.logger.Errorw("error, validateGlobalAuthorisationConfigPayload", "payload", globalConfigPayload, "err", err)
if isValidationError {
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
return
}
globalConfigPayload.UserId = userId
resp, err := handler.globalAuthorisationConfigService.CreateOrUpdateGlobalAuthConfig(globalConfigPayload, nil)
if err != nil {
handler.logger.Errorw("service error, CreateOrUpdateAuthorisationConfig", "err", err, "payload", globalConfigPayload)
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
return
}
common.WriteJsonResp(w, nil, resp, http.StatusOK)
}

func (handler *AuthorisationConfigRestHandlerImpl) GetAllActiveAuthorisationConfig(w http.ResponseWriter, r *http.Request) {
userId, err := handler.userService.GetLoggedInUser(r)
if userId == 0 || err != nil {
common.HandleUnauthorized(w, r)
return
}
token := r.Header.Get("token")
isAuthorised, err := handler.rbacEnforcementUtil.CheckRbacForMangerAndAboveAccess(token, userId)
if err != nil {
handler.logger.Errorw("error, GetAllActiveAuthorisationConfig", "err", err)
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
return
}
if !isAuthorised {
common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden)
return
}
resp, err := handler.globalAuthorisationConfigService.GetAllActiveAuthorisationConfig()
if err != nil {
handler.logger.Errorw("service error, GetAllActiveAuthorisationConfig", "err", err)
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
return
}
common.WriteJsonResp(w, nil, resp, http.StatusOK)
}

func (handler *AuthorisationConfigRestHandlerImpl) validateGlobalAuthorisationConfigPayload(globalConfigPayload bean.GlobalAuthorisationConfig) (bool, error) {
err := handler.validator.Struct(globalConfigPayload)
if err != nil {
handler.logger.Errorw("err, validateGlobalAuthorisationConfigPayload", "payload", globalConfigPayload, "err", err)
return true, err
}
if len(globalConfigPayload.ConfigTypes) == 0 {
handler.logger.Errorw("err, validation failed on validateGlobalAuthorisationConfigPayload due to no configType provided", "payload", globalConfigPayload)
return true, errors.New("no configTypes provided in request")
}
return false, nil
}
29 changes: 29 additions & 0 deletions api/auth/authorisation/globalConfig/wire_globalConfig.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2024. Devtron Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package globalConfig

import "github.com/google/wire"

// GlobalConfigWireSet wires the REST handler and router for the authorisation global-config API.
// NOTE: GlobalAuthorisationConfigRepository and GlobalAuthorisationConfigService are already
// provided by UserWireSet (api/auth/user/wire_user.go) and must not be re-declared here.
var GlobalConfigWireSet = wire.NewSet(
NewGlobalAuthorisationConfigRestHandlerImpl,
wire.Bind(new(AuthorisationConfigRestHandler), new(*AuthorisationConfigRestHandlerImpl)),
NewGlobalConfigAuthorisationRouterImpl,
wire.Bind(new(AuthorisationConfigRouter), new(*AuthorisationConfigRouterImpl)),
)
3 changes: 2 additions & 1 deletion api/auth/user/UserRestHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -749,7 +749,8 @@ func (handler UserRestHandlerImpl) CheckUserRoles(w http.ResponseWriter, r *http
common.HandleUnauthorized(w, r)
return
}
roles, err := handler.userService.CheckUserRoles(userId, "")
token := r.Header.Get("token")
roles, err := handler.userService.CheckUserRoles(userId, token)
if err != nil {
handler.logger.Errorw("service err, CheckUserRoles", "err", err, "userId", userId)
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
Expand Down
1 change: 1 addition & 0 deletions api/auth/user/wire_selfRegistration.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
//depends on sql,
//TODO integrate user auth module

// SelfRegistrationWireSet depends on GlobalAuthorisationConfigService which is provided by UserWireSet
var SelfRegistrationWireSet = wire.NewSet(
repository.NewSelfRegistrationRolesRepositoryImpl,
wire.Bind(new(repository.SelfRegistrationRolesRepository), new(*repository.SelfRegistrationRolesRepositoryImpl)),
Expand Down
11 changes: 11 additions & 0 deletions api/auth/user/wire_user.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ package user
import (
"github.com/devtron-labs/devtron/pkg/auth/authentication"
"github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin"
globalConfig "github.com/devtron-labs/devtron/pkg/auth/authorisation/globalConfig"
globalConfigRepo "github.com/devtron-labs/devtron/pkg/auth/authorisation/globalConfig/repository"
user2 "github.com/devtron-labs/devtron/pkg/auth/user"
repository2 "github.com/devtron-labs/devtron/pkg/auth/user/repository"
"github.com/google/wire"
Expand Down Expand Up @@ -77,4 +79,13 @@ var UserWireSet = wire.NewSet(
wire.Bind(new(RbacRoleRestHandler), new(*RbacRoleRestHandlerImpl)),
user2.NewRbacRoleServiceImpl,
wire.Bind(new(user2.RbacRoleService), new(*user2.RbacRoleServiceImpl)),

repository2.NewUserAutoAssignGroupMapRepositoryImpl,
wire.Bind(new(repository2.UserAutoAssignGroupMapRepository), new(*repository2.UserAutoAssignGroupMapRepositoryImpl)),

globalConfigRepo.NewGlobalAuthorisationConfigRepositoryImpl,
wire.Bind(new(globalConfigRepo.GlobalAuthorisationConfigRepository), new(*globalConfigRepo.GlobalAuthorisationConfigRepositoryImpl)),

globalConfig.NewGlobalAuthorisationConfigServiceImpl,
wire.Bind(new(globalConfig.GlobalAuthorisationConfigService), new(*globalConfig.GlobalAuthorisationConfigServiceImpl)),
)
6 changes: 3 additions & 3 deletions api/cluster/ClusterRestHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -686,7 +686,7 @@ func (impl ClusterRestHandlerImpl) HandleRbacForClusterNamespace(userId int32, t
if ok := impl.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionGet, "*"); ok {
return clusterNamespaces, nil
}
roles, err := impl.clusterService.FetchRolesFromGroup(userId)
roles, err := impl.clusterService.FetchRolesFromGroup(userId, token)
if err != nil {
impl.logger.Errorw("error on fetching user roles for cluster list", "err", err)
return nil, err
Expand Down Expand Up @@ -740,7 +740,7 @@ func (impl ClusterRestHandlerImpl) GetClusterNamespaces(w http.ResponseWriter, r
return
}

allClusterNamespaces, err := impl.clusterService.FindAllNamespacesByUserIdAndClusterId(userId, clusterId, isActionUserSuperAdmin)
allClusterNamespaces, err := impl.clusterService.FindAllNamespacesByUserIdAndClusterId(userId, clusterId, isActionUserSuperAdmin, token)
if err != nil {
// Check if it's a cluster connectivity error and return appropriate status code
if err.Error() == cluster.ErrClusterNotReachable {
Expand All @@ -767,7 +767,7 @@ func (impl ClusterRestHandlerImpl) FindAllForClusterPermission(w http.ResponseWr
if ok := impl.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionGet, "*"); ok {
isActionUserSuperAdmin = true
}
clusterList, err := impl.clusterService.FindAllForClusterByUserId(userId, isActionUserSuperAdmin)
clusterList, err := impl.clusterService.FindAllForClusterByUserId(userId, isActionUserSuperAdmin, token)
if err != nil {
impl.logger.Errorw("error in deleting cluster", "err", err)
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
Expand Down
2 changes: 1 addition & 1 deletion api/k8s/application/k8sApplicationRestHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -903,7 +903,7 @@ func (handler *K8sApplicationRestHandlerImpl) GetAllApiResources(w http.Response
}

// get data from service
response, err := handler.k8sApplicationService.GetAllApiResources(r.Context(), clusterId, isSuperAdmin, userId)
response, err := handler.k8sApplicationService.GetAllApiResources(r.Context(), clusterId, isSuperAdmin, userId, token)
if err != nil {
handler.logger.Errorw("error in getting api-resources", "clusterId", clusterId, "err", err)
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
Expand Down
4 changes: 2 additions & 2 deletions api/restHandler/PolicyRestHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func (impl PolicyRestHandlerImpl) SavePolicy(w http.ResponseWriter, r *http.Requ
}
} else {
// for global and cluster level check super admin access only
roles, err := impl.userService.CheckUserRoles(userId, "")
roles, err := impl.userService.CheckUserRoles(userId, token)
if err != nil {
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
return
Expand Down Expand Up @@ -174,7 +174,7 @@ func (impl PolicyRestHandlerImpl) UpdatePolicy(w http.ResponseWriter, r *http.Re
}
} else {
// for global and cluster level check super admin access only
roles, err := impl.userService.CheckUserRoles(userId, "")
roles, err := impl.userService.CheckUserRoles(userId, token)
if err != nil {
common.WriteJsonResp(w, err, "Failed to get user by id", http.StatusInternalServerError)
return
Expand Down
Loading
Loading