All Sections to SubSections (#16917)

* initial

* Revert "initial"

This reverts commit 3d631aeecd.

* [MM-32352] Add Experimental Subsections BACKEND (#16887)

Automatic Merge

* update appiface

* Fix app layers

* Ancillary Permissions on backend (#17061)

Automatic Merge

* [MM-32799] Add About Section (#17015)

* Add About Section

* add mock key

* Update role.go

* Update role.go

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>

* [MM-33437] Fix config access tags for experimental settings (#17111)

Automatic Merge

* [MM-32794] Reporting Sub Section (#17035)

* test

* revert

* add permissions

* add new permission stuff

* add store mock

* fix bad merge

* gofmt fix

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>

* [MM-32343] Environment SubSection (#17054)

* pre-checkout commit

* fix permission for testSiteURL

* pre-merge commit

* increase size of Permissions column in Roles table

* add entry for ENVIRONMENT to testlib/store.go

* use TEXT for Permissions column in Roles table

* use environment subsection permissions for API endpoints

* use subsections permissions for /config/environment

* add suggestions from hahmadia

* update tests to use subsection permissions

* add permissions column back in

* comment out code in upgradeDatabaseToVersion534

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Co-authored-by: Scott Bishel <scott.bishel@mattermost.com>

* MM-32351: Add Compliance Subsections (#17023)

* add subsections for compliance sectin

* add to mock functions

* updates for read job

* fixes

* fix test

* update tests

* update tests

* another test fix

* some cleanup

* update mlog

* fix linting

* Fix bad merges

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Co-authored-by: Hossein <hahmadia@users.noreply.github.com>
Co-authored-by: Hossein Ahmadian-Yazdi <hyazdi1997@gmail.com>

* MM-32347 Site Subsections (#17095)

* Init

* Added migration key in testlib store

* Fix syntax error

* fix bad merge

* fix lint

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Co-authored-by: Scott Bishel <scott.bishel@mattermost.com>

* MM-32350 Integrations (#17097)

* implement server subsections

* fix tests

* update test

* go fmt

Co-authored-by: Hossein Ahmadian-Yazdi <hyazdi1997@gmail.com>

* patch forgotten endpoints

* Adding subsection permissions for Authentication (#17087)

* adding new permissions, migrations to do

* permission migrations and ancilary permissions

* running make app-layers

* fixing tests and lint

* adding permissions to saml

* ldap write permissions

* running make app-layers

* fixing conflict

* making app layers

* clean up and fix tests

* change job type

* fix js error, if site url not returned

Co-authored-by: Benjamin Cooke <benjamincooke@Benjamins-MacBook-Pro.local>
Co-authored-by: Hossein Ahmadian-Yazdi <hyazdi1997@gmail.com>
Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Co-authored-by: Scott Bishel <scott.bishel@mattermost.com>

* Update permissions_migrations.go

* gofmt

* upgrade to 535

* gofmt

Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
Co-authored-by: Max Erenberg <max.erenberg@mattermost.com>
Co-authored-by: Scott Bishel <scott.bishel@mattermost.com>
Co-authored-by: Anurag Shivarathri <anurag6713@gmail.com>
Co-authored-by: Ben Cooke <benkcooke@gmail.com>
Co-authored-by: Benjamin Cooke <benjamincooke@Benjamins-MacBook-Pro.local>
This commit is contained in:
Hossein
2021-04-06 10:39:48 -04:00
committed by GitHub
parent 2cb82965b0
commit daec0b3201
44 changed files with 2938 additions and 626 deletions

View File

@@ -18,8 +18,8 @@ func purgeBleveIndexes(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("purgeBleveIndexes", audit.Fail)
defer c.LogAuditRec(auditRec)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_WRITE_EXPERIMENTAL) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_EXPERIMENTAL)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_PURGE_BLEVE_INDEXES) {
c.SetPermissionError(model.PERMISSION_PURGE_BLEVE_INDEXES)
return
}

View File

@@ -19,7 +19,7 @@ func TestBlevePurgeIndexes(t *testing.T) {
})
t.Run("as system user with write experimental permission", func(t *testing.T) {
th.AddPermissionToRole(model.PERMISSION_SYSCONSOLE_WRITE_EXPERIMENTAL.Id, model.SYSTEM_USER_ROLE_ID)
th.AddPermissionToRole(model.PERMISSION_PURGE_BLEVE_INDEXES.Id, model.SYSTEM_USER_ROLE_ID)
defer th.RemovePermissionFromRole(model.PERMISSION_SYSCONSOLE_WRITE_EXPERIMENTAL.Id, model.SYSTEM_USER_ROLE_ID)
_, resp := th.Client.PurgeBleveIndexes()
CheckOKStatus(t, resp)

View File

@@ -14,8 +14,8 @@ func (api *API) InitCluster() {
}
func getClusterStatus(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_HIGH_AVAILABILITY) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_HIGH_AVAILABILITY)
return
}

View File

@@ -30,8 +30,8 @@ func createComplianceReport(c *Context, w http.ResponseWriter, r *http.Request)
auditRec := c.MakeAuditRecord("createComplianceReport", audit.Fail)
defer c.LogAuditRec(auditRec)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_WRITE_COMPLIANCE) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_COMPLIANCE)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_CREATE_COMPLIANCE_EXPORT_JOB) {
c.SetPermissionError(model.PERMISSION_CREATE_COMPLIANCE_EXPORT_JOB)
return
}
@@ -53,8 +53,8 @@ func createComplianceReport(c *Context, w http.ResponseWriter, r *http.Request)
}
func getComplianceReports(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_READ_COMPLIANCE_EXPORT_JOB) {
c.SetPermissionError(model.PERMISSION_READ_COMPLIANCE_EXPORT_JOB)
return
}
@@ -80,8 +80,8 @@ func getComplianceReport(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("getComplianceReport", audit.Fail)
defer c.LogAuditRec(auditRec)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_READ_COMPLIANCE_EXPORT_JOB) {
c.SetPermissionError(model.PERMISSION_READ_COMPLIANCE_EXPORT_JOB)
return
}
@@ -108,8 +108,8 @@ func downloadComplianceReport(c *Context, w http.ResponseWriter, r *http.Request
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("compliance_id", c.Params.ReportId)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_DOWNLOAD_COMPLIANCE_EXPORT_RESULT) {
c.SetPermissionError(model.PERMISSION_DOWNLOAD_COMPLIANCE_EXPORT_RESULT)
return
}

View File

@@ -78,8 +78,8 @@ func configReload(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("configReload", audit.Fail)
defer c.LogAuditRec(auditRec)
if !c.App.SessionHasPermissionToAny(*c.App.Session(), model.SysconsoleReadPermissions) {
c.SetPermissionError(model.SysconsoleReadPermissions...)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_RELOAD_CONFIG) {
c.SetPermissionError(model.PERMISSION_RELOAD_CONFIG)
return
}
@@ -193,12 +193,11 @@ func getClientConfig(c *Context, w http.ResponseWriter, r *http.Request) {
}
func getEnvironmentConfig(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT)
return
}
envConfig := c.App.GetEnvironmentConfig()
// Only return the environment variables for the subsections which the client is
// allowed to see
envConfig := c.App.GetEnvironmentConfig(func(structField reflect.StructField) bool {
return readFilter(c, structField)
})
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
w.Write([]byte(model.StringInterfaceToJson(envConfig)))

View File

@@ -77,8 +77,8 @@ func TestGetConfigWithAccessTag(t *testing.T) {
th.Client.Login(th.BasicUser.Username, th.BasicUser.Password)
// add read sysconsole environment config
th.AddPermissionToRole(model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT.Id, model.SYSTEM_USER_ROLE_ID)
defer th.RemovePermissionFromRole(model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT.Id, model.SYSTEM_USER_ROLE_ID)
th.AddPermissionToRole(model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_RATE_LIMITING.Id, model.SYSTEM_USER_ROLE_ID)
defer th.RemovePermissionFromRole(model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_RATE_LIMITING.Id, model.SYSTEM_USER_ROLE_ID)
cfg, resp := th.Client.GetConfig()
CheckNoError(t, resp)
@@ -268,8 +268,8 @@ func TestUpdateConfigWithoutManageSystemPermission(t *testing.T) {
th.Client.Login(th.BasicUser.Username, th.BasicUser.Password)
// add read sysconsole integrations config
th.AddPermissionToRole(model.PERMISSION_SYSCONSOLE_READ_INTEGRATIONS.Id, model.SYSTEM_USER_ROLE_ID)
defer th.RemovePermissionFromRole(model.PERMISSION_SYSCONSOLE_READ_INTEGRATIONS.Id, model.SYSTEM_USER_ROLE_ID)
th.AddPermissionToRole(model.PERMISSION_SYSCONSOLE_READ_INTEGRATIONS_INTEGRATION_MANAGEMENT.Id, model.SYSTEM_USER_ROLE_ID)
defer th.RemovePermissionFromRole(model.PERMISSION_SYSCONSOLE_READ_INTEGRATIONS_INTEGRATION_MANAGEMENT.Id, model.SYSTEM_USER_ROLE_ID)
t.Run("sysconsole read permission does not provides config write access", func(t *testing.T) {
// should be readable because has a sysconsole read permission
@@ -289,8 +289,8 @@ func TestUpdateConfigWithoutManageSystemPermission(t *testing.T) {
originalValue := *cfg.ServiceSettings.AllowCorsFrom
// add the wrong write permission
th.AddPermissionToRole(model.PERMISSION_SYSCONSOLE_WRITE_ABOUT.Id, model.SYSTEM_USER_ROLE_ID)
defer th.RemovePermissionFromRole(model.PERMISSION_SYSCONSOLE_WRITE_ABOUT.Id, model.SYSTEM_USER_ROLE_ID)
th.AddPermissionToRole(model.PERMISSION_SYSCONSOLE_WRITE_ABOUT_EDITION_AND_LICENSE.Id, model.SYSTEM_USER_ROLE_ID)
defer th.RemovePermissionFromRole(model.PERMISSION_SYSCONSOLE_WRITE_ABOUT_EDITION_AND_LICENSE.Id, model.SYSTEM_USER_ROLE_ID)
// try update a config value allowed by sysconsole WRITE integrations
mockVal := model.NewId()
@@ -299,7 +299,7 @@ func TestUpdateConfigWithoutManageSystemPermission(t *testing.T) {
CheckNoError(t, resp)
// ensure the config setting was not updated
cfg, resp = th.Client.GetConfig()
cfg, resp = th.SystemAdminClient.GetConfig()
CheckNoError(t, resp)
assert.Equal(t, *cfg.ServiceSettings.AllowCorsFrom, originalValue)
})
@@ -309,8 +309,10 @@ func TestUpdateConfigWithoutManageSystemPermission(t *testing.T) {
cfg, resp := th.SystemAdminClient.GetConfig()
CheckNoError(t, resp)
th.AddPermissionToRole(model.PERMISSION_SYSCONSOLE_WRITE_INTEGRATIONS.Id, model.SYSTEM_USER_ROLE_ID)
defer th.RemovePermissionFromRole(model.PERMISSION_SYSCONSOLE_WRITE_INTEGRATIONS.Id, model.SYSTEM_USER_ROLE_ID)
th.AddPermissionToRole(model.PERMISSION_SYSCONSOLE_WRITE_INTEGRATIONS_CORS.Id, model.SYSTEM_USER_ROLE_ID)
defer th.RemovePermissionFromRole(model.PERMISSION_SYSCONSOLE_WRITE_INTEGRATIONS_CORS.Id, model.SYSTEM_USER_ROLE_ID)
th.AddPermissionToRole(model.PERMISSION_SYSCONSOLE_READ_INTEGRATIONS_CORS.Id, model.SYSTEM_USER_ROLE_ID)
defer th.RemovePermissionFromRole(model.PERMISSION_SYSCONSOLE_READ_INTEGRATIONS_CORS.Id, model.SYSTEM_USER_ROLE_ID)
// try update a config value allowed by sysconsole WRITE integrations
mockVal := model.NewId()
@@ -477,15 +479,17 @@ func TestGetEnvironmentConfig(t *testing.T) {
TeamAdminClient := th.CreateClient()
th.LoginTeamAdminWithClient(TeamAdminClient)
_, resp := TeamAdminClient.GetEnvironmentConfig()
CheckForbiddenStatus(t, resp)
envConfig, resp := TeamAdminClient.GetEnvironmentConfig()
CheckNoError(t, resp)
require.Empty(t, envConfig)
})
t.Run("as regular user", func(t *testing.T) {
Client := th.Client
_, resp := Client.GetEnvironmentConfig()
CheckForbiddenStatus(t, resp)
envConfig, resp := Client.GetEnvironmentConfig()
CheckNoError(t, resp)
require.Empty(t, envConfig)
})
t.Run("as not-regular user", func(t *testing.T) {

View File

@@ -21,8 +21,10 @@ func testElasticsearch(c *Context, w http.ResponseWriter, r *http.Request) {
cfg = c.App.Config()
}
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT)
// PERMISSION_TEST_ELASTICSEARCH is an ancillary permission of PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_ELASTICSEARCH,
// which should prevent read-only managers from password sniffing
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_TEST_ELASTICSEARCH) {
c.SetPermissionError(model.PERMISSION_TEST_ELASTICSEARCH)
return
}
@@ -31,14 +33,6 @@ func testElasticsearch(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
// no sniffing for ports or passwords
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT) {
if (*cfg.ElasticsearchSettings.ConnectionUrl != *c.App.Config().ElasticsearchSettings.ConnectionUrl) || (*cfg.ElasticsearchSettings.Password != model.FAKE_SETTING) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT)
return
}
}
if err := c.App.TestElasticsearch(cfg); err != nil {
c.Err = err
return
@@ -51,8 +45,8 @@ func purgeElasticsearchIndexes(c *Context, w http.ResponseWriter, r *http.Reques
auditRec := c.MakeAuditRecord("purgeElasticsearchIndexes", audit.Fail)
defer c.LogAuditRec(auditRec)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_PURGE_ELASTICSEARCH_INDEXES) {
c.SetPermissionError(model.PERMISSION_PURGE_ELASTICSEARCH_INDEXES)
return
}

View File

@@ -11,6 +11,7 @@ import (
"github.com/mattermost/mattermost-server/v5/audit"
"github.com/mattermost/mattermost-server/v5/model"
"github.com/mattermost/mattermost-server/v5/shared/mlog"
)
func (api *API) InitJob() {
@@ -28,17 +29,22 @@ func getJob(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_READ_JOBS) {
c.SetPermissionError(model.PERMISSION_READ_JOBS)
return
}
job, err := c.App.GetJob(c.Params.JobId)
if err != nil {
c.Err = err
return
}
hasPermission, permissionRequired := c.App.SessionHasPermissionToReadJob(*c.App.Session(), job.Type)
if permissionRequired == nil {
c.Err = model.NewAppError("getJob", "api.job.retrieve.nopermissions", nil, "", http.StatusBadRequest)
return
}
if !hasPermission {
c.SetPermissionError(permissionRequired)
return
}
w.Write([]byte(job.ToJson()))
}
@@ -105,8 +111,14 @@ func createJob(c *Context, w http.ResponseWriter, r *http.Request) {
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("job", job)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_JOBS) {
c.SetPermissionError(model.PERMISSION_MANAGE_JOBS)
hasPermission, permissionRequired := c.App.SessionHasPermissionToCreateJob(*c.App.Session(), job)
if permissionRequired == nil {
c.Err = model.NewAppError("unableToCreateJob", "api.job.unable_to_create_job.incorrect_job_type", nil, "", http.StatusBadRequest)
return
}
if !hasPermission {
c.SetPermissionError(permissionRequired)
return
}
@@ -128,12 +140,23 @@ func getJobs(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_READ_JOBS) {
c.SetPermissionError(model.PERMISSION_READ_JOBS)
var validJobTypes []string
for _, jobType := range model.ALL_JOB_TYPES {
hasPermission, permissionRequired := c.App.SessionHasPermissionToReadJob(*c.App.Session(), jobType)
if permissionRequired == nil {
mlog.Warn("The job types of a job you are trying to retrieve does not contain permissions", mlog.String("jobType", jobType))
continue
}
if hasPermission {
validJobTypes = append(validJobTypes, jobType)
}
}
if len(validJobTypes) == 0 {
c.SetPermissionError()
return
}
jobs, err := c.App.GetJobsPage(c.Params.Page, c.Params.PerPage)
jobs, err := c.App.GetJobsByTypesPage(validJobTypes, c.Params.Page, c.Params.PerPage)
if err != nil {
c.Err = err
return
@@ -148,8 +171,13 @@ func getJobsByType(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_READ_JOBS) {
c.SetPermissionError(model.PERMISSION_READ_JOBS)
hasPermission, permissionRequired := c.App.SessionHasPermissionToReadJob(*c.App.Session(), c.Params.JobType)
if permissionRequired == nil {
c.Err = model.NewAppError("getJobsByType", "api.job.retrieve.nopermissions", nil, "", http.StatusBadRequest)
return
}
if !hasPermission {
c.SetPermissionError(permissionRequired)
return
}
@@ -172,8 +200,21 @@ func cancelJob(c *Context, w http.ResponseWriter, r *http.Request) {
defer c.LogAuditRec(auditRec)
auditRec.AddMeta("job_id", c.Params.JobId)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_JOBS) {
c.SetPermissionError(model.PERMISSION_MANAGE_JOBS)
job, err := c.App.GetJob(c.Params.JobId)
if err != nil {
c.Err = err
return
}
// if permission to create, permission to cancel, same permission
hasPermission, permissionRequired := c.App.SessionHasPermissionToCreateJob(*c.App.Session(), job)
if permissionRequired == nil {
c.Err = model.NewAppError("unableToCancelJob", "api.job.unable_to_create_job.incorrect_job_type", nil, "", http.StatusBadRequest)
return
}
if !hasPermission {
c.SetPermissionError(permissionRequired)
return
}

View File

@@ -26,7 +26,7 @@ func TestCreateJob(t *testing.T) {
}
_, resp := th.SystemManagerClient.CreateJob(job)
require.Nil(t, resp.Error)
CheckForbiddenStatus(t, resp)
received, resp := th.SystemAdminClient.CreateJob(job)
require.Nil(t, resp.Error)
@@ -40,6 +40,7 @@ func TestCreateJob(t *testing.T) {
_, resp = th.SystemAdminClient.CreateJob(job)
CheckBadRequestStatus(t, resp)
job.Type = model.JOB_TYPE_ELASTICSEARCH_POST_INDEXING
_, resp = th.Client.CreateJob(job)
CheckForbiddenStatus(t, resp)
}
@@ -51,6 +52,7 @@ func TestGetJob(t *testing.T) {
job := &model.Job{
Id: model.NewId(),
Status: model.JOB_STATUS_PENDING,
Type: model.JOB_TYPE_MESSAGE_EXPORT,
}
_, err := th.App.Srv().Store.Job().Save(job)
require.NoError(t, err)
@@ -77,7 +79,7 @@ func TestGetJobs(t *testing.T) {
th := Setup(t)
defer th.TearDown()
jobType := model.NewId()
jobType := model.JOB_TYPE_DATA_RETENTION
t0 := model.GetMillis()
jobs := []*model.Job{
@@ -124,7 +126,7 @@ func TestGetJobsByType(t *testing.T) {
th := Setup(t)
defer th.TearDown()
jobType := model.NewId()
jobType := model.JOB_TYPE_DATA_RETENTION
jobs := []*model.Job{
{
@@ -177,7 +179,7 @@ func TestGetJobsByType(t *testing.T) {
_, resp = th.Client.GetJobsByType(jobType, 0, 60)
CheckForbiddenStatus(t, resp)
_, resp = th.SystemManagerClient.GetJobsByType(model.JOB_TYPE_MESSAGE_EXPORT, 0, 60)
_, resp = th.SystemManagerClient.GetJobsByType(model.JOB_TYPE_ELASTICSEARCH_POST_INDEXING, 0, 60)
require.Nil(t, resp.Error)
}
@@ -273,20 +275,21 @@ func TestCancelJob(t *testing.T) {
th := Setup(t)
defer th.TearDown()
jobType := model.JOB_TYPE_MESSAGE_EXPORT
jobs := []*model.Job{
{
Id: model.NewId(),
Type: model.NewId(),
Type: jobType,
Status: model.JOB_STATUS_PENDING,
},
{
Id: model.NewId(),
Type: model.NewId(),
Type: jobType,
Status: model.JOB_STATUS_IN_PROGRESS,
},
{
Id: model.NewId(),
Type: model.NewId(),
Type: jobType,
Status: model.JOB_STATUS_SUCCESS,
},
}
@@ -310,5 +313,5 @@ func TestCancelJob(t *testing.T) {
CheckInternalErrorStatus(t, resp)
_, resp = th.SystemAdminClient.CancelJob(model.NewId())
CheckInternalErrorStatus(t, resp)
CheckNotFoundStatus(t, resp)
}

View File

@@ -50,8 +50,8 @@ func syncLdap(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("syncLdap", audit.Fail)
defer c.LogAuditRec(auditRec)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_CREATE_LDAP_SYNC_JOB) {
c.SetPermissionError(model.PERMISSION_CREATE_LDAP_SYNC_JOB)
return
}
@@ -67,8 +67,8 @@ func testLdap(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_READ_AUTHENTICATION) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_AUTHENTICATION)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_TEST_LDAP) {
c.SetPermissionError(model.PERMISSION_TEST_LDAP)
return
}
@@ -319,8 +319,8 @@ func parseLdapCertificateRequest(r *http.Request, maxFileSize int64) (*multipart
}
func addLdapPublicCertificate(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) {
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_ADD_LDAP_PUBLIC_CERT) {
c.SetPermissionError(model.PERMISSION_ADD_LDAP_PUBLIC_CERT)
return
}
@@ -343,8 +343,8 @@ func addLdapPublicCertificate(c *Context, w http.ResponseWriter, r *http.Request
}
func addLdapPrivateCertificate(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) {
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_ADD_LDAP_PRIVATE_CERT) {
c.SetPermissionError(model.PERMISSION_ADD_LDAP_PRIVATE_CERT)
return
}
@@ -367,8 +367,8 @@ func addLdapPrivateCertificate(c *Context, w http.ResponseWriter, r *http.Reques
}
func removeLdapPublicCertificate(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) {
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_REMOVE_LDAP_PUBLIC_CERT) {
c.SetPermissionError(model.PERMISSION_REMOVE_LDAP_PUBLIC_CERT)
return
}
@@ -385,8 +385,8 @@ func removeLdapPublicCertificate(c *Context, w http.ResponseWriter, r *http.Requ
}
func removeLdapPrivateCertificate(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_SYSTEM) {
c.SetPermissionError(model.PERMISSION_MANAGE_SYSTEM)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_REMOVE_LDAP_PRIVATE_CERT) {
c.SetPermissionError(model.PERMISSION_REMOVE_LDAP_PRIVATE_CERT)
return
}

View File

@@ -38,7 +38,7 @@ func getClientLicense(c *Context, w http.ResponseWriter, r *http.Request) {
var clientLicense map[string]string
if c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_READ_ABOUT) {
if c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_READ_LICENSE_INFORMATION) {
clientLicense = c.App.Srv().ClientLicense()
} else {
clientLicense = c.App.Srv().GetSanitizedClientLicense()
@@ -52,8 +52,8 @@ func addLicense(c *Context, w http.ResponseWriter, r *http.Request) {
defer c.LogAuditRec(auditRec)
c.LogAudit("attempt")
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_WRITE_ABOUT) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_ABOUT)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_LICENSE_INFORMATION) {
c.SetPermissionError(model.PERMISSION_MANAGE_LICENSE_INFORMATION)
return
}
@@ -118,8 +118,8 @@ func removeLicense(c *Context, w http.ResponseWriter, r *http.Request) {
defer c.LogAuditRec(auditRec)
c.LogAudit("attempt")
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_WRITE_ABOUT) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_ABOUT)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_LICENSE_INFORMATION) {
c.SetPermissionError(model.PERMISSION_MANAGE_LICENSE_INFORMATION)
return
}
@@ -144,8 +144,8 @@ func requestTrialLicense(c *Context, w http.ResponseWriter, r *http.Request) {
defer c.LogAuditRec(auditRec)
c.LogAudit("attempt")
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_WRITE_ABOUT) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_ABOUT)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_LICENSE_INFORMATION) {
c.SetPermissionError(model.PERMISSION_MANAGE_LICENSE_INFORMATION)
return
}
@@ -213,8 +213,8 @@ func requestRenewalLink(c *Context, w http.ResponseWriter, r *http.Request) {
defer c.LogAuditRec(auditRec)
c.LogAudit("attempt")
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_WRITE_ABOUT) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_ABOUT)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_MANAGE_LICENSE_INFORMATION) {
c.SetPermissionError(model.PERMISSION_MANAGE_LICENSE_INFORMATION)
return
}

View File

@@ -162,6 +162,11 @@ func patchRole(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
}
ancillaryPermissions := model.AddAncillaryPermissions(*patch.Permissions)
*patch.Permissions = append(*patch.Permissions, ancillaryPermissions...)
*patch.Permissions = model.UniqueStrings(*patch.Permissions)
}
if c.App.Srv().License() != nil && isGuest && !*c.App.Srv().License().Features.GuestAccountsPermissions {

View File

@@ -62,8 +62,8 @@ func parseSamlCertificateRequest(r *http.Request, maxFileSize int64) (*multipart
}
func addSamlPublicCertificate(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_ADD_SAML_PUBLIC_CERT) {
c.SetPermissionError(model.PERMISSION_ADD_SAML_PUBLIC_CERT)
return
}
@@ -86,8 +86,8 @@ func addSamlPublicCertificate(c *Context, w http.ResponseWriter, r *http.Request
}
func addSamlPrivateCertificate(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_ADD_SAML_PRIVATE_CERT) {
c.SetPermissionError(model.PERMISSION_ADD_SAML_PRIVATE_CERT)
return
}
@@ -110,8 +110,8 @@ func addSamlPrivateCertificate(c *Context, w http.ResponseWriter, r *http.Reques
}
func addSamlIdpCertificate(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_ADD_SAML_IDP_CERT) {
c.SetPermissionError(model.PERMISSION_ADD_SAML_IDP_CERT)
return
}
@@ -163,8 +163,8 @@ func addSamlIdpCertificate(c *Context, w http.ResponseWriter, r *http.Request) {
}
func removeSamlPublicCertificate(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_REMOVE_SAML_PUBLIC_CERT) {
c.SetPermissionError(model.PERMISSION_REMOVE_SAML_PUBLIC_CERT)
return
}
@@ -181,8 +181,8 @@ func removeSamlPublicCertificate(c *Context, w http.ResponseWriter, r *http.Requ
}
func removeSamlPrivateCertificate(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_REMOVE_SAML_PRIVATE_CERT) {
c.SetPermissionError(model.PERMISSION_REMOVE_SAML_PRIVATE_CERT)
return
}
@@ -199,8 +199,8 @@ func removeSamlPrivateCertificate(c *Context, w http.ResponseWriter, r *http.Req
}
func removeSamlIdpCertificate(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_REMOVE_SAML_IDP_CERT) {
c.SetPermissionError(model.PERMISSION_REMOVE_SAML_IDP_CERT)
return
}
@@ -217,8 +217,8 @@ func removeSamlIdpCertificate(c *Context, w http.ResponseWriter, r *http.Request
}
func getSamlCertificateStatus(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_GET_SAML_CERT_STATUS) {
c.SetPermissionError(model.PERMISSION_GET_SAML_CERT_STATUS)
return
}
@@ -227,8 +227,8 @@ func getSamlCertificateStatus(c *Context, w http.ResponseWriter, r *http.Request
}
func getSamlMetadataFromIdp(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_GET_SAML_METADATA_FROM_IDP) {
c.SetPermissionError(model.PERMISSION_GET_SAML_METADATA_FROM_IDP)
return
}

View File

@@ -195,8 +195,8 @@ func testEmail(c *Context, w http.ResponseWriter, r *http.Request) {
cfg = c.App.Config()
}
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_TEST_EMAIL) {
c.SetPermissionError(model.PERMISSION_TEST_EMAIL)
return
}
@@ -215,8 +215,8 @@ func testEmail(c *Context, w http.ResponseWriter, r *http.Request) {
}
func testSiteURL(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_TEST_SITE_URL) {
c.SetPermissionError(model.PERMISSION_TEST_SITE_URL)
return
}
@@ -232,11 +232,6 @@ func testSiteURL(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT) && siteURL != *c.App.Config().ServiceSettings.SiteURL {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT)
return
}
err := c.App.TestSiteURL(siteURL)
if err != nil {
c.Err = err
@@ -250,8 +245,8 @@ func getAudits(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("getAudits", audit.Fail)
defer c.LogAuditRec(auditRec)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_READ_AUDITS) {
c.SetPermissionError(model.PERMISSION_READ_AUDITS)
return
}
@@ -269,8 +264,8 @@ func getAudits(c *Context, w http.ResponseWriter, r *http.Request) {
}
func databaseRecycle(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_RECYCLE_DATABASE_CONNECTIONS) {
c.SetPermissionError(model.PERMISSION_RECYCLE_DATABASE_CONNECTIONS)
return
}
@@ -289,8 +284,8 @@ func databaseRecycle(c *Context, w http.ResponseWriter, r *http.Request) {
}
func invalidateCaches(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_INVALIDATE_CACHES) {
c.SetPermissionError(model.PERMISSION_INVALIDATE_CACHES)
return
}
@@ -323,8 +318,8 @@ func getLogs(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_READ_REPORTING) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_REPORTING)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_GET_LOGS) {
c.SetPermissionError(model.PERMISSION_GET_LOGS)
return
}
@@ -386,12 +381,8 @@ func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) {
name = "standard"
}
permissions := []*model.Permission{
model.PERMISSION_SYSCONSOLE_READ_REPORTING,
model.PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_USERS,
}
if !c.App.SessionHasPermissionToAny(*c.App.Session(), permissions) {
c.SetPermissionError(permissions...)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_GET_ANALYTICS) {
c.SetPermissionError(model.PERMISSION_GET_ANALYTICS)
return
}
@@ -430,8 +421,8 @@ func testS3(c *Context, w http.ResponseWriter, r *http.Request) {
cfg = c.App.Config()
}
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_TEST_S3) {
c.SetPermissionError(model.PERMISSION_TEST_S3)
return
}

View File

@@ -1396,8 +1396,8 @@ func getInviteInfo(c *Context, w http.ResponseWriter, r *http.Request) {
}
func invalidateAllEmailInvites(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION) {
c.SetPermissionError(model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION)
if !c.App.SessionHasPermissionTo(*c.App.Session(), model.PERMISSION_INVALIDATE_EMAIL_INVITE) {
c.SetPermissionError(model.PERMISSION_INVALIDATE_EMAIL_INVITE)
return
}

View File

@@ -3321,8 +3321,8 @@ func TestInvalidateAllEmailInvites(t *testing.T) {
})
t.Run("OK when request performed by system user with requisite system permission", func(t *testing.T) {
th.AddPermissionToRole(model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION.Id, model.SYSTEM_USER_ROLE_ID)
defer th.RemovePermissionFromRole(model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION.Id, model.SYSTEM_USER_ROLE_ID)
th.AddPermissionToRole(model.PERMISSION_INVALIDATE_EMAIL_INVITE.Id, model.SYSTEM_USER_ROLE_ID)
defer th.RemovePermissionFromRole(model.PERMISSION_INVALIDATE_EMAIL_INVITE.Id, model.SYSTEM_USER_ROLE_ID)
ok, res := th.Client.InvalidateEmailInvites()
require.Equal(t, true, ok)
CheckOKStatus(t, res)

View File

@@ -14,6 +14,7 @@ import (
"mime/multipart"
"net/http"
"net/url"
"reflect"
"time"
"github.com/dyatlov/go-opengraph/opengraph"
@@ -159,7 +160,8 @@ type AppIface interface {
// and the API route for custom ones. Errors if not found or if custom and deleted.
GetEmojiStaticUrl(emojiName string) (string, *model.AppError)
// GetEnvironmentConfig returns a map of configuration keys whose values have been overridden by an environment variable.
GetEnvironmentConfig() map[string]interface{}
// If filter is not nil and returns false for a struct field, that field will be omitted.
GetEnvironmentConfig(filter func(reflect.StructField) bool) map[string]interface{}
// GetFilteredUsersStats is used to get a count of users based on the set of filters supported by UserCountOptions.
GetFilteredUsersStats(options *model.UserCountOptions) (*model.UsersStats, *model.AppError)
// GetGroupsByTeam returns the paged list and the total count of group associated to the given team.
@@ -511,7 +513,7 @@ type AppIface interface {
DoUploadFileExpectModification(now time.Time, rawTeamId string, rawChannelId string, rawUserId string, rawFilename string, data []byte) (*model.FileInfo, []byte, *model.AppError)
DownloadFromURL(downloadURL string) ([]byte, error)
EnableUserAccessToken(token *model.UserAccessToken) *model.AppError
EnvironmentConfig() map[string]interface{}
EnvironmentConfig(filter func(reflect.StructField) bool) map[string]interface{}
ExportPermissions(w io.Writer) error
FetchSamlMetadataFromIdp(url string) ([]byte, *model.AppError)
FileBackend() (filestore.FileBackend, *model.AppError)
@@ -615,6 +617,8 @@ type AppIface interface {
GetJobs(offset int, limit int) ([]*model.Job, *model.AppError)
GetJobsByType(jobType string, offset int, limit int) ([]*model.Job, *model.AppError)
GetJobsByTypePage(jobType string, page int, perPage int) ([]*model.Job, *model.AppError)
GetJobsByTypes(jobTypes []string, offset int, limit int) ([]*model.Job, *model.AppError)
GetJobsByTypesPage(jobType []string, page int, perPage int) ([]*model.Job, *model.AppError)
GetJobsPage(page int, perPage int) ([]*model.Job, *model.AppError)
GetLatestTermsOfService() (*model.TermsOfService, *model.AppError)
GetLogs(page, perPage int) ([]string, *model.AppError)
@@ -948,6 +952,8 @@ type AppIface interface {
SessionHasPermissionToCategory(session model.Session, userID, teamID, categoryId string) bool
SessionHasPermissionToChannel(session model.Session, channelID string, permission *model.Permission) bool
SessionHasPermissionToChannelByPost(session model.Session, postID string, permission *model.Permission) bool
SessionHasPermissionToCreateJob(session model.Session, job *model.Job) (bool, *model.Permission)
SessionHasPermissionToReadJob(session model.Session, jobType string) (bool, *model.Permission)
SessionHasPermissionToTeam(session model.Session, teamID string, permission *model.Permission) bool
SessionHasPermissionToUser(session model.Session, userID string) bool
SessionHasPermissionToUserOrBot(session model.Session, userID string) bool

View File

@@ -14,6 +14,7 @@ import (
"fmt"
"net/http"
"net/url"
"reflect"
"strconv"
"time"
@@ -38,12 +39,12 @@ func (a *App) Config() *model.Config {
return a.Srv().Config()
}
func (s *Server) EnvironmentConfig() map[string]interface{} {
return s.configStore.GetEnvironmentOverrides()
func (s *Server) EnvironmentConfig(filter func(reflect.StructField) bool) map[string]interface{} {
return s.configStore.GetEnvironmentOverridesWithFilter(filter)
}
func (a *App) EnvironmentConfig() map[string]interface{} {
return a.Srv().EnvironmentConfig()
func (a *App) EnvironmentConfig(filter func(reflect.StructField) bool) map[string]interface{} {
return a.Srv().EnvironmentConfig(filter)
}
func (s *Server) UpdateConfig(f func(*model.Config)) {
@@ -398,8 +399,9 @@ func (a *App) GetSanitizedConfig() *model.Config {
}
// GetEnvironmentConfig returns a map of configuration keys whose values have been overridden by an environment variable.
func (a *App) GetEnvironmentConfig() map[string]interface{} {
return a.EnvironmentConfig()
// If filter is not nil and returns false for a struct field, that field will be omitted.
func (a *App) GetEnvironmentConfig(filter func(reflect.StructField) bool) map[string]interface{} {
return a.EnvironmentConfig(filter)
}
// SaveConfig replaces the active configuration, optionally notifying cluster peers.

View File

@@ -52,6 +52,18 @@ func (a *App) GetJobsByType(jobType string, offset int, limit int) ([]*model.Job
return jobs, nil
}
func (a *App) GetJobsByTypesPage(jobType []string, page int, perPage int) ([]*model.Job, *model.AppError) {
return a.GetJobsByTypes(jobType, page*perPage, perPage)
}
func (a *App) GetJobsByTypes(jobTypes []string, offset int, limit int) ([]*model.Job, *model.AppError) {
jobs, err := a.Srv().Store.Job().GetAllByTypesPage(jobTypes, offset, limit)
if err != nil {
return nil, model.NewAppError("GetJobsByType", "app.job.get_all.app_error", nil, err.Error(), http.StatusInternalServerError)
}
return jobs, nil
}
func (a *App) CreateJob(job *model.Job) (*model.Job, *model.AppError) {
return a.Srv().Jobs.CreateJob(job.Type, job.Data)
}
@@ -59,3 +71,64 @@ func (a *App) CreateJob(job *model.Job) (*model.Job, *model.AppError) {
func (a *App) CancelJob(jobId string) *model.AppError {
return a.Srv().Jobs.RequestCancellation(jobId)
}
func (a *App) SessionHasPermissionToCreateJob(session model.Session, job *model.Job) (bool, *model.Permission) {
switch job.Type {
case model.JOB_TYPE_BLEVE_POST_INDEXING:
return a.SessionHasPermissionTo(session, model.PERMISSION_CREATE_POST_BLEVE_INDEXES_JOB), model.PERMISSION_CREATE_POST_BLEVE_INDEXES_JOB
case model.JOB_TYPE_DATA_RETENTION:
return a.SessionHasPermissionTo(session, model.PERMISSION_CREATE_DATA_RETENTION_JOB), model.PERMISSION_CREATE_DATA_RETENTION_JOB
case model.JOB_TYPE_MESSAGE_EXPORT:
return a.SessionHasPermissionTo(session, model.PERMISSION_CREATE_COMPLIANCE_EXPORT_JOB), model.PERMISSION_CREATE_COMPLIANCE_EXPORT_JOB
case model.JOB_TYPE_ELASTICSEARCH_POST_INDEXING:
return a.SessionHasPermissionTo(session, model.PERMISSION_CREATE_ELASTICSEARCH_POST_INDEXING_JOB), model.PERMISSION_CREATE_ELASTICSEARCH_POST_INDEXING_JOB
case model.JOB_TYPE_ELASTICSEARCH_POST_AGGREGATION:
return a.SessionHasPermissionTo(session, model.PERMISSION_CREATE_ELASTICSEARCH_POST_AGGREGATION_JOB), model.PERMISSION_CREATE_ELASTICSEARCH_POST_AGGREGATION_JOB
case model.JOB_TYPE_LDAP_SYNC:
return a.SessionHasPermissionTo(session, model.PERMISSION_CREATE_LDAP_SYNC_JOB), model.PERMISSION_CREATE_LDAP_SYNC_JOB
case
model.JOB_TYPE_MIGRATIONS,
model.JOB_TYPE_PLUGINS,
model.JOB_TYPE_PRODUCT_NOTICES,
model.JOB_TYPE_EXPIRY_NOTIFY,
model.JOB_TYPE_ACTIVE_USERS,
model.JOB_TYPE_IMPORT_PROCESS,
model.JOB_TYPE_IMPORT_DELETE,
model.JOB_TYPE_EXPORT_PROCESS,
model.JOB_TYPE_EXPORT_DELETE,
model.JOB_TYPE_CLOUD:
return a.SessionHasPermissionTo(session, model.PERMISSION_MANAGE_JOBS), model.PERMISSION_MANAGE_JOBS
}
return false, nil
}
func (a *App) SessionHasPermissionToReadJob(session model.Session, jobType string) (bool, *model.Permission) {
switch jobType {
case model.JOB_TYPE_DATA_RETENTION:
return a.SessionHasPermissionTo(session, model.PERMISSION_READ_DATA_RETENTION_JOB), model.PERMISSION_READ_DATA_RETENTION_JOB
case model.JOB_TYPE_MESSAGE_EXPORT:
return a.SessionHasPermissionTo(session, model.PERMISSION_READ_COMPLIANCE_EXPORT_JOB), model.PERMISSION_READ_COMPLIANCE_EXPORT_JOB
case model.JOB_TYPE_ELASTICSEARCH_POST_INDEXING:
return a.SessionHasPermissionTo(session, model.PERMISSION_READ_ELASTICSEARCH_POST_INDEXING_JOB), model.PERMISSION_READ_ELASTICSEARCH_POST_INDEXING_JOB
case model.JOB_TYPE_ELASTICSEARCH_POST_AGGREGATION:
return a.SessionHasPermissionTo(session, model.PERMISSION_READ_ELASTICSEARCH_POST_AGGREGATION_JOB), model.PERMISSION_READ_ELASTICSEARCH_POST_AGGREGATION_JOB
case model.JOB_TYPE_LDAP_SYNC:
return a.SessionHasPermissionTo(session, model.PERMISSION_READ_LDAP_SYNC_JOB), model.PERMISSION_READ_LDAP_SYNC_JOB
case
model.JOB_TYPE_BLEVE_POST_INDEXING,
model.JOB_TYPE_MIGRATIONS,
model.JOB_TYPE_PLUGINS,
model.JOB_TYPE_PRODUCT_NOTICES,
model.JOB_TYPE_EXPIRY_NOTIFY,
model.JOB_TYPE_ACTIVE_USERS,
model.JOB_TYPE_IMPORT_PROCESS,
model.JOB_TYPE_IMPORT_DELETE,
model.JOB_TYPE_EXPORT_PROCESS,
model.JOB_TYPE_EXPORT_DELETE,
model.JOB_TYPE_CLOUD:
return a.SessionHasPermissionTo(session, model.PERMISSION_READ_JOBS), model.PERMISSION_READ_JOBS
}
return false, nil
}

View File

@@ -6,6 +6,7 @@ package app
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/v5/model"
@@ -29,6 +30,185 @@ func TestGetJob(t *testing.T) {
require.Equal(t, status, received, "incorrect job status received")
}
func TestSessionHasPermissionToCreateJob(t *testing.T) {
th := Setup(t)
defer th.TearDown()
jobs := []model.Job{
{
Id: model.NewId(),
Type: model.JOB_TYPE_BLEVE_POST_INDEXING,
CreateAt: 1000,
},
{
Id: model.NewId(),
Type: model.JOB_TYPE_DATA_RETENTION,
CreateAt: 999,
},
{
Id: model.NewId(),
Type: model.JOB_TYPE_MESSAGE_EXPORT,
CreateAt: 1001,
},
}
testCases := []struct {
Job model.Job
PermissionRequired *model.Permission
}{
{
Job: jobs[0],
PermissionRequired: model.PERMISSION_CREATE_POST_BLEVE_INDEXES_JOB,
},
{
Job: jobs[1],
PermissionRequired: model.PERMISSION_CREATE_DATA_RETENTION_JOB,
},
{
Job: jobs[2],
PermissionRequired: model.PERMISSION_CREATE_COMPLIANCE_EXPORT_JOB,
},
}
session := model.Session{
Roles: model.SYSTEM_USER_ROLE_ID + " " + model.SYSTEM_ADMIN_ROLE_ID,
}
// Check to see if admin has permission to all the jobs
for _, testCase := range testCases {
hasPermission, permissionRequired := th.App.SessionHasPermissionToCreateJob(session, &testCase.Job)
assert.Equal(t, true, hasPermission)
require.NotNil(t, permissionRequired)
assert.Equal(t, testCase.PermissionRequired.Id, permissionRequired.Id)
}
session = model.Session{
Roles: model.SYSTEM_USER_ROLE_ID + " " + model.SYSTEM_READ_ONLY_ADMIN_ROLE_ID,
}
// Initially the system read only admin should not have access to create these jobs
for _, testCase := range testCases {
hasPermission, permissionRequired := th.App.SessionHasPermissionToCreateJob(session, &testCase.Job)
assert.Equal(t, false, hasPermission)
require.NotNil(t, permissionRequired)
assert.Equal(t, testCase.PermissionRequired.Id, permissionRequired.Id)
}
role, _ := th.App.GetRoleByName(model.SYSTEM_READ_ONLY_ADMIN_ROLE_ID)
role.Permissions = append(role.Permissions, model.PERMISSION_CREATE_POST_BLEVE_INDEXES_JOB.Id)
_, err := th.App.UpdateRole(role)
require.Nil(t, err)
// Now system read only admin should have ability to create a Belve Post Index job but not the others
for _, testCase := range testCases {
hasPermission, permissionRequired := th.App.SessionHasPermissionToCreateJob(session, &testCase.Job)
expectedHasPermission := testCase.Job.Type == model.JOB_TYPE_BLEVE_POST_INDEXING
assert.Equal(t, expectedHasPermission, hasPermission)
require.NotNil(t, permissionRequired)
assert.Equal(t, testCase.PermissionRequired.Id, permissionRequired.Id)
}
role.Permissions = append(role.Permissions, model.PERMISSION_CREATE_DATA_RETENTION_JOB.Id)
role.Permissions = append(role.Permissions, model.PERMISSION_CREATE_COMPLIANCE_EXPORT_JOB.Id)
_, err = th.App.UpdateRole(role)
require.Nil(t, err)
// Now system read only admin should have ability to create all jobs
for _, testCase := range testCases {
hasPermission, permissionRequired := th.App.SessionHasPermissionToCreateJob(session, &testCase.Job)
assert.Equal(t, true, hasPermission)
require.NotNil(t, permissionRequired)
assert.Equal(t, testCase.PermissionRequired.Id, permissionRequired.Id)
}
}
func TestSessionHasPermissionToReadJob(t *testing.T) {
th := Setup(t)
defer th.TearDown()
jobs := []model.Job{
{
Id: model.NewId(),
Type: model.JOB_TYPE_DATA_RETENTION,
CreateAt: 999,
},
{
Id: model.NewId(),
Type: model.JOB_TYPE_MESSAGE_EXPORT,
CreateAt: 1001,
},
}
testCases := []struct {
Job model.Job
PermissionRequired *model.Permission
}{
{
Job: jobs[0],
PermissionRequired: model.PERMISSION_READ_DATA_RETENTION_JOB,
},
{
Job: jobs[1],
PermissionRequired: model.PERMISSION_READ_COMPLIANCE_EXPORT_JOB,
},
}
session := model.Session{
Roles: model.SYSTEM_USER_ROLE_ID + " " + model.SYSTEM_ADMIN_ROLE_ID,
}
// Check to see if admin has permission to all the jobs
for _, testCase := range testCases {
hasPermission, permissionRequired := th.App.SessionHasPermissionToReadJob(session, testCase.Job.Type)
assert.Equal(t, true, hasPermission)
require.NotNil(t, permissionRequired)
assert.Equal(t, testCase.PermissionRequired.Id, permissionRequired.Id)
}
session = model.Session{
Roles: model.SYSTEM_USER_ROLE_ID + " " + model.SYSTEM_MANAGER_ROLE_ID,
}
// Initially the system manager should not have access to read these jobs
for _, testCase := range testCases {
hasPermission, permissionRequired := th.App.SessionHasPermissionToReadJob(session, testCase.Job.Type)
assert.Equal(t, false, hasPermission)
require.NotNil(t, permissionRequired)
assert.Equal(t, testCase.PermissionRequired.Id, permissionRequired.Id)
}
role, _ := th.App.GetRoleByName(model.SYSTEM_MANAGER_ROLE_ID)
role.Permissions = append(role.Permissions, model.PERMISSION_READ_DATA_RETENTION_JOB.Id)
_, err := th.App.UpdateRole(role)
require.Nil(t, err)
// Now system manager should have ability to read data retention jobs
for _, testCase := range testCases {
hasPermission, permissionRequired := th.App.SessionHasPermissionToReadJob(session, testCase.Job.Type)
expectedHasPermission := testCase.Job.Type == model.JOB_TYPE_DATA_RETENTION
assert.Equal(t, expectedHasPermission, hasPermission)
require.NotNil(t, permissionRequired)
assert.Equal(t, testCase.PermissionRequired.Id, permissionRequired.Id)
}
role.Permissions = append(role.Permissions, model.PERMISSION_READ_COMPLIANCE_EXPORT_JOB.Id)
_, err = th.App.UpdateRole(role)
require.Nil(t, err)
// Now system read only admin should have ability to create all jobs
for _, testCase := range testCases {
hasPermission, permissionRequired := th.App.SessionHasPermissionToReadJob(session, testCase.Job.Type)
assert.Equal(t, true, hasPermission)
require.NotNil(t, permissionRequired)
assert.Equal(t, testCase.PermissionRequired.Id, permissionRequired.Id)
}
}
func TestGetJobByType(t *testing.T) {
th := Setup(t)
defer th.TearDown()
@@ -70,3 +250,55 @@ func TestGetJobByType(t *testing.T) {
require.Len(t, received, 1, "received wrong number of statuses")
require.Equal(t, statuses[1], received[0], "should've received oldest job last")
}
func TestGetJobsByTypes(t *testing.T) {
th := Setup(t)
defer th.TearDown()
jobType := model.NewId()
jobType1 := model.NewId()
jobType2 := model.NewId()
statuses := []*model.Job{
{
Id: model.NewId(),
Type: jobType,
CreateAt: 1000,
},
{
Id: model.NewId(),
Type: jobType1,
CreateAt: 999,
},
{
Id: model.NewId(),
Type: jobType2,
CreateAt: 1001,
},
}
for _, status := range statuses {
_, err := th.App.Srv().Store.Job().Save(status)
require.NoError(t, err)
defer th.App.Srv().Store.Job().Delete(status.Id)
}
jobTypes := []string{jobType, jobType1, jobType2}
received, err := th.App.GetJobsByTypes(jobTypes, 0, 2)
require.Nil(t, err)
require.Len(t, received, 2, "received wrong number of jobs")
require.Equal(t, statuses[2], received[0], "should've received newest job first")
require.Equal(t, statuses[0], received[1], "should've received second newest job second")
received, err = th.App.GetJobsByTypes(jobTypes, 2, 2)
require.Nil(t, err)
require.Len(t, received, 1, "received wrong number of jobs")
require.Equal(t, statuses[1], received[0], "should've received oldest job last")
jobTypes = []string{jobType1, jobType2}
received, err = th.App.GetJobsByTypes(jobTypes, 0, 3)
require.Nil(t, err)
require.Len(t, received, 2, "received wrong number of jobs")
require.Equal(t, statuses[2], received[0], "received wrong job type")
require.Equal(t, statuses[1], received[1], "received wrong job type")
}

View File

@@ -14,6 +14,7 @@ import (
"mime/multipart"
"net/http"
"net/url"
"reflect"
"time"
"github.com/dyatlov/go-opengraph/opengraph"
@@ -3714,7 +3715,7 @@ func (a *OpenTracingAppLayer) EnableUserAccessToken(token *model.UserAccessToken
return resultVar0
}
func (a *OpenTracingAppLayer) EnvironmentConfig() map[string]interface{} {
func (a *OpenTracingAppLayer) EnvironmentConfig(filter func(reflect.StructField) bool) map[string]interface{} {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.EnvironmentConfig")
@@ -3726,7 +3727,7 @@ func (a *OpenTracingAppLayer) EnvironmentConfig() map[string]interface{} {
}()
defer span.Finish()
resultVar0 := a.app.EnvironmentConfig()
resultVar0 := a.app.EnvironmentConfig(filter)
return resultVar0
}
@@ -5541,7 +5542,7 @@ func (a *OpenTracingAppLayer) GetEmojiStaticUrl(emojiName string) (string, *mode
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) GetEnvironmentConfig() map[string]interface{} {
func (a *OpenTracingAppLayer) GetEnvironmentConfig(filter func(reflect.StructField) bool) map[string]interface{} {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetEnvironmentConfig")
@@ -5553,7 +5554,7 @@ func (a *OpenTracingAppLayer) GetEnvironmentConfig() map[string]interface{} {
}()
defer span.Finish()
resultVar0 := a.app.GetEnvironmentConfig()
resultVar0 := a.app.GetEnvironmentConfig(filter)
return resultVar0
}
@@ -6345,6 +6346,50 @@ func (a *OpenTracingAppLayer) GetJobsByTypePage(jobType string, page int, perPag
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) GetJobsByTypes(jobTypes []string, offset int, limit int) ([]*model.Job, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetJobsByTypes")
a.ctx = newCtx
a.app.Srv().Store.SetContext(newCtx)
defer func() {
a.app.Srv().Store.SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
resultVar0, resultVar1 := a.app.GetJobsByTypes(jobTypes, offset, limit)
if resultVar1 != nil {
span.LogFields(spanlog.Error(resultVar1))
ext.Error.Set(span, true)
}
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) GetJobsByTypesPage(jobType []string, page int, perPage int) ([]*model.Job, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetJobsByTypesPage")
a.ctx = newCtx
a.app.Srv().Store.SetContext(newCtx)
defer func() {
a.app.Srv().Store.SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
resultVar0, resultVar1 := a.app.GetJobsByTypesPage(jobType, page, perPage)
if resultVar1 != nil {
span.LogFields(spanlog.Error(resultVar1))
ext.Error.Set(span, true)
}
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) GetJobsPage(page int, perPage int) ([]*model.Job, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetJobsPage")
@@ -14053,6 +14098,23 @@ func (a *OpenTracingAppLayer) SessionHasPermissionToChannelByPost(session model.
return resultVar0
}
func (a *OpenTracingAppLayer) SessionHasPermissionToCreateJob(session model.Session, job *model.Job) (bool, *model.Permission) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SessionHasPermissionToCreateJob")
a.ctx = newCtx
a.app.Srv().Store.SetContext(newCtx)
defer func() {
a.app.Srv().Store.SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
resultVar0, resultVar1 := a.app.SessionHasPermissionToCreateJob(session, job)
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) SessionHasPermissionToManageBot(session model.Session, botUserId string) *model.AppError {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SessionHasPermissionToManageBot")
@@ -14075,6 +14137,23 @@ func (a *OpenTracingAppLayer) SessionHasPermissionToManageBot(session model.Sess
return resultVar0
}
func (a *OpenTracingAppLayer) SessionHasPermissionToReadJob(session model.Session, jobType string) (bool, *model.Permission) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SessionHasPermissionToReadJob")
a.ctx = newCtx
a.app.Srv().Store.SetContext(newCtx)
defer func() {
a.app.Srv().Store.SetContext(origCtx)
a.ctx = origCtx
}()
defer span.Finish()
resultVar0, resultVar1 := a.app.SessionHasPermissionToReadJob(session, jobType)
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) SessionHasPermissionToTeam(session model.Session, teamID string, permission *model.Permission) bool {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SessionHasPermissionToTeam")

View File

@@ -537,7 +537,7 @@ func (a *App) getAddManageRemoteClustersPermissionsMigration() (permissionsMap,
func (a *App) getAddDownloadComplianceExportResult() (permissionsMap, error) {
transformations := []permissionTransformation{}
permissionsToAddComplianceRead := []string{model.PERMISSION_DOWNLOAD_COMPLIANCE_EXPORT_RESULT.Id, model.PERMISSION_READ_JOBS.Id}
permissionsToAddComplianceRead := []string{model.PERMISSION_DOWNLOAD_COMPLIANCE_EXPORT_RESULT.Id, model.PERMISSION_READ_DATA_RETENTION_JOB.Id}
permissionsToAddComplianceWrite := []string{model.PERMISSION_MANAGE_JOBS.Id}
// add the new permissions to system admin
@@ -562,6 +562,350 @@ func (a *App) getAddDownloadComplianceExportResult() (permissionsMap, error) {
return transformations, nil
}
func (a *App) getAddExperimentalSubsectionPermissions() (permissionsMap, error) {
transformations := []permissionTransformation{}
permissionsExperimentalRead := []string{model.PERMISSION_SYSCONSOLE_READ_EXPERIMENTAL_BLEVE.Id, model.PERMISSION_SYSCONSOLE_READ_EXPERIMENTAL_FEATURES.Id, model.PERMISSION_SYSCONSOLE_READ_EXPERIMENTAL_FEATURE_FLAGS.Id}
permissionsExperimentalWrite := []string{model.PERMISSION_SYSCONSOLE_WRITE_EXPERIMENTAL_BLEVE.Id, model.PERMISSION_SYSCONSOLE_WRITE_EXPERIMENTAL_FEATURES.Id, model.PERMISSION_SYSCONSOLE_WRITE_EXPERIMENTAL_FEATURE_FLAGS.Id}
// Give the new subsection READ permissions to any user with READ_EXPERIMENTAL
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_READ_EXPERIMENTAL.Id),
Add: permissionsExperimentalRead,
Remove: []string{model.PERMISSION_SYSCONSOLE_READ_EXPERIMENTAL.Id},
})
// Give the new subsection WRITE permissions to any user with WRITE_EXPERIMENTAL
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_WRITE_EXPERIMENTAL.Id),
Add: permissionsExperimentalWrite,
Remove: []string{model.PERMISSION_SYSCONSOLE_WRITE_EXPERIMENTAL.Id},
})
// Give the ancillary permissions MANAGE_JOBS and PURGE_BLEVE_INDEXES to anyone with WRITE_EXPERIMENTAL_BLEVE
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_WRITE_EXPERIMENTAL_BLEVE.Id),
Add: []string{model.PERMISSION_CREATE_POST_BLEVE_INDEXES_JOB.Id, model.PERMISSION_PURGE_BLEVE_INDEXES.Id},
})
return transformations, nil
}
func (a *App) getAddIntegrationsSubsectionPermissions() (permissionsMap, error) {
transformations := []permissionTransformation{}
permissionsIntegrationsRead := []string{model.PERMISSION_SYSCONSOLE_READ_INTEGRATIONS_INTEGRATION_MANAGEMENT.Id, model.PERMISSION_SYSCONSOLE_READ_INTEGRATIONS_BOT_ACCOUNTS.Id, model.PERMISSION_SYSCONSOLE_READ_INTEGRATIONS_GIF.Id, model.PERMISSION_SYSCONSOLE_READ_INTEGRATIONS_CORS.Id}
permissionsIntegrationsWrite := []string{model.PERMISSION_SYSCONSOLE_WRITE_INTEGRATIONS_INTEGRATION_MANAGEMENT.Id, model.PERMISSION_SYSCONSOLE_WRITE_INTEGRATIONS_BOT_ACCOUNTS.Id, model.PERMISSION_SYSCONSOLE_WRITE_INTEGRATIONS_GIF.Id, model.PERMISSION_SYSCONSOLE_WRITE_INTEGRATIONS_CORS.Id}
// Give the new subsection READ permissions to any user with READ_INTEGRATIONS
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_READ_INTEGRATIONS.Id),
Add: permissionsIntegrationsRead,
Remove: []string{model.PERMISSION_SYSCONSOLE_READ_INTEGRATIONS.Id},
})
// Give the new subsection WRITE permissions to any user with WRITE_EXPERIMENTAL
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_WRITE_INTEGRATIONS.Id),
Add: permissionsIntegrationsWrite,
Remove: []string{model.PERMISSION_SYSCONSOLE_WRITE_INTEGRATIONS.Id},
})
return transformations, nil
}
func (a *App) getAddSiteSubsectionPermissions() (permissionsMap, error) {
transformations := []permissionTransformation{}
permissionsSiteRead := []string{model.PERMISSION_SYSCONSOLE_READ_SITE_CUSTOMIZATION.Id, model.PERMISSION_SYSCONSOLE_READ_SITE_LOCALIZATION.Id, model.PERMISSION_SYSCONSOLE_READ_SITE_USERS_AND_TEAMS.Id, model.PERMISSION_SYSCONSOLE_READ_SITE_NOTIFICATIONS.Id, model.PERMISSION_SYSCONSOLE_READ_SITE_ANNOUNCEMENT_BANNER.Id, model.PERMISSION_SYSCONSOLE_READ_SITE_EMOJI.Id, model.PERMISSION_SYSCONSOLE_READ_SITE_POSTS.Id, model.PERMISSION_SYSCONSOLE_READ_SITE_FILE_SHARING_AND_DOWNLOADS.Id, model.PERMISSION_SYSCONSOLE_READ_SITE_PUBLIC_LINKS.Id, model.PERMISSION_SYSCONSOLE_READ_SITE_NOTICES.Id}
permissionsSiteWrite := []string{model.PERMISSION_SYSCONSOLE_WRITE_SITE_CUSTOMIZATION.Id, model.PERMISSION_SYSCONSOLE_WRITE_SITE_LOCALIZATION.Id, model.PERMISSION_SYSCONSOLE_WRITE_SITE_USERS_AND_TEAMS.Id, model.PERMISSION_SYSCONSOLE_WRITE_SITE_NOTIFICATIONS.Id, model.PERMISSION_SYSCONSOLE_WRITE_SITE_ANNOUNCEMENT_BANNER.Id, model.PERMISSION_SYSCONSOLE_WRITE_SITE_EMOJI.Id, model.PERMISSION_SYSCONSOLE_WRITE_SITE_POSTS.Id, model.PERMISSION_SYSCONSOLE_WRITE_SITE_FILE_SHARING_AND_DOWNLOADS.Id, model.PERMISSION_SYSCONSOLE_WRITE_SITE_PUBLIC_LINKS.Id, model.PERMISSION_SYSCONSOLE_WRITE_SITE_NOTICES.Id}
// Give the new subsection READ permissions to any user with READ_SITE
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_READ_SITE.Id),
Add: permissionsSiteRead,
Remove: []string{model.PERMISSION_SYSCONSOLE_READ_SITE.Id},
})
// Give the new subsection WRITE permissions to any user with WRITE_SITE
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_WRITE_SITE.Id),
Add: permissionsSiteWrite,
Remove: []string{model.PERMISSION_SYSCONSOLE_WRITE_SITE.Id},
})
// Give the ancillary permissions EDIT_BRAND to anyone with WRITE_SITE_CUSTOMIZATION
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_WRITE_SITE_CUSTOMIZATION.Id),
Add: []string{model.PERMISSION_EDIT_BRAND.Id},
})
return transformations, nil
}
func (a *App) getAddComplianceSubsectionPermissions() (permissionsMap, error) {
transformations := []permissionTransformation{}
permissionsComplianceRead := []string{model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE_DATA_RETENTION_POLICY.Id, model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE_COMPLIANCE_EXPORT.Id, model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE_COMPLIANCE_MONITORING.Id, model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE_CUSTOM_TERMS_OF_SERVICE.Id}
permissionsComplianceWrite := []string{model.PERMISSION_SYSCONSOLE_WRITE_COMPLIANCE_DATA_RETENTION_POLICY.Id, model.PERMISSION_SYSCONSOLE_WRITE_COMPLIANCE_COMPLIANCE_EXPORT.Id, model.PERMISSION_SYSCONSOLE_WRITE_COMPLIANCE_COMPLIANCE_MONITORING.Id, model.PERMISSION_SYSCONSOLE_WRITE_COMPLIANCE_CUSTOM_TERMS_OF_SERVICE.Id}
// Give the new subsection READ permissions to any user with READ_COMPLIANCE
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE.Id),
Add: permissionsComplianceRead,
Remove: []string{model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE.Id},
})
// Give the new subsection WRITE permissions to any user with WRITE_COMPLIANCE
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_WRITE_COMPLIANCE.Id),
Add: permissionsComplianceWrite,
Remove: []string{model.PERMISSION_SYSCONSOLE_WRITE_COMPLIANCE.Id},
})
// Ancilary permissions
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_WRITE_COMPLIANCE_DATA_RETENTION_POLICY.Id),
Add: []string{model.PERMISSION_CREATE_DATA_RETENTION_JOB.Id},
})
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE_DATA_RETENTION_POLICY.Id),
Add: []string{model.PERMISSION_READ_DATA_RETENTION_JOB.Id},
})
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_WRITE_COMPLIANCE_COMPLIANCE_EXPORT.Id),
Add: []string{model.PERMISSION_CREATE_COMPLIANCE_EXPORT_JOB.Id, model.PERMISSION_DOWNLOAD_COMPLIANCE_EXPORT_RESULT.Id},
})
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE_COMPLIANCE_EXPORT.Id),
Add: []string{model.PERMISSION_READ_COMPLIANCE_EXPORT_JOB.Id, model.PERMISSION_DOWNLOAD_COMPLIANCE_EXPORT_RESULT.Id},
})
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_READ_COMPLIANCE_CUSTOM_TERMS_OF_SERVICE.Id),
Add: []string{model.PERMISSION_READ_AUDITS.Id},
})
return transformations, nil
}
func (a *App) getAddEnvironmentSubsectionPermissions() (permissionsMap, error) {
transformations := []permissionTransformation{}
permissionsEnvironmentRead := []string{
model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_WEB_SERVER.Id,
model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_DATABASE.Id,
model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_ELASTICSEARCH.Id,
model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_FILE_STORAGE.Id,
model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_IMAGE_PROXY.Id,
model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_SMTP.Id,
model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_PUSH_NOTIFICATION_SERVER.Id,
model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_HIGH_AVAILABILITY.Id,
model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_RATE_LIMITING.Id,
model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_LOGGING.Id,
model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_SESSION_LENGTHS.Id,
model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_PERFORMANCE_MONITORING.Id,
model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_DEVELOPER.Id,
}
permissionsEnvironmentWrite := []string{
model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_WEB_SERVER.Id,
model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_DATABASE.Id,
model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_ELASTICSEARCH.Id,
model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_FILE_STORAGE.Id,
model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_IMAGE_PROXY.Id,
model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_SMTP.Id,
model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_PUSH_NOTIFICATION_SERVER.Id,
model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_HIGH_AVAILABILITY.Id,
model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_RATE_LIMITING.Id,
model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_LOGGING.Id,
model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_SESSION_LENGTHS.Id,
model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_PERFORMANCE_MONITORING.Id,
model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_DEVELOPER.Id,
}
// Give the new subsection READ permissions to any user with READ_ENVIRONMENT
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT.Id),
Add: permissionsEnvironmentRead,
Remove: []string{model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT.Id},
})
// Give the new subsection WRITE permissions to any user with WRITE_ENVIRONMENT
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT.Id),
Add: permissionsEnvironmentWrite,
Remove: []string{model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT.Id},
})
// Give these ancillary permissions to anyone with READ_ENVIRONMENT_ELASTICSEARCH
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_ELASTICSEARCH.Id),
Add: []string{
model.PERMISSION_READ_ELASTICSEARCH_POST_INDEXING_JOB.Id,
model.PERMISSION_READ_ELASTICSEARCH_POST_AGGREGATION_JOB.Id,
},
})
// Give these ancillary permissions to anyone with WRITE_ENVIRONMENT_WEB_SERVER
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_WEB_SERVER.Id),
Add: []string{
model.PERMISSION_TEST_SITE_URL.Id,
model.PERMISSION_RELOAD_CONFIG.Id,
model.PERMISSION_INVALIDATE_CACHES.Id,
},
})
// Give these ancillary permissions to anyone with WRITE_ENVIRONMENT_DATABASE
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_DATABASE.Id),
Add: []string{model.PERMISSION_RECYCLE_DATABASE_CONNECTIONS.Id},
})
// Give these ancillary permissions to anyone with WRITE_ENVIRONMENT_ELASTICSEARCH
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_ELASTICSEARCH.Id),
Add: []string{
model.PERMISSION_TEST_ELASTICSEARCH.Id,
model.PERMISSION_CREATE_ELASTICSEARCH_POST_INDEXING_JOB.Id,
model.PERMISSION_CREATE_ELASTICSEARCH_POST_AGGREGATION_JOB.Id,
model.PERMISSION_PURGE_ELASTICSEARCH_INDEXES.Id,
},
})
// Give these ancillary permissions to anyone with WRITE_ENVIRONMENT_FILE_STORAGE
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_FILE_STORAGE.Id),
Add: []string{model.PERMISSION_TEST_S3.Id},
})
return transformations, nil
}
func (a *App) getAddAboutSubsectionPermissions() (permissionsMap, error) {
transformations := []permissionTransformation{}
permissionsAboutRead := []string{model.PERMISSION_SYSCONSOLE_READ_ABOUT_EDITION_AND_LICENSE.Id}
permissionsAboutWrite := []string{model.PERMISSION_SYSCONSOLE_WRITE_ABOUT_EDITION_AND_LICENSE.Id}
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_READ_ABOUT.Id),
Add: permissionsAboutRead,
Remove: []string{model.PERMISSION_SYSCONSOLE_READ_ABOUT.Id},
})
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_WRITE_ABOUT.Id),
Add: permissionsAboutWrite,
Remove: []string{model.PERMISSION_SYSCONSOLE_WRITE_ABOUT.Id},
})
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_READ_ABOUT_EDITION_AND_LICENSE.Id),
Add: []string{model.PERMISSION_READ_LICENSE_INFORMATION.Id},
})
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_WRITE_ABOUT_EDITION_AND_LICENSE.Id),
Add: []string{model.PERMISSION_MANAGE_LICENSE_INFORMATION.Id},
})
return transformations, nil
}
func (a *App) getAddReportingSubsectionPermissions() (permissionsMap, error) {
transformations := []permissionTransformation{}
permissionsReportingRead := []string{
model.PERMISSION_SYSCONSOLE_READ_REPORTING_SITE_STATISTICS.Id,
model.PERMISSION_SYSCONSOLE_READ_REPORTING_TEAM_STATISTICS.Id,
model.PERMISSION_SYSCONSOLE_READ_REPORTING_SERVER_LOGS.Id,
}
permissionsReportingWrite := []string{
model.PERMISSION_SYSCONSOLE_WRITE_REPORTING_SITE_STATISTICS.Id,
model.PERMISSION_SYSCONSOLE_WRITE_REPORTING_TEAM_STATISTICS.Id,
model.PERMISSION_SYSCONSOLE_WRITE_REPORTING_SERVER_LOGS.Id,
}
// Give the new subsection READ permissions to any user with READ_REPORTING
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_READ_REPORTING.Id),
Add: permissionsReportingRead,
Remove: []string{model.PERMISSION_SYSCONSOLE_READ_REPORTING.Id},
})
// Give the new subsection WRITE permissions to any user with WRITE_REPORTING
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_WRITE_REPORTING.Id),
Add: permissionsReportingWrite,
Remove: []string{model.PERMISSION_SYSCONSOLE_WRITE_REPORTING.Id},
})
// Give the ancillary permissions PERMISSION_GET_ANALYTICS to anyone with PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_USERS or PERMISSION_SYSCONSOLE_READ_REPORTING_SITE_STATISTICS
transformations = append(transformations, permissionTransformation{
On: permissionOr(permissionExists(model.PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_USERS.Id), permissionExists(model.PERMISSION_SYSCONSOLE_READ_REPORTING_SITE_STATISTICS.Id)),
Add: []string{model.PERMISSION_GET_ANALYTICS.Id},
})
// Give the ancillary permissions PERMISSION_GET_LOGS to anyone with PERMISSION_SYSCONSOLE_READ_REPORTING_SERVER_LOGS
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_READ_REPORTING_SERVER_LOGS.Id),
Add: []string{model.PERMISSION_GET_LOGS.Id},
})
return transformations, nil
}
func (a *App) getAddAuthenticationSubsectionPermissions() (permissionsMap, error) {
transformations := []permissionTransformation{}
permissionsAuthenticationRead := []string{model.PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_SIGNUP.Id, model.PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_EMAIL.Id, model.PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_PASSWORD.Id, model.PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_MFA.Id, model.PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_LDAP.Id, model.PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_SAML.Id, model.PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_OPENID.Id, model.PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_GUEST_ACCESS.Id}
permissionsAuthenticationWrite := []string{model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION_SIGNUP.Id, model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION_EMAIL.Id, model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION_PASSWORD.Id, model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION_MFA.Id, model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION_LDAP.Id, model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION_SAML.Id, model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION_OPENID.Id, model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION_GUEST_ACCESS.Id}
// Give the new subsection READ permissions to any user with READ_AUTHENTICATION
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_READ_AUTHENTICATION.Id),
Add: permissionsAuthenticationRead,
Remove: []string{model.PERMISSION_SYSCONSOLE_READ_AUTHENTICATION.Id},
})
// Give the new subsection WRITE permissions to any user with WRITE_AUTHENTICATION
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION.Id),
Add: permissionsAuthenticationWrite,
Remove: []string{model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION.Id},
})
// Give the ancillary permissions for LDAP to anyone with WRITE_AUTHENTICATION_LDAP
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION_LDAP.Id),
Add: []string{model.PERMISSION_CREATE_LDAP_SYNC_JOB.Id, model.PERMISSION_TEST_LDAP.Id, model.PERMISSION_ADD_LDAP_PUBLIC_CERT.Id, model.PERMISSION_ADD_LDAP_PRIVATE_CERT.Id, model.PERMISSION_REMOVE_LDAP_PUBLIC_CERT.Id, model.PERMISSION_REMOVE_LDAP_PRIVATE_CERT.Id},
})
// Give the ancillary permissions PERMISSION_TEST_LDAP to anyone with READ_AUTHENTICATION_LDAP
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_LDAP.Id),
Add: []string{model.PERMISSION_READ_LDAP_SYNC_JOB.Id},
})
// Give the ancillary permissions PERMISSION_INVALIDATE_EMAIL_INVITE to anyone with WRITE_AUTHENTICATION_EMAIL
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION_EMAIL.Id),
Add: []string{model.PERMISSION_INVALIDATE_EMAIL_INVITE.Id},
})
// Give the ancillary permissions for SAML to anyone with WRITE_AUTHENTICATION_SAML
transformations = append(transformations, permissionTransformation{
On: permissionExists(model.PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION_SAML.Id),
Add: []string{model.PERMISSION_GET_SAML_METADATA_FROM_IDP.Id, model.PERMISSION_ADD_SAML_PUBLIC_CERT.Id, model.PERMISSION_ADD_SAML_PRIVATE_CERT.Id, model.PERMISSION_ADD_SAML_IDP_CERT.Id, model.PERMISSION_REMOVE_SAML_PUBLIC_CERT.Id, model.PERMISSION_REMOVE_SAML_PRIVATE_CERT.Id, model.PERMISSION_REMOVE_SAML_IDP_CERT.Id, model.PERMISSION_GET_SAML_CERT_STATUS.Id},
})
return transformations, nil
}
// DoPermissionsMigrations execute all the permissions migrations need by the current version.
func (a *App) DoPermissionsMigrations() error {
PermissionsMigrations := []struct {
@@ -586,6 +930,14 @@ func (a *App) DoPermissionsMigrations() error {
{Key: model.MIGRATION_KEY_ADD_SYSTEM_ROLES_PERMISSIONS, Migration: a.getSystemRolesPermissionsMigration},
{Key: model.MIGRATION_KEY_ADD_BILLING_PERMISSIONS, Migration: a.getBillingPermissionsMigration},
{Key: model.MIGRATION_KEY_ADD_DOWNLOAD_COMPLIANCE_EXPORT_RESULTS, Migration: a.getAddDownloadComplianceExportResult},
{Key: model.MIGRATION_KEY_ADD_EXPERIMENTAL_SUBSECTION_PERMISSIONS, Migration: a.getAddExperimentalSubsectionPermissions},
{Key: model.MIGRATION_KEY_ADD_AUTHENTICATION_SUBSECTION_PERMISSIONS, Migration: a.getAddAuthenticationSubsectionPermissions},
{Key: model.MIGRATION_KEY_ADD_INTEGRATIONS_SUBSECTION_PERMISSIONS, Migration: a.getAddIntegrationsSubsectionPermissions},
{Key: model.MIGRATION_KEY_ADD_SITE_SUBSECTION_PERMISSIONS, Migration: a.getAddSiteSubsectionPermissions},
{Key: model.MIGRATION_KEY_ADD_COMPLIANCE_SUBSECTION_PERMISSIONS, Migration: a.getAddComplianceSubsectionPermissions},
{Key: model.MIGRATION_KEY_ADD_ENVIRONMENT_SUBSECTION_PERMISSIONS, Migration: a.getAddEnvironmentSubsectionPermissions},
{Key: model.MIGRATION_KEY_ADD_ABOUT_SUBSECTION_PERMISSIONS, Migration: a.getAddAboutSubsectionPermissions},
{Key: model.MIGRATION_KEY_ADD_REPORTING_SUBSECTION_PERMISSIONS, Migration: a.getAddReportingSubsectionPermissions},
}
roles, err := a.GetAllRoles()

View File

@@ -89,12 +89,12 @@ func applyEnvironmentMap(inputConfig *model.Config, env map[string]string) *mode
// generateEnvironmentMap creates a map[string]interface{} containing true at the leaves mirroring the
// configuration structure so the client can know which env variables are overridden
func generateEnvironmentMap(env map[string]string) map[string]interface{} {
func generateEnvironmentMap(env map[string]string, filter func(reflect.StructField) bool) map[string]interface{} {
rType := reflect.TypeOf(model.Config{})
return generateEnvironmentMapWithBaseKey(env, rType, "MM")
return generateEnvironmentMapWithBaseKey(env, rType, "MM", filter)
}
func generateEnvironmentMapWithBaseKey(env map[string]string, rType reflect.Type, base string) map[string]interface{} {
func generateEnvironmentMapWithBaseKey(env map[string]string, rType reflect.Type, base string, filter func(reflect.StructField) bool) map[string]interface{} {
if rType.Kind() != reflect.Struct {
return nil
}
@@ -102,8 +102,11 @@ func generateEnvironmentMapWithBaseKey(env map[string]string, rType reflect.Type
mapRepresentation := make(map[string]interface{})
for i := 0; i < rType.NumField(); i++ {
rField := rType.Field(i)
if filter != nil && !filter(rField) {
continue
}
if rField.Type.Kind() == reflect.Struct {
if val := generateEnvironmentMapWithBaseKey(env, rField.Type, base+"_"+rField.Name); val != nil {
if val := generateEnvironmentMapWithBaseKey(env, rField.Type, base+"_"+rField.Name, filter); val != nil {
mapRepresentation[rField.Name] = val
}
} else {

View File

@@ -6,6 +6,7 @@ package config
import (
"bytes"
"encoding/json"
"reflect"
"sync"
"github.com/pkg/errors"
@@ -140,7 +141,13 @@ func (s *Store) GetNoEnv() *model.Config {
// GetEnvironmentOverrides fetches the configuration fields overridden by environment variables.
func (s *Store) GetEnvironmentOverrides() map[string]interface{} {
return generateEnvironmentMap(GetEnvironment())
return generateEnvironmentMap(GetEnvironment(), nil)
}
// GetEnvironmentOverridesWithFilter fetches the configuration fields overridden by environment variables.
// If filter is not nil and returns false for a struct field, that field will be omitted.
func (s *Store) GetEnvironmentOverridesWithFilter(filter func(reflect.StructField) bool) map[string]interface{} {
return generateEnvironmentMap(GetEnvironment(), filter)
}
// RemoveEnvironmentOverrides returns a new config without the environment

View File

@@ -1908,6 +1908,14 @@
"id": "api.io_error",
"translation": "input/output error"
},
{
"id": "api.job.retrieve.nopermissions",
"translation": "The job types of a job you are trying to retrieve does not contain permissions"
},
{
"id": "api.job.unable_to_create_job.incorrect_job_type",
"translation": "The job type of the job you are trying to create is invalid"
},
{
"id": "api.job.unable_to_download_job",
"translation": "Unable to download this job"

File diff suppressed because it is too large Load Diff

View File

@@ -38,6 +38,25 @@ const (
JOB_STATUS_WARNING = "warning"
)
var ALL_JOB_TYPES = [...]string{
JOB_TYPE_DATA_RETENTION,
JOB_TYPE_MESSAGE_EXPORT,
JOB_TYPE_ELASTICSEARCH_POST_INDEXING,
JOB_TYPE_ELASTICSEARCH_POST_AGGREGATION,
JOB_TYPE_BLEVE_POST_INDEXING,
JOB_TYPE_LDAP_SYNC,
JOB_TYPE_MIGRATIONS,
JOB_TYPE_PLUGINS,
JOB_TYPE_EXPIRY_NOTIFY,
JOB_TYPE_PRODUCT_NOTICES,
JOB_TYPE_ACTIVE_USERS,
JOB_TYPE_IMPORT_PROCESS,
JOB_TYPE_IMPORT_DELETE,
JOB_TYPE_EXPORT_PROCESS,
JOB_TYPE_EXPORT_DELETE,
JOB_TYPE_CLOUD,
}
type Job struct {
Id string `json:"id"`
Type string `json:"type"`

View File

@@ -26,4 +26,12 @@ const (
MIGRATION_KEY_ADD_MANAGE_SHARED_CHANNEL_PERMISSIONS = "manage_shared_channel_permissions"
MIGRATION_KEY_ADD_MANAGE_REMOTE_CLUSTERS_PERMISSIONS = "manage_remote_clusters_permissions"
MIGRATION_KEY_ADD_DOWNLOAD_COMPLIANCE_EXPORT_RESULTS = "download_compliance_export_results"
MIGRATION_KEY_ADD_COMPLIANCE_SUBSECTION_PERMISSIONS = "compliance_subsection_permissions"
MIGRATION_KEY_ADD_EXPERIMENTAL_SUBSECTION_PERMISSIONS = "experimental_subsection_permissions"
MIGRATION_KEY_ADD_AUTHENTICATION_SUBSECTION_PERMISSIONS = "authentication_subsection_permissions"
MIGRATION_KEY_ADD_SITE_SUBSECTION_PERMISSIONS = "site_subsection_permissions"
MIGRATION_KEY_ADD_ENVIRONMENT_SUBSECTION_PERMISSIONS = "environment_subsection_permissions"
MIGRATION_KEY_ADD_REPORTING_SUBSECTION_PERMISSIONS = "reporting_subsection_permissions"
MIGRATION_KEY_ADD_ABOUT_SUBSECTION_PERMISSIONS = "about_subsection_permissions"
MIGRATION_KEY_ADD_INTEGRATIONS_SUBSECTION_PERMISSIONS = "integrations_subsection_permissions"
)

File diff suppressed because it is too large Load Diff

View File

@@ -1,21 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package model
import (
"testing"
"github.com/stretchr/testify/assert"
)
// This is a test to ensure that we don't accidentally add more permissions than can fit
// in the database column for role permissions.
func TestPermissionsLength(t *testing.T) {
permissionsString := ""
for _, permission := range AllPermissions {
permissionsString += " " + permission.Id
}
assert.True(t, len(permissionsString) < 4096)
}

View File

@@ -47,6 +47,12 @@ func init() {
// When updating the values here, the values in mattermost-redux must also be updated.
SysconsoleAncillaryPermissions = map[string][]*Permission{
PERMISSION_SYSCONSOLE_READ_ABOUT_EDITION_AND_LICENSE.Id: {
PERMISSION_READ_LICENSE_INFORMATION,
},
PERMISSION_SYSCONSOLE_WRITE_ABOUT_EDITION_AND_LICENSE.Id: {
PERMISSION_MANAGE_LICENSE_INFORMATION,
},
PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_CHANNELS.Id: {
PERMISSION_READ_PUBLIC_CHANNEL,
PERMISSION_READ_CHANNEL,
@@ -55,26 +61,44 @@ func init() {
},
PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_USERS.Id: {
PERMISSION_READ_OTHER_USERS_TEAMS,
PERMISSION_GET_ANALYTICS,
},
PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_TEAMS.Id: {
PERMISSION_LIST_PRIVATE_TEAMS,
PERMISSION_LIST_PUBLIC_TEAMS,
PERMISSION_VIEW_TEAM,
},
PERMISSION_SYSCONSOLE_WRITE_COMPLIANCE.Id: {
PERMISSION_MANAGE_JOBS,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_ELASTICSEARCH.Id: {
PERMISSION_READ_ELASTICSEARCH_POST_INDEXING_JOB,
PERMISSION_READ_ELASTICSEARCH_POST_AGGREGATION_JOB,
},
PERMISSION_SYSCONSOLE_READ_COMPLIANCE.Id: {
PERMISSION_READ_JOBS,
PERMISSION_DOWNLOAD_COMPLIANCE_EXPORT_RESULT,
PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_WEB_SERVER.Id: {
PERMISSION_TEST_SITE_URL,
PERMISSION_RELOAD_CONFIG,
PERMISSION_INVALIDATE_CACHES,
},
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT.Id: {
PERMISSION_READ_JOBS,
PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_DATABASE.Id: {
PERMISSION_RECYCLE_DATABASE_CONNECTIONS,
},
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION.Id: {
PERMISSION_READ_JOBS,
PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_ELASTICSEARCH.Id: {
PERMISSION_TEST_ELASTICSEARCH,
PERMISSION_CREATE_ELASTICSEARCH_POST_INDEXING_JOB,
PERMISSION_CREATE_ELASTICSEARCH_POST_AGGREGATION_JOB,
PERMISSION_PURGE_ELASTICSEARCH_INDEXES,
},
PERMISSION_SYSCONSOLE_READ_REPORTING.Id: {
PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_FILE_STORAGE.Id: {
PERMISSION_TEST_S3,
},
PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_SMTP.Id: {
PERMISSION_TEST_EMAIL,
},
PERMISSION_SYSCONSOLE_READ_REPORTING_SERVER_LOGS.Id: {
PERMISSION_GET_LOGS,
},
PERMISSION_SYSCONSOLE_READ_REPORTING_SITE_STATISTICS.Id: {
PERMISSION_GET_ANALYTICS,
},
PERMISSION_SYSCONSOLE_READ_REPORTING_TEAM_STATISTICS.Id: {
PERMISSION_VIEW_TEAM,
},
PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_USERS.Id: {
@@ -109,12 +133,54 @@ func init() {
PERMISSION_CONVERT_PUBLIC_CHANNEL_TO_PRIVATE,
PERMISSION_CONVERT_PRIVATE_CHANNEL_TO_PUBLIC,
},
PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT.Id: {
PERMISSION_MANAGE_JOBS,
},
PERMISSION_SYSCONSOLE_WRITE_SITE.Id: {
PERMISSION_SYSCONSOLE_WRITE_SITE_CUSTOMIZATION.Id: {
PERMISSION_EDIT_BRAND,
},
PERMISSION_SYSCONSOLE_WRITE_COMPLIANCE_DATA_RETENTION_POLICY.Id: {
PERMISSION_CREATE_DATA_RETENTION_JOB,
},
PERMISSION_SYSCONSOLE_READ_COMPLIANCE_DATA_RETENTION_POLICY.Id: {
PERMISSION_READ_DATA_RETENTION_JOB,
},
PERMISSION_SYSCONSOLE_WRITE_COMPLIANCE_COMPLIANCE_EXPORT.Id: {
PERMISSION_CREATE_COMPLIANCE_EXPORT_JOB,
PERMISSION_DOWNLOAD_COMPLIANCE_EXPORT_RESULT,
},
PERMISSION_SYSCONSOLE_READ_COMPLIANCE_COMPLIANCE_EXPORT.Id: {
PERMISSION_READ_COMPLIANCE_EXPORT_JOB,
PERMISSION_DOWNLOAD_COMPLIANCE_EXPORT_RESULT,
},
PERMISSION_SYSCONSOLE_READ_COMPLIANCE_CUSTOM_TERMS_OF_SERVICE.Id: {
PERMISSION_READ_AUDITS,
},
PERMISSION_SYSCONSOLE_WRITE_EXPERIMENTAL_BLEVE.Id: {
PERMISSION_CREATE_POST_BLEVE_INDEXES_JOB,
PERMISSION_PURGE_BLEVE_INDEXES,
},
PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION_LDAP.Id: {
PERMISSION_CREATE_LDAP_SYNC_JOB,
PERMISSION_ADD_LDAP_PUBLIC_CERT,
PERMISSION_REMOVE_LDAP_PUBLIC_CERT,
PERMISSION_ADD_LDAP_PRIVATE_CERT,
PERMISSION_REMOVE_LDAP_PRIVATE_CERT,
},
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_LDAP.Id: {
PERMISSION_TEST_LDAP,
PERMISSION_READ_LDAP_SYNC_JOB,
},
PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION_EMAIL.Id: {
PERMISSION_INVALIDATE_EMAIL_INVITE,
},
PERMISSION_SYSCONSOLE_WRITE_AUTHENTICATION_SAML.Id: {
PERMISSION_GET_SAML_METADATA_FROM_IDP,
PERMISSION_ADD_SAML_PUBLIC_CERT,
PERMISSION_ADD_SAML_PRIVATE_CERT,
PERMISSION_ADD_SAML_IDP_CERT,
PERMISSION_REMOVE_SAML_PUBLIC_CERT,
PERMISSION_REMOVE_SAML_PRIVATE_CERT,
PERMISSION_REMOVE_SAML_IDP_CERT,
PERMISSION_GET_SAML_CERT_STATUS,
},
}
SystemUserManagerDefaultPermissions = []string{
@@ -125,29 +191,76 @@ func init() {
PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_GROUPS.Id,
PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_TEAMS.Id,
PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_CHANNELS.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_SIGNUP.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_EMAIL.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_PASSWORD.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_MFA.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_LDAP.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_SAML.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_OPENID.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_GUEST_ACCESS.Id,
}
SystemReadOnlyAdminDefaultPermissions = []string{
PERMISSION_SYSCONSOLE_READ_ABOUT.Id,
PERMISSION_SYSCONSOLE_READ_REPORTING.Id,
PERMISSION_SYSCONSOLE_READ_ABOUT_EDITION_AND_LICENSE.Id,
PERMISSION_SYSCONSOLE_READ_REPORTING_SITE_STATISTICS.Id,
PERMISSION_SYSCONSOLE_READ_REPORTING_TEAM_STATISTICS.Id,
PERMISSION_SYSCONSOLE_READ_REPORTING_SERVER_LOGS.Id,
PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_USERS.Id,
PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_GROUPS.Id,
PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_TEAMS.Id,
PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_CHANNELS.Id,
PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_PERMISSIONS.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT.Id,
PERMISSION_SYSCONSOLE_READ_SITE.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_WEB_SERVER.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_DATABASE.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_ELASTICSEARCH.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_FILE_STORAGE.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_IMAGE_PROXY.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_SMTP.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_PUSH_NOTIFICATION_SERVER.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_HIGH_AVAILABILITY.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_RATE_LIMITING.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_LOGGING.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_SESSION_LENGTHS.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_PERFORMANCE_MONITORING.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_DEVELOPER.Id,
PERMISSION_SYSCONSOLE_READ_SITE_CUSTOMIZATION.Id,
PERMISSION_SYSCONSOLE_READ_SITE_LOCALIZATION.Id,
PERMISSION_SYSCONSOLE_READ_SITE_USERS_AND_TEAMS.Id,
PERMISSION_SYSCONSOLE_READ_SITE_NOTIFICATIONS.Id,
PERMISSION_SYSCONSOLE_READ_SITE_ANNOUNCEMENT_BANNER.Id,
PERMISSION_SYSCONSOLE_READ_SITE_EMOJI.Id,
PERMISSION_SYSCONSOLE_READ_SITE_POSTS.Id,
PERMISSION_SYSCONSOLE_READ_SITE_FILE_SHARING_AND_DOWNLOADS.Id,
PERMISSION_SYSCONSOLE_READ_SITE_PUBLIC_LINKS.Id,
PERMISSION_SYSCONSOLE_READ_SITE_NOTICES.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_SIGNUP.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_EMAIL.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_PASSWORD.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_MFA.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_LDAP.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_SAML.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_OPENID.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_GUEST_ACCESS.Id,
PERMISSION_SYSCONSOLE_READ_PLUGINS.Id,
PERMISSION_SYSCONSOLE_READ_COMPLIANCE.Id,
PERMISSION_SYSCONSOLE_READ_INTEGRATIONS.Id,
PERMISSION_SYSCONSOLE_READ_EXPERIMENTAL.Id,
PERMISSION_SYSCONSOLE_READ_INTEGRATIONS_INTEGRATION_MANAGEMENT.Id,
PERMISSION_SYSCONSOLE_READ_INTEGRATIONS_BOT_ACCOUNTS.Id,
PERMISSION_SYSCONSOLE_READ_INTEGRATIONS_GIF.Id,
PERMISSION_SYSCONSOLE_READ_INTEGRATIONS_CORS.Id,
PERMISSION_SYSCONSOLE_READ_COMPLIANCE_DATA_RETENTION_POLICY.Id,
PERMISSION_SYSCONSOLE_READ_COMPLIANCE_COMPLIANCE_EXPORT.Id,
PERMISSION_SYSCONSOLE_READ_COMPLIANCE_COMPLIANCE_MONITORING.Id,
PERMISSION_SYSCONSOLE_READ_COMPLIANCE_CUSTOM_TERMS_OF_SERVICE.Id,
PERMISSION_SYSCONSOLE_READ_EXPERIMENTAL_FEATURES.Id,
PERMISSION_SYSCONSOLE_READ_EXPERIMENTAL_FEATURE_FLAGS.Id,
PERMISSION_SYSCONSOLE_READ_EXPERIMENTAL_BLEVE.Id,
}
SystemManagerDefaultPermissions = []string{
PERMISSION_SYSCONSOLE_READ_ABOUT.Id,
PERMISSION_SYSCONSOLE_READ_REPORTING.Id,
PERMISSION_SYSCONSOLE_READ_ABOUT_EDITION_AND_LICENSE.Id,
PERMISSION_SYSCONSOLE_READ_REPORTING_SITE_STATISTICS.Id,
PERMISSION_SYSCONSOLE_READ_REPORTING_TEAM_STATISTICS.Id,
PERMISSION_SYSCONSOLE_READ_REPORTING_SERVER_LOGS.Id,
PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_GROUPS.Id,
PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_TEAMS.Id,
PERMISSION_SYSCONSOLE_READ_USERMANAGEMENT_CHANNELS.Id,
@@ -156,20 +269,75 @@ func init() {
PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_TEAMS.Id,
PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_CHANNELS.Id,
PERMISSION_SYSCONSOLE_WRITE_USERMANAGEMENT_PERMISSIONS.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT.Id,
PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT.Id,
PERMISSION_SYSCONSOLE_READ_SITE.Id,
PERMISSION_SYSCONSOLE_WRITE_SITE.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_WEB_SERVER.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_DATABASE.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_ELASTICSEARCH.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_FILE_STORAGE.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_IMAGE_PROXY.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_SMTP.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_PUSH_NOTIFICATION_SERVER.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_HIGH_AVAILABILITY.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_RATE_LIMITING.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_LOGGING.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_SESSION_LENGTHS.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_PERFORMANCE_MONITORING.Id,
PERMISSION_SYSCONSOLE_READ_ENVIRONMENT_DEVELOPER.Id,
PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_WEB_SERVER.Id,
PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_DATABASE.Id,
PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_ELASTICSEARCH.Id,
PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_FILE_STORAGE.Id,
PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_IMAGE_PROXY.Id,
PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_SMTP.Id,
PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_PUSH_NOTIFICATION_SERVER.Id,
PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_HIGH_AVAILABILITY.Id,
PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_RATE_LIMITING.Id,
PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_LOGGING.Id,
PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_SESSION_LENGTHS.Id,
PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_PERFORMANCE_MONITORING.Id,
PERMISSION_SYSCONSOLE_WRITE_ENVIRONMENT_DEVELOPER.Id,
PERMISSION_SYSCONSOLE_READ_SITE_CUSTOMIZATION.Id,
PERMISSION_SYSCONSOLE_WRITE_SITE_CUSTOMIZATION.Id,
PERMISSION_SYSCONSOLE_READ_SITE_LOCALIZATION.Id,
PERMISSION_SYSCONSOLE_WRITE_SITE_LOCALIZATION.Id,
PERMISSION_SYSCONSOLE_READ_SITE_USERS_AND_TEAMS.Id,
PERMISSION_SYSCONSOLE_WRITE_SITE_USERS_AND_TEAMS.Id,
PERMISSION_SYSCONSOLE_READ_SITE_NOTIFICATIONS.Id,
PERMISSION_SYSCONSOLE_WRITE_SITE_NOTIFICATIONS.Id,
PERMISSION_SYSCONSOLE_READ_SITE_ANNOUNCEMENT_BANNER.Id,
PERMISSION_SYSCONSOLE_WRITE_SITE_ANNOUNCEMENT_BANNER.Id,
PERMISSION_SYSCONSOLE_READ_SITE_EMOJI.Id,
PERMISSION_SYSCONSOLE_WRITE_SITE_EMOJI.Id,
PERMISSION_SYSCONSOLE_READ_SITE_POSTS.Id,
PERMISSION_SYSCONSOLE_WRITE_SITE_POSTS.Id,
PERMISSION_SYSCONSOLE_READ_SITE_FILE_SHARING_AND_DOWNLOADS.Id,
PERMISSION_SYSCONSOLE_WRITE_SITE_FILE_SHARING_AND_DOWNLOADS.Id,
PERMISSION_SYSCONSOLE_READ_SITE_PUBLIC_LINKS.Id,
PERMISSION_SYSCONSOLE_WRITE_SITE_PUBLIC_LINKS.Id,
PERMISSION_SYSCONSOLE_READ_SITE_NOTICES.Id,
PERMISSION_SYSCONSOLE_WRITE_SITE_NOTICES.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_SIGNUP.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_EMAIL.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_PASSWORD.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_MFA.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_LDAP.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_SAML.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_OPENID.Id,
PERMISSION_SYSCONSOLE_READ_AUTHENTICATION_GUEST_ACCESS.Id,
PERMISSION_SYSCONSOLE_READ_PLUGINS.Id,
PERMISSION_SYSCONSOLE_READ_INTEGRATIONS.Id,
PERMISSION_SYSCONSOLE_WRITE_INTEGRATIONS.Id,
PERMISSION_SYSCONSOLE_READ_INTEGRATIONS_INTEGRATION_MANAGEMENT.Id,
PERMISSION_SYSCONSOLE_READ_INTEGRATIONS_BOT_ACCOUNTS.Id,
PERMISSION_SYSCONSOLE_READ_INTEGRATIONS_GIF.Id,
PERMISSION_SYSCONSOLE_READ_INTEGRATIONS_CORS.Id,
PERMISSION_SYSCONSOLE_WRITE_INTEGRATIONS_INTEGRATION_MANAGEMENT.Id,
PERMISSION_SYSCONSOLE_WRITE_INTEGRATIONS_BOT_ACCOUNTS.Id,
PERMISSION_SYSCONSOLE_WRITE_INTEGRATIONS_GIF.Id,
PERMISSION_SYSCONSOLE_WRITE_INTEGRATIONS_CORS.Id,
}
// Add the ancillary permissions to each system role
SystemUserManagerDefaultPermissions = addAncillaryPermissions(SystemUserManagerDefaultPermissions)
SystemReadOnlyAdminDefaultPermissions = addAncillaryPermissions(SystemReadOnlyAdminDefaultPermissions)
SystemManagerDefaultPermissions = addAncillaryPermissions(SystemManagerDefaultPermissions)
SystemUserManagerDefaultPermissions = AddAncillaryPermissions(SystemUserManagerDefaultPermissions)
SystemReadOnlyAdminDefaultPermissions = AddAncillaryPermissions(SystemReadOnlyAdminDefaultPermissions)
SystemManagerDefaultPermissions = AddAncillaryPermissions(SystemManagerDefaultPermissions)
}
type RoleType string
@@ -772,7 +940,7 @@ func MakeDefaultRoles() map[string]*Role {
return roles
}
func addAncillaryPermissions(permissions []string) []string {
func AddAncillaryPermissions(permissions []string) []string {
for _, permission := range permissions {
if ancillaryPermissions, ok := SysconsoleAncillaryPermissions[permission]; ok {
for _, ancillaryPermission := range ancillaryPermissions {

View File

@@ -697,3 +697,18 @@ func filterBlocklist(r rune) rune {
return r
}
// UniqueStrings returns a unique subset of the string slice provided.
func UniqueStrings(input []string) []string {
u := make([]string, 0, len(input))
m := make(map[string]bool)
for _, val := range input {
if _, ok := m[val]; !ok {
m[val] = true
u = append(u, val)
}
}
return u
}

View File

@@ -866,3 +866,36 @@ func TestIsValidHttpUrl(t *testing.T) {
})
}
}
func TestUniqueStrings(t *testing.T) {
cases := []struct {
Input []string
Result []string
}{
{
Input: []string{"1", "2", "3", "3", "3"},
Result: []string{"1", "2", "3"},
},
{
Input: []string{"1", "2", "3", "4", "5"},
Result: []string{"1", "2", "3", "4", "5"},
},
{
Input: []string{"1", "1", "1", "3", "3"},
Result: []string{"1", "3"},
},
{
Input: []string{"1", "1", "1", "1", "1"},
Result: []string{"1"},
},
{
Input: []string{},
Result: []string{},
},
}
for _, tc := range cases {
actual := UniqueStrings(tc.Input)
require.Equalf(t, actual, tc.Result, "case: %v\tshould returned: %#v", tc, tc.Result)
}
}

View File

@@ -445,7 +445,7 @@ CREATE TABLE public.roles (
createat bigint,
updateat bigint,
deleteat bigint,
permissions character varying(4096),
permissions text,
schememanaged boolean,
builtin boolean
);

View File

@@ -4185,6 +4185,24 @@ func (s *OpenTracingLayerJobStore) GetAllByTypePage(jobType string, offset int,
return result, err
}
func (s *OpenTracingLayerJobStore) GetAllByTypesPage(jobTypes []string, offset int, limit int) ([]*model.Job, error) {
origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "JobStore.GetAllByTypesPage")
s.Root.Store.SetContext(newCtx)
defer func() {
s.Root.Store.SetContext(origCtx)
}()
defer span.Finish()
result, err := s.JobStore.GetAllByTypesPage(jobTypes, offset, limit)
if err != nil {
span.LogFields(spanlog.Error(err))
ext.Error.Set(span, true)
}
return result, err
}
func (s *OpenTracingLayerJobStore) GetAllPage(offset int, limit int) ([]*model.Job, error) {
origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "JobStore.GetAllPage")

View File

@@ -4516,6 +4516,26 @@ func (s *RetryLayerJobStore) GetAllByTypePage(jobType string, offset int, limit
}
func (s *RetryLayerJobStore) GetAllByTypesPage(jobTypes []string, offset int, limit int) ([]*model.Job, error) {
tries := 0
for {
result, err := s.JobStore.GetAllByTypesPage(jobTypes, offset, limit)
if err == nil {
return result, nil
}
if !isRepeatableError(err) {
return result, err
}
tries++
if tries >= 3 {
err = errors.Wrap(err, "giving up after 3 consecutive repeatable transaction failures")
return result, err
}
}
}
func (s *RetryLayerJobStore) GetAllPage(offset int, limit int) ([]*model.Job, error) {
tries := 0

View File

@@ -156,6 +156,25 @@ func (jss SqlJobStore) GetAllPage(offset int, limit int) ([]*model.Job, error) {
return statuses, nil
}
func (jss SqlJobStore) GetAllByTypesPage(jobTypes []string, offset int, limit int) ([]*model.Job, error) {
query, args, err := jss.getQueryBuilder().
Select("*").
From("Jobs").
Where(sq.Eq{"Type": jobTypes}).
OrderBy("CreateAt DESC").
Limit(uint64(limit)).
Offset(uint64(offset)).ToSql()
if err != nil {
return nil, errors.Wrap(err, "job_tosql")
}
var jobs []*model.Job
if _, err = jss.GetReplica().Select(&jobs, query, args...); err != nil {
return nil, errors.Wrapf(err, "failed to find Jobs with types")
}
return jobs, nil
}
func (jss SqlJobStore) GetAllByType(jobType string) ([]*model.Job, error) {
query, args, err := jss.getQueryBuilder().
Select("*").

View File

@@ -91,7 +91,7 @@ func newSqlRoleStore(sqlStore *SqlStore) store.RoleStore {
table.ColMap("Name").SetMaxSize(64).SetUnique(true)
table.ColMap("DisplayName").SetMaxSize(128)
table.ColMap("Description").SetMaxSize(1024)
table.ColMap("Permissions").SetMaxSize(4096)
table.ColMap("Permissions")
}
return s
}

View File

@@ -1011,6 +1011,7 @@ func upgradeDatabaseToVersion534(sqlStore *SqlStore) {
func upgradeDatabaseToVersion535(sqlStore *SqlStore) {
// if shouldPerformUpgrade(sqlStore, Version5340, Version5350) {
sqlStore.AlterColumnTypeIfExists("Roles", "Permissions", "longtext", "text")
sqlStore.CreateColumnIfNotExists("SidebarCategories", "Collapsed", "tinyint(1)", "boolean", "0")

View File

@@ -630,6 +630,7 @@ type JobStore interface {
GetAllPage(offset int, limit int) ([]*model.Job, error)
GetAllByType(jobType string) ([]*model.Job, error)
GetAllByTypePage(jobType string, offset int, limit int) ([]*model.Job, error)
GetAllByTypesPage(jobTypes []string, offset int, limit int) ([]*model.Job, error)
GetAllByStatus(status string) ([]*model.Job, error)
GetNewestJobByStatusAndType(status string, jobType string) (*model.Job, error)
GetNewestJobByStatusesAndType(statuses []string, jobType string) (*model.Job, error)

View File

@@ -20,6 +20,7 @@ func TestJobStore(t *testing.T, ss store.Store) {
t.Run("JobSaveGet", func(t *testing.T) { testJobSaveGet(t, ss) })
t.Run("JobGetAllByType", func(t *testing.T) { testJobGetAllByType(t, ss) })
t.Run("JobGetAllByTypePage", func(t *testing.T) { testJobGetAllByTypePage(t, ss) })
t.Run("JobGetAllByTypesPage", func(t *testing.T) { testJobGetAllByTypesPage(t, ss) })
t.Run("JobGetAllPage", func(t *testing.T) { testJobGetAllPage(t, ss) })
t.Run("JobGetAllByStatus", func(t *testing.T) { testJobGetAllByStatus(t, ss) })
t.Run("GetNewestJobByStatusAndType", func(t *testing.T) { testJobStoreGetNewestJobByStatusAndType(t, ss) })
@@ -127,6 +128,61 @@ func testJobGetAllByTypePage(t *testing.T, ss store.Store) {
require.Equal(t, received[0].Id, jobs[1].Id, "should've received oldest job last")
}
func testJobGetAllByTypesPage(t *testing.T, ss store.Store) {
jobType := model.NewId()
jobType2 := model.NewId()
jobs := []*model.Job{
{
Id: model.NewId(),
Type: jobType,
CreateAt: 1000,
},
{
Id: model.NewId(),
Type: jobType,
CreateAt: 999,
},
{
Id: model.NewId(),
Type: jobType2,
CreateAt: 1001,
},
{
Id: model.NewId(),
Type: model.NewId(),
CreateAt: 1002,
},
}
for _, job := range jobs {
_, err := ss.Job().Save(job)
require.NoError(t, err)
defer ss.Job().Delete(job.Id)
}
// test return all
jobTypes := []string{jobType, jobType2}
received, err := ss.Job().GetAllByTypesPage(jobTypes, 0, 4)
require.NoError(t, err)
require.Len(t, received, 3)
require.Equal(t, received[0].Id, jobs[2].Id, "should've received newest job first")
require.Equal(t, received[1].Id, jobs[0].Id, "should've received second newest job second")
// test paging
jobTypes = []string{jobType, jobType2}
received, err = ss.Job().GetAllByTypesPage(jobTypes, 0, 2)
require.NoError(t, err)
require.Len(t, received, 2)
require.Equal(t, received[0].Id, jobs[2].Id, "should've received newest job first")
require.Equal(t, received[1].Id, jobs[0].Id, "should've received second newest job second")
received, err = ss.Job().GetAllByTypesPage(jobTypes, 2, 2)
require.NoError(t, err)
require.Len(t, received, 1)
require.Equal(t, received[0].Id, jobs[1].Id, "should've received oldest job last")
}
func testJobGetAllPage(t *testing.T, ss store.Store) {
jobType := model.NewId()
createAtTime := model.GetMillis()

View File

@@ -127,6 +127,29 @@ func (_m *JobStore) GetAllByTypePage(jobType string, offset int, limit int) ([]*
return r0, r1
}
// GetAllByTypesPage provides a mock function with given fields: jobTypes, offset, limit
func (_m *JobStore) GetAllByTypesPage(jobTypes []string, offset int, limit int) ([]*model.Job, error) {
ret := _m.Called(jobTypes, offset, limit)
var r0 []*model.Job
if rf, ok := ret.Get(0).(func([]string, int, int) []*model.Job); ok {
r0 = rf(jobTypes, offset, limit)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]*model.Job)
}
}
var r1 error
if rf, ok := ret.Get(1).(func([]string, int, int) error); ok {
r1 = rf(jobTypes, offset, limit)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetAllPage provides a mock function with given fields: offset, limit
func (_m *JobStore) GetAllPage(offset int, limit int) ([]*model.Job, error) {
ret := _m.Called(offset, limit)

View File

@@ -3809,6 +3809,22 @@ func (s *TimerLayerJobStore) GetAllByTypePage(jobType string, offset int, limit
return result, err
}
func (s *TimerLayerJobStore) GetAllByTypesPage(jobTypes []string, offset int, limit int) ([]*model.Job, error) {
start := timemodule.Now()
result, err := s.JobStore.GetAllByTypesPage(jobTypes, offset, limit)
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
if s.Root.Metrics != nil {
success := "false"
if err == nil {
success = "true"
}
s.Root.Metrics.ObserveStoreMethodDuration("JobStore.GetAllByTypesPage", success, elapsed)
}
return result, err
}
func (s *TimerLayerJobStore) GetAllPage(offset int, limit int) ([]*model.Job, error) {
start := timemodule.Now()

View File

@@ -50,6 +50,14 @@ func GetMockStoreForSetupFunctions() *mocks.Store {
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_SYSTEM_ROLES_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_SYSTEM_ROLES_PERMISSIONS, Value: "true"}, nil)
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_BILLING_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_BILLING_PERMISSIONS, Value: "true"}, nil)
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_DOWNLOAD_COMPLIANCE_EXPORT_RESULTS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_DOWNLOAD_COMPLIANCE_EXPORT_RESULTS, Value: "true"}, nil)
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_SITE_SUBSECTION_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_SITE_SUBSECTION_PERMISSIONS, Value: "true"}, nil)
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_EXPERIMENTAL_SUBSECTION_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_EXPERIMENTAL_SUBSECTION_PERMISSIONS, Value: "true"}, nil)
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_AUTHENTICATION_SUBSECTION_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_AUTHENTICATION_SUBSECTION_PERMISSIONS, Value: "true"}, nil)
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_COMPLIANCE_SUBSECTION_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_EXPERIMENTAL_SUBSECTION_PERMISSIONS, Value: "true"}, nil)
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_ENVIRONMENT_SUBSECTION_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_ENVIRONMENT_SUBSECTION_PERMISSIONS, Value: "true"}, nil)
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_REPORTING_SUBSECTION_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_REPORTING_SUBSECTION_PERMISSIONS, Value: "true"}, nil)
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_ABOUT_SUBSECTION_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_ABOUT_SUBSECTION_PERMISSIONS, Value: "true"}, nil)
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_INTEGRATIONS_SUBSECTION_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_INTEGRATIONS_SUBSECTION_PERMISSIONS, Value: "true"}, nil)
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_MANAGE_SHARED_CHANNEL_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_MANAGE_SHARED_CHANNEL_PERMISSIONS, Value: "true"}, nil)
systemStore.On("GetByName", model.MIGRATION_KEY_ADD_MANAGE_REMOTE_CLUSTERS_PERMISSIONS).Return(&model.System{Name: model.MIGRATION_KEY_ADD_MANAGE_REMOTE_CLUSTERS_PERMISSIONS, Value: "true"}, nil)
systemStore.On("Get").Return(make(model.StringMap), nil)