summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api4/user.go111
-rw-r--r--api4/user_test.go27
-rw-r--r--app/audit.go10
-rw-r--r--model/client4.go11
-rw-r--r--store/sql_audit_store.go6
-rw-r--r--store/sql_audit_store_test.go9
-rw-r--r--store/store.go2
7 files changed, 121 insertions, 55 deletions
diff --git a/api4/user.go b/api4/user.go
index 5337cedf0..4c40ef4b4 100644
--- a/api4/user.go
+++ b/api4/user.go
@@ -36,6 +36,7 @@ func InitUser() {
BaseRoutes.User.Handle("/sessions", ApiSessionRequired(getSessions)).Methods("GET")
BaseRoutes.User.Handle("/sessions/revoke", ApiSessionRequired(revokeSession)).Methods("POST")
+ BaseRoutes.User.Handle("/audits", ApiSessionRequired(getAudits)).Methods("GET")
}
@@ -481,51 +482,71 @@ func Logout(c *Context, w http.ResponseWriter, r *http.Request) {
}
func getSessions(c *Context, w http.ResponseWriter, r *http.Request) {
- c.RequireUserId()
- if c.Err != nil {
- return
- }
-
- if !app.SessionHasPermissionToUser(c.Session, c.Params.UserId) {
- c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
- return
- }
-
- if sessions, err := app.GetSessions(c.Params.UserId); err != nil {
- c.Err = err
- return
- } else {
- for _, session := range sessions {
- session.Sanitize()
- }
-
- w.Write([]byte(model.SessionsToJson(sessions)))
- return
- }
+ c.RequireUserId()
+ if c.Err != nil {
+ return
+ }
+
+ if !app.SessionHasPermissionToUser(c.Session, c.Params.UserId) {
+ c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
+ return
+ }
+
+ if sessions, err := app.GetSessions(c.Params.UserId); err != nil {
+ c.Err = err
+ return
+ } else {
+ for _, session := range sessions {
+ session.Sanitize()
+ }
+
+ w.Write([]byte(model.SessionsToJson(sessions)))
+ return
+ }
}
func revokeSession(c *Context, w http.ResponseWriter, r *http.Request) {
- c.RequireUserId()
- if c.Err != nil {
- return
- }
-
- if !app.SessionHasPermissionToUser(c.Session, c.Params.UserId) {
- c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
- return
- }
-
- props := model.MapFromJson(r.Body)
- sessionId := props["session_id"]
-
- if sessionId == "" {
- c.SetInvalidParam("session_id")
- }
-
- if err := app.RevokeSessionById(sessionId); err != nil {
- c.Err = err
- return
- }
-
- ReturnStatusOK(w)
-} \ No newline at end of file
+ c.RequireUserId()
+ if c.Err != nil {
+ return
+ }
+
+ if !app.SessionHasPermissionToUser(c.Session, c.Params.UserId) {
+ c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
+ return
+ }
+
+ props := model.MapFromJson(r.Body)
+ sessionId := props["session_id"]
+
+ if sessionId == "" {
+ c.SetInvalidParam("session_id")
+ }
+
+ if err := app.RevokeSessionById(sessionId); err != nil {
+ c.Err = err
+ return
+ }
+
+ ReturnStatusOK(w)
+}
+
+func getAudits(c *Context, w http.ResponseWriter, r *http.Request) {
+ c.RequireUserId()
+ if c.Err != nil {
+ return
+ }
+
+ if !app.SessionHasPermissionToUser(c.Session, c.Params.UserId) {
+ c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
+ return
+ }
+
+ if audits, err := app.GetAuditsPage(c.Params.UserId, c.Params.Page, c.Params.PerPage); err != nil {
+ c.Err = err
+ return
+ } else {
+ w.Write([]byte(audits.ToJson()))
+ return
+ }
+}
diff --git a/api4/user_test.go b/api4/user_test.go
index 5fe497d90..07b9745c6 100644
--- a/api4/user_test.go
+++ b/api4/user_test.go
@@ -811,7 +811,7 @@ func TestGetSessions(t *testing.T) {
user := th.BasicUser
Client.Login(user.Email, user.Password)
-
+
sessions, resp := Client.GetSessions(user.Id, "")
for _, session := range sessions {
if session.UserId != user.Id {
@@ -899,3 +899,28 @@ func TestRevokeSessions(t *testing.T) {
CheckNoError(t, resp)
}
+
+func TestGetAudits(t *testing.T) {
+ th := Setup().InitBasic().InitSystemAdmin()
+ defer TearDown()
+ Client := th.Client
+ user := th.BasicUser
+
+ audits, resp := Client.GetAudits(user.Id, 0, 100, "")
+ for _, audit := range audits {
+ if audit.UserId != user.Id {
+ t.Fatal("user id does not match audit user id")
+ }
+ }
+ CheckNoError(t, resp)
+
+ _, resp = Client.GetAudits(th.BasicUser2.Id, 0, 100, "")
+ CheckForbiddenStatus(t, resp)
+
+ Client.Logout()
+ _, resp = Client.GetAudits(user.Id, 0, 100, "")
+ CheckUnauthorizedStatus(t, resp)
+
+ _, resp = th.SystemAdminClient.GetAudits(user.Id, 0, 100, "")
+ CheckNoError(t, resp)
+}
diff --git a/app/audit.go b/app/audit.go
index 6978e9bc2..6b7439d43 100644
--- a/app/audit.go
+++ b/app/audit.go
@@ -8,7 +8,15 @@ import (
)
func GetAudits(userId string, limit int) (model.Audits, *model.AppError) {
- if result := <-Srv.Store.Audit().Get(userId, limit); result.Err != nil {
+ if result := <-Srv.Store.Audit().Get(userId, 0, limit); result.Err != nil {
+ return nil, result.Err
+ } else {
+ return result.Data.(model.Audits), nil
+ }
+}
+
+func GetAuditsPage(userId string, page int, perPage int) (model.Audits, *model.AppError) {
+ if result := <-Srv.Store.Audit().Get(userId, page*perPage, perPage); result.Err != nil {
return nil, result.Err
} else {
return result.Data.(model.Audits), nil
diff --git a/model/client4.go b/model/client4.go
index f4447b769..8f9bb82f5 100644
--- a/model/client4.go
+++ b/model/client4.go
@@ -459,6 +459,17 @@ func (c *Client4) RevokeSession(userId, sessionId string) (bool, *Response) {
}
}
+// GetAudits returns a list of audit based on the provided user id string.
+func (c *Client4) GetAudits(userId string, page int, perPage int, etag string) (Audits, *Response) {
+ query := fmt.Sprintf("?page=%v&per_page=%v", page, perPage)
+ if r, err := c.DoApiGet(c.GetUserRoute(userId)+"/audits"+query, etag); err != nil {
+ return nil, &Response{StatusCode: r.StatusCode, Error: err}
+ } else {
+ defer closeBody(r)
+ return AuditsFromJson(r.Body), BuildResponse(r)
+ }
+}
+
// Team Section
// CreateTeam creates a team in the system based on the provided team struct.
diff --git a/store/sql_audit_store.go b/store/sql_audit_store.go
index 7e8fa74e4..693b46bb9 100644
--- a/store/sql_audit_store.go
+++ b/store/sql_audit_store.go
@@ -54,7 +54,7 @@ func (s SqlAuditStore) Save(audit *model.Audit) StoreChannel {
return storeChannel
}
-func (s SqlAuditStore) Get(user_id string, limit int) StoreChannel {
+func (s SqlAuditStore) Get(user_id string, offset int, limit int) StoreChannel {
storeChannel := make(StoreChannel, 1)
@@ -75,10 +75,10 @@ func (s SqlAuditStore) Get(user_id string, limit int) StoreChannel {
query += " WHERE UserId = :user_id"
}
- query += " ORDER BY CreateAt DESC LIMIT :limit"
+ query += " ORDER BY CreateAt DESC LIMIT :limit OFFSET :offset"
var audits model.Audits
- if _, err := s.GetReplica().Select(&audits, query, map[string]interface{}{"user_id": user_id, "limit": limit}); err != nil {
+ if _, err := s.GetReplica().Select(&audits, query, map[string]interface{}{"user_id": user_id, "limit": limit, "offset": offset}); err != nil {
result.Err = model.NewLocAppError("SqlAuditStore.Get", "store.sql_audit.get.finding.app_error", nil, "user_id="+user_id)
} else {
result.Data = audits
diff --git a/store/sql_audit_store_test.go b/store/sql_audit_store_test.go
index 841b79627..fcdada4e5 100644
--- a/store/sql_audit_store_test.go
+++ b/store/sql_audit_store_test.go
@@ -4,9 +4,10 @@
package store
import (
- "github.com/mattermost/platform/model"
"testing"
"time"
+
+ "github.com/mattermost/platform/model"
)
func TestSqlAuditStore(t *testing.T) {
@@ -25,7 +26,7 @@ func TestSqlAuditStore(t *testing.T) {
time.Sleep(100 * time.Millisecond)
- c := store.Audit().Get(audit.UserId, 100)
+ c := store.Audit().Get(audit.UserId, 0, 100)
result := <-c
audits := result.Data.(model.Audits)
@@ -37,7 +38,7 @@ func TestSqlAuditStore(t *testing.T) {
t.Fatal("Failed to save property for extra info")
}
- c = store.Audit().Get("missing", 100)
+ c = store.Audit().Get("missing", 0, 100)
result = <-c
audits = result.Data.(model.Audits)
@@ -45,7 +46,7 @@ func TestSqlAuditStore(t *testing.T) {
t.Fatal("Should have returned empty because user_id is missing")
}
- c = store.Audit().Get("", 100)
+ c = store.Audit().Get("", 0, 100)
result = <-c
audits = result.Data.(model.Audits)
diff --git a/store/store.go b/store/store.go
index 1a43767dd..6c78a235d 100644
--- a/store/store.go
+++ b/store/store.go
@@ -208,7 +208,7 @@ type SessionStore interface {
type AuditStore interface {
Save(audit *model.Audit) StoreChannel
- Get(user_id string, limit int) StoreChannel
+ Get(user_id string, offset int, limit int) StoreChannel
PermanentDeleteByUser(userId string) StoreChannel
}