[MM-56035] Added missing unit tests for user endpoints (#28237)
Automatic Merge
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
c7aec8c5c5
Коммит
48c42fc588
@@ -4,9 +4,11 @@
|
||||
package api4
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"image/png"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -8075,3 +8077,579 @@ func TestLoginWithDesktopToken(t *testing.T) {
|
||||
assert.Len(t, sessions, 0)
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetUsersByNames(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
t.Run("Get users by valid usernames", func(t *testing.T) {
|
||||
users, _, err := th.Client.GetUsersByUsernames(context.Background(), []string{th.BasicUser.Username, th.BasicUser2.Username})
|
||||
require.NoError(t, err)
|
||||
require.ElementsMatch(t, []string{th.BasicUser.Username, th.BasicUser2.Username}, []string{users[0].Username, users[1].Username})
|
||||
|
||||
for _, user := range users {
|
||||
CheckUserSanitization(t, user)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Get users by invalid usernames", func(t *testing.T) {
|
||||
users, resp, err := th.Client.GetUsersByUsernames(context.Background(), []string{"invalid1", "invalid2"})
|
||||
require.NoError(t, err)
|
||||
CheckOKStatus(t, resp)
|
||||
require.Empty(t, users)
|
||||
})
|
||||
|
||||
t.Run("Get users by mixed valid and invalid usernames", func(t *testing.T) {
|
||||
users, resp, err := th.Client.GetUsersByUsernames(context.Background(), []string{th.BasicUser.Username, "invalid"})
|
||||
require.NoError(t, err)
|
||||
CheckOKStatus(t, resp)
|
||||
require.ElementsMatch(t, []string{th.BasicUser.Username}, []string{users[0].Username})
|
||||
|
||||
for _, user := range users {
|
||||
CheckUserSanitization(t, user)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Get users by empty slice", func(t *testing.T) {
|
||||
_, resp, err := th.Client.GetUsersByUsernames(context.Background(), []string{})
|
||||
require.Error(t, err)
|
||||
CheckBadRequestStatus(t, resp)
|
||||
})
|
||||
|
||||
t.Run("Get users without permissions", func(t *testing.T) {
|
||||
th.Client.Logout(context.Background())
|
||||
defer th.LoginBasic() // Ensure the client is logged back in after the test
|
||||
|
||||
_, resp, err := th.Client.GetUsersByUsernames(context.Background(), []string{th.BasicUser.Username})
|
||||
require.Error(t, err)
|
||||
CheckUnauthorizedStatus(t, resp)
|
||||
})
|
||||
|
||||
t.Run("Get users as system admin", func(t *testing.T) {
|
||||
users, resp, err := th.SystemAdminClient.GetUsersByUsernames(context.Background(), []string{th.BasicUser.Username})
|
||||
require.NoError(t, err)
|
||||
CheckOKStatus(t, resp)
|
||||
require.ElementsMatch(t, []string{th.BasicUser.Username}, []string{users[0].Username})
|
||||
require.Len(t, users, 1)
|
||||
CheckUserSanitization(t, users[0])
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetFilteredUsersStats(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
t.Run("Get filtered users stats as system admin", func(t *testing.T) {
|
||||
// Create an additional user and link them to the team
|
||||
regularUser := th.CreateUser()
|
||||
th.LinkUserToTeam(regularUser, th.BasicTeam)
|
||||
|
||||
options := &model.UserCountOptions{
|
||||
TeamId: th.BasicTeam.Id,
|
||||
IncludeDeleted: false,
|
||||
IncludeBotAccounts: false,
|
||||
IncludeRemoteUsers: false,
|
||||
}
|
||||
|
||||
stats, resp, err := th.SystemAdminClient.GetFilteredUsersStats(context.Background(), options)
|
||||
require.NoError(t, err)
|
||||
CheckOKStatus(t, resp)
|
||||
require.NotNil(t, stats)
|
||||
|
||||
// We expect 4 users: BasicUser, BasicUser2, the newly created regularUser, and possibly a system admin or other pre-existing user
|
||||
expectedCount := int64(4)
|
||||
assert.Equal(t, expectedCount, stats.TotalUsersCount, "Unexpected user count")
|
||||
})
|
||||
|
||||
t.Run("Get filtered users stats as regular user", func(t *testing.T) {
|
||||
options := &model.UserCountOptions{
|
||||
TeamId: th.BasicTeam.Id,
|
||||
IncludeDeleted: false,
|
||||
IncludeBotAccounts: false,
|
||||
IncludeRemoteUsers: false,
|
||||
}
|
||||
_, resp, err := th.Client.GetFilteredUsersStats(context.Background(), options)
|
||||
require.Error(t, err)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
})
|
||||
|
||||
t.Run("Get filtered users stats with invalid team id", func(t *testing.T) {
|
||||
options := &model.UserCountOptions{
|
||||
TeamId: "invalid_team_id",
|
||||
IncludeDeleted: false,
|
||||
IncludeBotAccounts: false,
|
||||
IncludeRemoteUsers: false,
|
||||
}
|
||||
stats, resp, err := th.SystemAdminClient.GetFilteredUsersStats(context.Background(), options)
|
||||
require.NoError(t, err)
|
||||
CheckOKStatus(t, resp)
|
||||
require.NotNil(t, stats)
|
||||
// The server seems to return stats even with an invalid team ID
|
||||
// We should check that the returned stats make sense in this context
|
||||
require.Equal(t, int64(0), stats.TotalUsersCount, "Expected 0 users for an invalid team ID")
|
||||
})
|
||||
|
||||
t.Run("Get filtered users stats with roles", func(t *testing.T) {
|
||||
options := model.UserCountOptions{
|
||||
TeamId: th.BasicTeam.Id,
|
||||
IncludeDeleted: false,
|
||||
IncludeBotAccounts: false,
|
||||
IncludeRemoteUsers: false,
|
||||
Roles: []string{model.SystemUserRoleId},
|
||||
}
|
||||
|
||||
// Get the actual count from the server
|
||||
actualCount, err := th.App.Srv().Store().User().Count(options)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Get the count from the client
|
||||
stats, resp, err := th.SystemAdminClient.GetFilteredUsersStats(context.Background(), &options)
|
||||
require.NoError(t, err)
|
||||
CheckOKStatus(t, resp)
|
||||
require.NotNil(t, stats)
|
||||
|
||||
// Compare the counts
|
||||
assert.Equal(t, actualCount, stats.TotalUsersCount, "Client-side count should match server-side count")
|
||||
assert.True(t, stats.TotalUsersCount > 0, "There should be at least one user")
|
||||
})
|
||||
|
||||
t.Run("Get filtered users stats with team roles", func(t *testing.T) {
|
||||
options := model.UserCountOptions{
|
||||
TeamId: th.BasicTeam.Id,
|
||||
IncludeDeleted: false,
|
||||
IncludeBotAccounts: false,
|
||||
IncludeRemoteUsers: false,
|
||||
TeamRoles: []string{model.TeamUserRoleId},
|
||||
}
|
||||
|
||||
// Get the actual count from the server
|
||||
actualCount, err := th.App.Srv().Store().User().Count(options)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Get the count from the client
|
||||
stats, resp, err := th.SystemAdminClient.GetFilteredUsersStats(context.Background(), &options)
|
||||
require.NoError(t, err)
|
||||
CheckOKStatus(t, resp)
|
||||
require.NotNil(t, stats)
|
||||
|
||||
// Compare the counts
|
||||
assert.Equal(t, actualCount, stats.TotalUsersCount, "Client-side count should match server-side count")
|
||||
assert.True(t, stats.TotalUsersCount > 0, "There should be at least one user with the specified team role")
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetDefaultProfileImage(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
t.Run("Get default profile image for existing user", func(t *testing.T) {
|
||||
user := th.BasicUser
|
||||
|
||||
img, resp, err := th.Client.GetDefaultProfileImage(context.Background(), user.Id)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, img)
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
|
||||
// Check if the image is a valid PNG
|
||||
_, err = png.Decode(bytes.NewReader(img))
|
||||
require.NoError(t, err, "Image should be a valid PNG")
|
||||
})
|
||||
|
||||
t.Run("Get default profile image for non-existent user", func(t *testing.T) {
|
||||
nonExistentUserId := model.NewId()
|
||||
|
||||
_, resp, err := th.Client.GetDefaultProfileImage(context.Background(), nonExistentUserId)
|
||||
require.Error(t, err)
|
||||
CheckNotFoundStatus(t, resp)
|
||||
})
|
||||
|
||||
t.Run("Get default profile image without proper permissions", func(t *testing.T) {
|
||||
user := th.CreateUser()
|
||||
|
||||
th.Client.Logout(context.Background())
|
||||
_, resp, err := th.Client.GetDefaultProfileImage(context.Background(), user.Id)
|
||||
require.Error(t, err)
|
||||
CheckUnauthorizedStatus(t, resp)
|
||||
})
|
||||
|
||||
t.Run("Get default profile image as system admin", func(t *testing.T) {
|
||||
user := th.CreateUser()
|
||||
|
||||
img, resp, err := th.SystemAdminClient.GetDefaultProfileImage(context.Background(), user.Id)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, img)
|
||||
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
_, err = png.Decode(bytes.NewReader(img))
|
||||
require.NoError(t, err, "Image should be a valid PNG")
|
||||
})
|
||||
|
||||
t.Run("Consistent default image for the same user", func(t *testing.T) {
|
||||
user := th.CreateUser()
|
||||
|
||||
// Login as the newly created user
|
||||
th.Client.Login(context.Background(), user.Email, user.Password)
|
||||
|
||||
img1, resp, err := th.Client.GetDefaultProfileImage(context.Background(), user.Id)
|
||||
require.NoError(t, err)
|
||||
CheckOKStatus(t, resp)
|
||||
|
||||
img2, resp, err := th.Client.GetDefaultProfileImage(context.Background(), user.Id)
|
||||
require.NoError(t, err)
|
||||
CheckOKStatus(t, resp)
|
||||
|
||||
require.Equal(t, img1, img2, "Default profile images should be consistent for the same user")
|
||||
|
||||
// Logout after the test
|
||||
th.Client.Logout(context.Background())
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetUserThread(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
client := th.Client
|
||||
user := th.BasicUser
|
||||
team := th.BasicTeam
|
||||
|
||||
t.Run("get thread for user", func(t *testing.T) {
|
||||
// Create a post
|
||||
post, _, err := client.CreatePost(context.Background(), &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
Message: "Root message",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create a reply to ensure thread membership
|
||||
_, _, err = client.CreatePost(context.Background(), &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
RootId: post.Id,
|
||||
Message: "Reply",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Get the thread
|
||||
thread, resp, err := client.GetUserThread(context.Background(), user.Id, team.Id, post.Id, false)
|
||||
require.NoError(t, err)
|
||||
CheckOKStatus(t, resp)
|
||||
require.NotNil(t, thread)
|
||||
require.Equal(t, post.Id, thread.PostId)
|
||||
require.Equal(t, int64(1), thread.ReplyCount)
|
||||
})
|
||||
|
||||
t.Run("get thread for user with extended info", func(t *testing.T) {
|
||||
post, _, err := client.CreatePost(context.Background(), &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
Message: "Root message for extended info",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create a reply to ensure thread membership
|
||||
_, _, err = client.CreatePost(context.Background(), &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
RootId: post.Id,
|
||||
Message: "Reply for extended info",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
thread, resp, err := client.GetUserThread(context.Background(), user.Id, team.Id, post.Id, true)
|
||||
require.NoError(t, err)
|
||||
CheckOKStatus(t, resp)
|
||||
require.NotNil(t, thread)
|
||||
require.NotNil(t, thread.Participants)
|
||||
})
|
||||
|
||||
t.Run("get thread for non-existent post", func(t *testing.T) {
|
||||
_, resp, err := client.GetUserThread(context.Background(), user.Id, team.Id, model.NewId(), false)
|
||||
require.Error(t, err)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
})
|
||||
|
||||
t.Run("get thread without permissions", func(t *testing.T) {
|
||||
post, _, err := client.CreatePost(context.Background(), &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
Message: "Root message for permissions test",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Log out
|
||||
client.Logout(context.Background())
|
||||
|
||||
_, resp, err := client.GetUserThread(context.Background(), user.Id, team.Id, post.Id, false)
|
||||
require.Error(t, err)
|
||||
CheckUnauthorizedStatus(t, resp)
|
||||
})
|
||||
|
||||
t.Run("get thread for different user", func(t *testing.T) {
|
||||
// Log back in
|
||||
client.Login(context.Background(), user.Email, user.Password)
|
||||
|
||||
post, _, err := client.CreatePost(context.Background(), &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
Message: "Root message for different user test",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Try to get thread for a different user
|
||||
_, resp, err := client.GetUserThread(context.Background(), th.BasicUser2.Id, team.Id, post.Id, false)
|
||||
require.Error(t, err)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
})
|
||||
|
||||
t.Run("get thread as system admin", func(t *testing.T) {
|
||||
// Create a post as the system admin
|
||||
post, _, err := th.SystemAdminClient.CreatePost(context.Background(), &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
Message: "Root message for system admin test",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Have the basic user reply to the post to create a thread membership
|
||||
_, _, err = client.CreatePost(context.Background(), &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
RootId: post.Id,
|
||||
Message: "Reply from basic user",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Now try to get the thread as the system admin
|
||||
thread, resp, err := th.SystemAdminClient.GetUserThread(context.Background(), user.Id, team.Id, post.Id, false)
|
||||
require.NoError(t, err)
|
||||
CheckOKStatus(t, resp)
|
||||
require.NotNil(t, thread)
|
||||
require.Equal(t, post.Id, thread.PostId)
|
||||
require.Equal(t, int64(1), thread.ReplyCount)
|
||||
})
|
||||
}
|
||||
|
||||
func TestUpdateReadStateThreadByUser(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
client := th.Client
|
||||
user := th.BasicUser
|
||||
team := th.BasicTeam
|
||||
|
||||
t.Run("update read state for thread", func(t *testing.T) {
|
||||
// Create a post
|
||||
post, _, err := client.CreatePost(context.Background(), &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
Message: "Root message",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create a reply to ensure thread membership
|
||||
_, _, err = client.CreatePost(context.Background(), &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
RootId: post.Id,
|
||||
Message: "Reply",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Update read state for the thread
|
||||
timestamp := model.GetMillis()
|
||||
thread, resp, err := client.UpdateThreadReadForUser(context.Background(), user.Id, team.Id, post.Id, timestamp)
|
||||
require.NoError(t, err)
|
||||
CheckOKStatus(t, resp)
|
||||
require.NotNil(t, thread)
|
||||
require.Equal(t, post.Id, thread.PostId)
|
||||
require.Equal(t, timestamp, thread.LastViewedAt)
|
||||
})
|
||||
|
||||
t.Run("update read state for non-existent thread", func(t *testing.T) {
|
||||
// Attempting to update read state for a non-existent thread results in a Forbidden error
|
||||
// This is likely because the user doesn't have permission to access the non-existent thread
|
||||
nonExistentPostId := model.NewId()
|
||||
_, resp, err := client.UpdateThreadReadForUser(context.Background(), user.Id, team.Id, nonExistentPostId, model.GetMillis())
|
||||
require.Error(t, err)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
})
|
||||
t.Run("update read state without permissions", func(t *testing.T) {
|
||||
// Create a post
|
||||
post, _, err := client.CreatePost(context.Background(), &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
Message: "Root message for permissions test",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Log out
|
||||
client.Logout(context.Background())
|
||||
|
||||
_, resp, err := client.UpdateThreadReadForUser(context.Background(), user.Id, team.Id, post.Id, model.GetMillis())
|
||||
require.Error(t, err)
|
||||
CheckUnauthorizedStatus(t, resp)
|
||||
})
|
||||
|
||||
t.Run("update read state for different user", func(t *testing.T) {
|
||||
// Log back in
|
||||
client.Login(context.Background(), user.Email, user.Password)
|
||||
|
||||
post, _, err := client.CreatePost(context.Background(), &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
Message: "Root message for different user test",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Try to update read state for a different user
|
||||
_, resp, err := client.UpdateThreadReadForUser(context.Background(), th.BasicUser2.Id, team.Id, post.Id, model.GetMillis())
|
||||
require.Error(t, err)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
})
|
||||
}
|
||||
|
||||
func TestSetUnreadThreadByPostId(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
client := th.Client
|
||||
user := th.BasicUser
|
||||
team := th.BasicTeam
|
||||
|
||||
t.Run("set unread state for thread", func(t *testing.T) {
|
||||
// Create a post
|
||||
post, _, err := client.CreatePost(context.Background(), &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
Message: "Root message",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create a reply to ensure thread membership
|
||||
reply, _, err := client.CreatePost(context.Background(), &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
RootId: post.Id,
|
||||
Message: "Reply",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Set unread state for the thread
|
||||
thread, resp, err := client.SetThreadUnreadByPostId(context.Background(), user.Id, team.Id, post.Id, reply.Id)
|
||||
require.NoError(t, err)
|
||||
CheckOKStatus(t, resp)
|
||||
require.NotNil(t, thread)
|
||||
require.Equal(t, post.Id, thread.PostId)
|
||||
|
||||
// Check that LastReplyAt matches the creation time of the last reply
|
||||
require.Equal(t, reply.CreateAt, thread.LastReplyAt, "LastReplyAt should match the creation time of the last reply")
|
||||
|
||||
// Check if the thread is marked as unread
|
||||
require.True(t, thread.UnreadReplies > 0, "Thread should have unread replies")
|
||||
|
||||
// Check that UnreadMentions is 0 (assuming the reply didn't mention the user)
|
||||
require.Equal(t, int64(0), thread.UnreadMentions, "UnreadMentions should be 0 if the reply didn't mention the user")
|
||||
})
|
||||
|
||||
t.Run("set unread state for non-existent thread", func(t *testing.T) {
|
||||
nonExistentPostId := model.NewId()
|
||||
_, resp, err := client.SetThreadUnreadByPostId(context.Background(), user.Id, team.Id, nonExistentPostId, nonExistentPostId)
|
||||
require.Error(t, err)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
})
|
||||
|
||||
t.Run("set unread state without permissions", func(t *testing.T) {
|
||||
// Create a post
|
||||
post, _, err := client.CreatePost(context.Background(), &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
Message: "Root message for permissions test",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Log out
|
||||
client.Logout(context.Background())
|
||||
|
||||
_, resp, err := client.SetThreadUnreadByPostId(context.Background(), user.Id, team.Id, post.Id, post.Id)
|
||||
require.Error(t, err)
|
||||
CheckUnauthorizedStatus(t, resp)
|
||||
})
|
||||
|
||||
t.Run("set unread state for different user", func(t *testing.T) {
|
||||
// Log back in
|
||||
client.Login(context.Background(), user.Email, user.Password)
|
||||
|
||||
post, _, err := client.CreatePost(context.Background(), &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
Message: "Root message for different user test",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Try to set unread state for a different user
|
||||
_, resp, err := client.SetThreadUnreadByPostId(context.Background(), th.BasicUser2.Id, team.Id, post.Id, post.Id)
|
||||
require.Error(t, err)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
})
|
||||
|
||||
t.Run("set unread state as system admin", func(t *testing.T) {
|
||||
post, _, err := th.SystemAdminClient.CreatePost(context.Background(), &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
Message: "Root message for system admin test",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
reply, _, err := th.SystemAdminClient.CreatePost(context.Background(), &model.Post{
|
||||
ChannelId: th.BasicChannel.Id,
|
||||
RootId: post.Id,
|
||||
Message: "Reply for system admin test",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
thread, resp, err := th.SystemAdminClient.SetThreadUnreadByPostId(context.Background(), user.Id, team.Id, post.Id, reply.Id)
|
||||
require.NoError(t, err)
|
||||
CheckOKStatus(t, resp)
|
||||
require.NotNil(t, thread)
|
||||
require.Equal(t, post.Id, thread.PostId)
|
||||
|
||||
// Check that LastReplyAt is a recent timestamp
|
||||
require.Greater(t, thread.LastReplyAt, int64(0))
|
||||
require.LessOrEqual(t, thread.LastReplyAt, model.GetMillis())
|
||||
|
||||
// Check if the thread is marked as unread
|
||||
require.True(t, thread.UnreadReplies > 0, "Thread should have unread replies")
|
||||
|
||||
require.InDelta(t, model.GetMillis(), thread.LastReplyAt, float64(5000), "LastReplyAt should be within 5 seconds of current time")
|
||||
})
|
||||
}
|
||||
|
||||
func TestRevokeAllSessionsForUser(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
user := th.BasicUser
|
||||
user2 := th.BasicUser2 // Additional user for permission testing
|
||||
|
||||
// Create multiple sessions for the primary user
|
||||
client1 := th.CreateClient()
|
||||
_, _, err := client1.Login(context.Background(), user.Email, user.Password)
|
||||
require.NoError(t, err)
|
||||
|
||||
client2 := th.CreateClient()
|
||||
_, _, err = client2.Login(context.Background(), user.Email, user.Password)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create a session for the second user (non-admin)
|
||||
nonAdminClient := th.CreateClient()
|
||||
_, _, err = nonAdminClient.Login(context.Background(), user2.Email, user2.Password)
|
||||
require.NoError(t, err)
|
||||
|
||||
th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
|
||||
resp, err := th.SystemAdminClient.RevokeAllSessions(context.Background(), user.Id)
|
||||
require.NoError(t, err)
|
||||
CheckOKStatus(t, resp)
|
||||
// Use SystemAdminClient to verify that all sessions are revoked
|
||||
sessions, _, err := th.SystemAdminClient.GetSessions(context.Background(), user.Id, "")
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, sessions, "All sessions should be revoked")
|
||||
}, "Revoke all sessions as admin and local")
|
||||
|
||||
th.TestForSystemAdminAndLocal(t, func(t *testing.T, client *model.Client4) {
|
||||
fakeUserId := "invalid_user_id"
|
||||
resp, err := client.RevokeAllSessions(context.Background(), fakeUserId)
|
||||
require.Error(t, err)
|
||||
CheckNotFoundStatus(t, resp)
|
||||
}, "Revoke all sessions for non-existent user")
|
||||
|
||||
t.Run("Revoke all sessions without permissions", func(t *testing.T) {
|
||||
// Attempt to revoke sessions of the primary user using a non-admin client
|
||||
resp, err := nonAdminClient.RevokeAllSessions(context.Background(), user.Id)
|
||||
require.Error(t, err)
|
||||
CheckForbiddenStatus(t, resp)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -9205,3 +9205,35 @@ func (c *Client4) SubmitClientMetrics(ctx context.Context, report *PerformanceRe
|
||||
|
||||
return BuildResponse(res), nil
|
||||
}
|
||||
|
||||
func (c *Client4) GetFilteredUsersStats(ctx context.Context, options *UserCountOptions) (*UsersStats, *Response, error) {
|
||||
v := url.Values{}
|
||||
v.Set("in_team", options.TeamId)
|
||||
v.Set("in_channel", options.ChannelId)
|
||||
v.Set("include_deleted", strconv.FormatBool(options.IncludeDeleted))
|
||||
v.Set("include_bots", strconv.FormatBool(options.IncludeBotAccounts))
|
||||
v.Set("include_remote_users", strconv.FormatBool(options.IncludeRemoteUsers))
|
||||
|
||||
if len(options.Roles) > 0 {
|
||||
v.Set("roles", strings.Join(options.Roles, ","))
|
||||
}
|
||||
if len(options.ChannelRoles) > 0 {
|
||||
v.Set("channel_roles", strings.Join(options.ChannelRoles, ","))
|
||||
}
|
||||
if len(options.TeamRoles) > 0 {
|
||||
v.Set("team_roles", strings.Join(options.TeamRoles, ","))
|
||||
}
|
||||
|
||||
query := v.Encode()
|
||||
r, err := c.DoAPIGet(ctx, c.usersRoute()+"/stats/filtered?"+query, "")
|
||||
if err != nil {
|
||||
return nil, BuildResponse(r), err
|
||||
}
|
||||
defer closeBody(r)
|
||||
|
||||
var stats UsersStats
|
||||
if err := json.NewDecoder(r.Body).Decode(&stats); err != nil {
|
||||
return nil, nil, NewAppError("GetFilteredUsersStats", "api.unmarshal_error", nil, "", http.StatusInternalServerError).Wrap(err)
|
||||
}
|
||||
return &stats, BuildResponse(r), nil
|
||||
}
|
||||
|
||||
Ссылка в новой задаче
Block a user