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", ApiSessionRequired(getSessions)).Methods("GET")
|
||||||
BaseRoutes.User.Handle("/sessions/revoke", ApiSessionRequired(revokeSession)).Methods("POST")
|
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) {
|
func getSessions(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
c.RequireUserId()
|
c.RequireUserId()
|
||||||
if c.Err != nil {
|
if c.Err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !app.SessionHasPermissionToUser(c.Session, c.Params.UserId) {
|
if !app.SessionHasPermissionToUser(c.Session, c.Params.UserId) {
|
||||||
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if sessions, err := app.GetSessions(c.Params.UserId); err != nil {
|
if sessions, err := app.GetSessions(c.Params.UserId); err != nil {
|
||||||
c.Err = err
|
c.Err = err
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
for _, session := range sessions {
|
for _, session := range sessions {
|
||||||
session.Sanitize()
|
session.Sanitize()
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Write([]byte(model.SessionsToJson(sessions)))
|
w.Write([]byte(model.SessionsToJson(sessions)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func revokeSession(c *Context, w http.ResponseWriter, r *http.Request) {
|
func revokeSession(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
c.RequireUserId()
|
c.RequireUserId()
|
||||||
if c.Err != nil {
|
if c.Err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !app.SessionHasPermissionToUser(c.Session, c.Params.UserId) {
|
if !app.SessionHasPermissionToUser(c.Session, c.Params.UserId) {
|
||||||
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
c.SetPermissionError(model.PERMISSION_EDIT_OTHER_USERS)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
props := model.MapFromJson(r.Body)
|
props := model.MapFromJson(r.Body)
|
||||||
sessionId := props["session_id"]
|
sessionId := props["session_id"]
|
||||||
|
|
||||||
if sessionId == "" {
|
if sessionId == "" {
|
||||||
c.SetInvalidParam("session_id")
|
c.SetInvalidParam("session_id")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := app.RevokeSessionById(sessionId); err != nil {
|
if err := app.RevokeSessionById(sessionId); err != nil {
|
||||||
c.Err = err
|
c.Err = err
|
||||||
return
|
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
|
user := th.BasicUser
|
||||||
|
|
||||||
Client.Login(user.Email, user.Password)
|
Client.Login(user.Email, user.Password)
|
||||||
|
|
||||||
sessions, resp := Client.GetSessions(user.Id, "")
|
sessions, resp := Client.GetSessions(user.Id, "")
|
||||||
for _, session := range sessions {
|
for _, session := range sessions {
|
||||||
if session.UserId != user.Id {
|
if session.UserId != user.Id {
|
||||||
@@ -899,3 +899,28 @@ func TestRevokeSessions(t *testing.T) {
|
|||||||
CheckNoError(t, resp)
|
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) {
|
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
|
return nil, result.Err
|
||||||
} else {
|
} else {
|
||||||
return result.Data.(model.Audits), nil
|
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
|
// Team Section
|
||||||
|
|
||||||
// CreateTeam creates a team in the system based on the provided team struct.
|
// 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
|
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)
|
storeChannel := make(StoreChannel, 1)
|
||||||
|
|
||||||
@@ -75,10 +75,10 @@ func (s SqlAuditStore) Get(user_id string, limit int) StoreChannel {
|
|||||||
query += " WHERE UserId = :user_id"
|
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
|
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)
|
result.Err = model.NewLocAppError("SqlAuditStore.Get", "store.sql_audit.get.finding.app_error", nil, "user_id="+user_id)
|
||||||
} else {
|
} else {
|
||||||
result.Data = audits
|
result.Data = audits
|
||||||
|
|||||||
@@ -4,9 +4,10 @@
|
|||||||
package store
|
package store
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/mattermost/platform/model"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/mattermost/platform/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSqlAuditStore(t *testing.T) {
|
func TestSqlAuditStore(t *testing.T) {
|
||||||
@@ -25,7 +26,7 @@ func TestSqlAuditStore(t *testing.T) {
|
|||||||
|
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
|
||||||
c := store.Audit().Get(audit.UserId, 100)
|
c := store.Audit().Get(audit.UserId, 0, 100)
|
||||||
result := <-c
|
result := <-c
|
||||||
audits := result.Data.(model.Audits)
|
audits := result.Data.(model.Audits)
|
||||||
|
|
||||||
@@ -37,7 +38,7 @@ func TestSqlAuditStore(t *testing.T) {
|
|||||||
t.Fatal("Failed to save property for extra info")
|
t.Fatal("Failed to save property for extra info")
|
||||||
}
|
}
|
||||||
|
|
||||||
c = store.Audit().Get("missing", 100)
|
c = store.Audit().Get("missing", 0, 100)
|
||||||
result = <-c
|
result = <-c
|
||||||
audits = result.Data.(model.Audits)
|
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")
|
t.Fatal("Should have returned empty because user_id is missing")
|
||||||
}
|
}
|
||||||
|
|
||||||
c = store.Audit().Get("", 100)
|
c = store.Audit().Get("", 0, 100)
|
||||||
result = <-c
|
result = <-c
|
||||||
audits = result.Data.(model.Audits)
|
audits = result.Data.(model.Audits)
|
||||||
|
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ type SessionStore interface {
|
|||||||
|
|
||||||
type AuditStore interface {
|
type AuditStore interface {
|
||||||
Save(audit *model.Audit) StoreChannel
|
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
|
PermanentDeleteByUser(userId string) StoreChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user