Implement endpoint for APIv4: GET /users/{user_id}/audits (#5472)
Этот коммит содержится в:
коммит произвёл
George Goldberg
родитель
7068307a1c
Коммит
5c19d9be7f
95
api4/user.go
95
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
|
||||
}
|
||||
c.RequireUserId()
|
||||
if c.Err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !app.SessionHasPermissionToUser(c.Session, c.Params.UserId) {
|
||||
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
||||
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()
|
||||
}
|
||||
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
|
||||
}
|
||||
w.Write([]byte(model.SessionsToJson(sessions)))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func revokeSession(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
c.RequireUserId()
|
||||
if c.Err != nil {
|
||||
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 !app.SessionHasPermissionToUser(c.Session, c.Params.UserId) {
|
||||
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
||||
return
|
||||
}
|
||||
|
||||
props := model.MapFromJson(r.Body)
|
||||
sessionId := props["session_id"]
|
||||
props := model.MapFromJson(r.Body)
|
||||
sessionId := props["session_id"]
|
||||
|
||||
if sessionId == "" {
|
||||
c.SetInvalidParam("session_id")
|
||||
}
|
||||
if sessionId == "" {
|
||||
c.SetInvalidParam("session_id")
|
||||
}
|
||||
|
||||
if err := app.RevokeSessionById(sessionId); err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
if err := app.RevokeSessionById(sessionId); err != nil {
|
||||
c.Err = err
|
||||
return
|
||||
}
|
||||
|
||||
ReturnStatusOK(w)
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
10
app/audit.go
10
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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
Ссылка в новой задаче
Block a user