Merge pull request #2442 from mattermost/PLT-2115

PLT-2115 adding compliance feature
Этот коммит содержится в:
Corey Hulen
2016-03-17 13:16:10 -07:00
родитель 8d571ee498 2e5cc29738
Коммит 53d7718e57
37 изменённых файлов: 1935 добавлений и 84 удалений

Просмотреть файл

@@ -474,6 +474,42 @@ func (c *Client) TestEmail(config *Config) (*Result, *AppError) {
}
}
func (c *Client) GetComplianceReports() (*Result, *AppError) {
if r, err := c.DoApiGet("/admin/compliance_reports", "", ""); err != nil {
return nil, err
} else {
return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), CompliancesFromJson(r.Body)}, nil
}
}
func (c *Client) SaveComplianceReport(job *Compliance) (*Result, *AppError) {
if r, err := c.DoApiPost("/admin/save_compliance_report", job.ToJson()); err != nil {
return nil, err
} else {
return &Result{r.Header.Get(HEADER_REQUEST_ID),
r.Header.Get(HEADER_ETAG_SERVER), ComplianceFromJson(r.Body)}, nil
}
}
func (c *Client) DownloadComplianceReport(id string) (*Result, *AppError) {
var rq *http.Request
rq, _ = http.NewRequest("GET", c.ApiUrl+"/admin/download_compliance_report/"+id, nil)
if len(c.AuthToken) > 0 {
rq.Header.Set(HEADER_AUTH, "BEARER "+c.AuthToken)
}
if rp, err := c.HttpClient.Do(rq); err != nil {
return nil, NewLocAppError("/admin/download_compliance_report", "model.client.connecting.app_error", nil, err.Error())
} else if rp.StatusCode >= 300 {
return nil, AppErrorFromJson(rp.Body)
} else {
return &Result{rp.Header.Get(HEADER_REQUEST_ID),
rp.Header.Get(HEADER_ETAG_SERVER), rp.Body}, nil
}
}
func (c *Client) GetTeamAnalytics(teamId, name string) (*Result, *AppError) {
if r, err := c.DoApiGet("/admin/analytics/"+teamId+"/"+name, "", ""); err != nil {
return nil, err

132
model/compliance.go Обычный файл
Просмотреть файл

@@ -0,0 +1,132 @@
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
import (
"encoding/json"
"io"
"strings"
)
const (
COMPLIANCE_STATUS_CREATED = "created"
COMPLIANCE_STATUS_RUNNING = "running"
COMPLIANCE_STATUS_FINISHED = "finished"
COMPLIANCE_STATUS_FAILED = "failed"
COMPLIANCE_STATUS_REMOVED = "removed"
COMPLIANCE_TYPE_DAILY = "daily"
COMPLIANCE_TYPE_ADHOC = "adhoc"
)
type Compliance struct {
Id string `json:"id"`
CreateAt int64 `json:"create_at"`
UserId string `json:"user_id"`
Status string `json:"status"`
Count int `json:"count"`
Desc string `json:"desc"`
Type string `json:"type"`
StartAt int64 `json:"start_at"`
EndAt int64 `json:"end_at"`
Keywords string `json:"keywords"`
Emails string `json:"emails"`
}
type Compliances []Compliance
func (o *Compliance) ToJson() string {
b, err := json.Marshal(o)
if err != nil {
return ""
} else {
return string(b)
}
}
func (me *Compliance) PreSave() {
if me.Id == "" {
me.Id = NewId()
}
if me.Status == "" {
me.Status = COMPLIANCE_STATUS_CREATED
}
me.Count = 0
me.Emails = strings.ToLower(me.Emails)
me.Keywords = strings.ToLower(me.Keywords)
me.CreateAt = GetMillis()
}
func (me *Compliance) JobName() string {
jobName := me.Type
if me.Type == COMPLIANCE_TYPE_DAILY {
jobName += "-" + me.Desc
}
jobName += "-" + me.Id
return jobName
}
func (me *Compliance) IsValid() *AppError {
if len(me.Id) != 26 {
return NewLocAppError("Compliance.IsValid", "model.compliance.is_valid.id.app_error", nil, "")
}
if me.CreateAt == 0 {
return NewLocAppError("Compliance.IsValid", "model.compliance.is_valid.create_at.app_error", nil, "")
}
if len(me.Desc) > 512 || len(me.Desc) == 0 {
return NewLocAppError("Compliance.IsValid", "model.compliance.is_valid.desc.app_error", nil, "")
}
if me.StartAt == 0 {
return NewLocAppError("Compliance.IsValid", "model.compliance.is_valid.start_at.app_error", nil, "")
}
if me.EndAt == 0 {
return NewLocAppError("Compliance.IsValid", "model.compliance.is_valid.end_at.app_error", nil, "")
}
if me.EndAt <= me.StartAt {
return NewLocAppError("Compliance.IsValid", "model.compliance.is_valid.start_end_at.app_error", nil, "")
}
return nil
}
func ComplianceFromJson(data io.Reader) *Compliance {
decoder := json.NewDecoder(data)
var o Compliance
err := decoder.Decode(&o)
if err == nil {
return &o
} else {
return nil
}
}
func (o Compliances) ToJson() string {
if b, err := json.Marshal(o); err != nil {
return "[]"
} else {
return string(b)
}
}
func CompliancesFromJson(data io.Reader) Compliances {
decoder := json.NewDecoder(data)
var o Compliances
err := decoder.Decode(&o)
if err == nil {
return o
} else {
return nil
}
}

104
model/compliance_post.go Обычный файл
Просмотреть файл

@@ -0,0 +1,104 @@
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
import (
"time"
)
type CompliancePost struct {
// From Team
TeamName string
TeamDisplayName string
// From Channel
ChannelName string
ChannelDisplayName string
// From User
UserUsername string
UserEmail string
UserNickname string
// From Post
PostId string
PostCreateAt int64
PostUpdateAt int64
PostDeleteAt int64
PostRootId string
PostParentId string
PostOriginalId string
PostMessage string
PostType string
PostProps string
PostHashtags string
PostFilenames string
}
func CompliancePostHeader() []string {
return []string{
"TeamName",
"TeamDisplayName",
"ChannelName",
"ChannelDisplayName",
"UserUsername",
"UserEmail",
"UserNickname",
"PostId",
"PostCreateAt",
"PostUpdateAt",
"PostDeleteAt",
"PostRootId",
"PostParentId",
"PostOriginalId",
"PostMessage",
"PostType",
"PostProps",
"PostHashtags",
"PostFilenames",
}
}
func (me *CompliancePost) Row() []string {
postDeleteAt := ""
if me.PostDeleteAt > 0 {
postDeleteAt = time.Unix(0, me.PostDeleteAt*int64(1000*1000)).Format(time.RFC3339)
}
postUpdateAt := ""
if me.PostUpdateAt != me.PostCreateAt {
postUpdateAt = time.Unix(0, me.PostUpdateAt*int64(1000*1000)).Format(time.RFC3339)
}
return []string{
me.TeamName,
me.TeamDisplayName,
me.ChannelName,
me.ChannelDisplayName,
me.UserUsername,
me.UserEmail,
me.UserNickname,
me.PostId,
time.Unix(0, me.PostCreateAt*int64(1000*1000)).Format(time.RFC3339),
postUpdateAt,
postDeleteAt,
me.PostRootId,
me.PostParentId,
me.PostOriginalId,
me.PostMessage,
me.PostType,
me.PostProps,
me.PostHashtags,
me.PostFilenames,
}
}

27
model/compliance_post_test.go Обычный файл
Просмотреть файл

@@ -0,0 +1,27 @@
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
import (
"testing"
)
func TestCompliancePostHeader(t *testing.T) {
if CompliancePostHeader()[0] != "TeamName" {
t.Fatal()
}
}
func TestCompliancePost(t *testing.T) {
o := CompliancePost{TeamName: "test", PostFilenames: "files", PostCreateAt: GetMillis()}
r := o.Row()
if r[0] != "test" {
t.Fatal()
}
if r[len(r)-1] != "files" {
t.Fatal()
}
}

19
model/compliance_test.go Обычный файл
Просмотреть файл

@@ -0,0 +1,19 @@
// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package model
import (
"strings"
"testing"
)
func TestCompliance(t *testing.T) {
o := Compliance{Desc: "test", CreateAt: GetMillis()}
json := o.ToJson()
result := ComplianceFromJson(strings.NewReader(json))
if o.Desc != result.Desc {
t.Fatal("JobName do not match")
}
}

Просмотреть файл

@@ -179,19 +179,26 @@ type LdapSettings struct {
QueryTimeout *int
}
type ComplianceSettings struct {
Enable *bool
Directory *string
EnableDaily *bool
}
type Config struct {
ServiceSettings ServiceSettings
TeamSettings TeamSettings
SqlSettings SqlSettings
LogSettings LogSettings
FileSettings FileSettings
EmailSettings EmailSettings
RateLimitSettings RateLimitSettings
PrivacySettings PrivacySettings
SupportSettings SupportSettings
GitLabSettings SSOSettings
GoogleSettings SSOSettings
LdapSettings LdapSettings
ServiceSettings ServiceSettings
TeamSettings TeamSettings
SqlSettings SqlSettings
LogSettings LogSettings
FileSettings FileSettings
EmailSettings EmailSettings
RateLimitSettings RateLimitSettings
PrivacySettings PrivacySettings
SupportSettings SupportSettings
GitLabSettings SSOSettings
GoogleSettings SSOSettings
LdapSettings LdapSettings
ComplianceSettings ComplianceSettings
}
func (o *Config) ToJson() string {
@@ -402,6 +409,21 @@ func (o *Config) SetDefaults() {
o.ServiceSettings.WebserverMode = new(string)
*o.ServiceSettings.WebserverMode = "regular"
}
if o.ComplianceSettings.Enable == nil {
o.ComplianceSettings.Enable = new(bool)
*o.ComplianceSettings.Enable = false
}
if o.ComplianceSettings.Directory == nil {
o.ComplianceSettings.Directory = new(string)
*o.ComplianceSettings.Directory = "./data/"
}
if o.ComplianceSettings.EnableDaily == nil {
o.ComplianceSettings.EnableDaily = new(bool)
*o.ComplianceSettings.EnableDaily = false
}
}
func (o *Config) IsValid() *AppError {

Просмотреть файл

@@ -32,9 +32,10 @@ type Customer struct {
}
type Features struct {
Users *int `json:"users"`
LDAP *bool `json:"ldap"`
GoogleSSO *bool `json:"google_sso"`
Users *int `json:"users"`
LDAP *bool `json:"ldap"`
GoogleSSO *bool `json:"google_sso"`
Compliance *bool `json:"compliance"`
}
func (f *Features) SetDefaults() {
@@ -52,6 +53,11 @@ func (f *Features) SetDefaults() {
f.GoogleSSO = new(bool)
*f.GoogleSSO = true
}
if f.Compliance == nil {
f.Compliance = new(bool)
*f.Compliance = true
}
}
func (l *License) IsExpired() bool {

Просмотреть файл

@@ -9,10 +9,11 @@ import (
)
const (
SYSTEM_DIAGNOSTIC_ID = "DiagnosticId"
SYSTEM_RAN_UNIT_TESTS = "RanUnitTests"
SYSTEM_LAST_SECURITY_TIME = "LastSecurityTime"
SYSTEM_ACTIVE_LICENSE_ID = "ActiveLicenseId"
SYSTEM_DIAGNOSTIC_ID = "DiagnosticId"
SYSTEM_RAN_UNIT_TESTS = "RanUnitTests"
SYSTEM_LAST_SECURITY_TIME = "LastSecurityTime"
SYSTEM_ACTIVE_LICENSE_ID = "ActiveLicenseId"
SYSTEM_LAST_COMPLIANCE_TIME = "LastComplianceTime"
)
type System struct {