Improve test suite (#628)
Signed-off-by: Thomas Miceli <tho.miceli@gmail.com>
هذا الالتزام موجود في:
@@ -1,448 +0,0 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/thomiceli/opengist/internal/db"
|
||||
)
|
||||
|
||||
func TestAccessTokensCRUD(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
// Register and login
|
||||
user1 := db.UserDTO{Username: "thomas", Password: "thomas"}
|
||||
register(t, s, user1)
|
||||
|
||||
// Access tokens page requires login
|
||||
s.sessionCookie = ""
|
||||
err := s.Request("GET", "/settings/access-tokens", nil, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
login(t, s, user1)
|
||||
|
||||
// Access tokens page
|
||||
err = s.Request("GET", "/settings/access-tokens", nil, 200)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create a token with read permission
|
||||
tokenDTO := db.AccessTokenDTO{
|
||||
Name: "test-token",
|
||||
ScopeGist: db.ReadPermission,
|
||||
}
|
||||
err = s.Request("POST", "/settings/access-tokens", tokenDTO, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify token was created in database
|
||||
tokens, err := db.GetAccessTokensByUserID(1)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, tokens, 1)
|
||||
require.Equal(t, "test-token", tokens[0].Name)
|
||||
require.Equal(t, uint(db.ReadPermission), tokens[0].ScopeGist)
|
||||
require.Equal(t, int64(0), tokens[0].ExpiresAt)
|
||||
|
||||
// Create another token with expiration
|
||||
tomorrow := time.Now().AddDate(0, 0, 1).Format("2006-01-02")
|
||||
tokenDTO2 := db.AccessTokenDTO{
|
||||
Name: "expiring-token",
|
||||
ScopeGist: db.ReadWritePermission,
|
||||
ExpiresAt: tomorrow,
|
||||
}
|
||||
err = s.Request("POST", "/settings/access-tokens", tokenDTO2, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
tokens, err = db.GetAccessTokensByUserID(1)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, tokens, 2)
|
||||
|
||||
// Delete the first token
|
||||
err = s.Request("DELETE", "/settings/access-tokens/1", nil, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
tokens, err = db.GetAccessTokensByUserID(1)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, tokens, 1)
|
||||
require.Equal(t, "expiring-token", tokens[0].Name)
|
||||
}
|
||||
|
||||
func TestAccessTokenPrivateGistAccess(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
// Register user and create a private gist
|
||||
user1 := db.UserDTO{Username: "thomas", Password: "thomas"}
|
||||
register(t, s, user1)
|
||||
|
||||
gist1 := db.GistDTO{
|
||||
Title: "private-gist",
|
||||
Description: "my private gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: db.PrivateVisibility,
|
||||
},
|
||||
Name: []string{"secret.txt"},
|
||||
Content: []string{"secret content"},
|
||||
}
|
||||
err := s.Request("POST", "/", gist1, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist1db, err := db.GetGistByID("1")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create access token with read permission
|
||||
token := &db.AccessToken{
|
||||
Name: "read-token",
|
||||
UserID: 1,
|
||||
ScopeGist: db.ReadPermission,
|
||||
}
|
||||
plainToken, err := token.GenerateToken()
|
||||
require.NoError(t, err)
|
||||
err = token.Create()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Clear session - simulate unauthenticated request
|
||||
s.sessionCookie = ""
|
||||
|
||||
// Without token, private gist should return 404
|
||||
err = s.Request("GET", "/thomas/"+gist1db.Uuid, nil, 404)
|
||||
require.NoError(t, err)
|
||||
|
||||
// With valid token, private gist should be accessible
|
||||
headers := map[string]string{"Authorization": "Token " + plainToken}
|
||||
err = s.RequestWithHeaders("GET", "/thomas/"+gist1db.Uuid, nil, 200, headers)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Raw content should also be accessible with token
|
||||
err = s.RequestWithHeaders("GET", "/thomas/"+gist1db.Uuid+"/raw/HEAD/secret.txt", nil, 200, headers)
|
||||
require.NoError(t, err)
|
||||
|
||||
// JSON endpoint should also be accessible with token
|
||||
err = s.RequestWithHeaders("GET", "/thomas/"+gist1db.Uuid+".json", nil, 200, headers)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Invalid token should not work
|
||||
invalidHeaders := map[string]string{"Authorization": "Token invalid_token"}
|
||||
err = s.RequestWithHeaders("GET", "/thomas/"+gist1db.Uuid, nil, 404, invalidHeaders)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestAccessTokenPermissions(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
// Register user and create a private gist
|
||||
user1 := db.UserDTO{Username: "thomas", Password: "thomas"}
|
||||
register(t, s, user1)
|
||||
|
||||
gist1 := db.GistDTO{
|
||||
Title: "private-gist",
|
||||
Description: "my private gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: db.PrivateVisibility,
|
||||
},
|
||||
Name: []string{"file.txt"},
|
||||
Content: []string{"content"},
|
||||
}
|
||||
err := s.Request("POST", "/", gist1, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist1db, err := db.GetGistByID("1")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create token with NO permission
|
||||
noPermToken := &db.AccessToken{
|
||||
Name: "no-perm-token",
|
||||
UserID: 1,
|
||||
ScopeGist: db.NoPermission,
|
||||
}
|
||||
noPermPlain, err := noPermToken.GenerateToken()
|
||||
require.NoError(t, err)
|
||||
err = noPermToken.Create()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create token with READ permission
|
||||
readToken := &db.AccessToken{
|
||||
Name: "read-token",
|
||||
UserID: 1,
|
||||
ScopeGist: db.ReadPermission,
|
||||
}
|
||||
readPlain, err := readToken.GenerateToken()
|
||||
require.NoError(t, err)
|
||||
err = readToken.Create()
|
||||
require.NoError(t, err)
|
||||
|
||||
s.sessionCookie = ""
|
||||
|
||||
// No permission token should not grant access
|
||||
noPermHeaders := map[string]string{"Authorization": "Token " + noPermPlain}
|
||||
err = s.RequestWithHeaders("GET", "/thomas/"+gist1db.Uuid, nil, 404, noPermHeaders)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Read permission token should grant access
|
||||
readHeaders := map[string]string{"Authorization": "Token " + readPlain}
|
||||
err = s.RequestWithHeaders("GET", "/thomas/"+gist1db.Uuid, nil, 200, readHeaders)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestAccessTokenExpiration(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
// Register user and create a private gist
|
||||
user1 := db.UserDTO{Username: "thomas", Password: "thomas"}
|
||||
register(t, s, user1)
|
||||
|
||||
gist1 := db.GistDTO{
|
||||
Title: "private-gist",
|
||||
Description: "my private gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: db.PrivateVisibility,
|
||||
},
|
||||
Name: []string{"file.txt"},
|
||||
Content: []string{"content"},
|
||||
}
|
||||
err := s.Request("POST", "/", gist1, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist1db, err := db.GetGistByID("1")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create an expired token
|
||||
expiredToken := &db.AccessToken{
|
||||
Name: "expired-token",
|
||||
UserID: 1,
|
||||
ScopeGist: db.ReadPermission,
|
||||
ExpiresAt: time.Now().Add(-24 * time.Hour).Unix(), // Expired yesterday
|
||||
}
|
||||
expiredPlain, err := expiredToken.GenerateToken()
|
||||
require.NoError(t, err)
|
||||
err = expiredToken.Create()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create a valid (non-expired) token
|
||||
validToken := &db.AccessToken{
|
||||
Name: "valid-token",
|
||||
UserID: 1,
|
||||
ScopeGist: db.ReadPermission,
|
||||
ExpiresAt: time.Now().Add(24 * time.Hour).Unix(), // Expires tomorrow
|
||||
}
|
||||
validPlain, err := validToken.GenerateToken()
|
||||
require.NoError(t, err)
|
||||
err = validToken.Create()
|
||||
require.NoError(t, err)
|
||||
|
||||
s.sessionCookie = ""
|
||||
|
||||
// Expired token should not grant access
|
||||
expiredHeaders := map[string]string{"Authorization": "Token " + expiredPlain}
|
||||
err = s.RequestWithHeaders("GET", "/thomas/"+gist1db.Uuid, nil, 404, expiredHeaders)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Valid token should grant access
|
||||
validHeaders := map[string]string{"Authorization": "Token " + validPlain}
|
||||
err = s.RequestWithHeaders("GET", "/thomas/"+gist1db.Uuid, nil, 200, validHeaders)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestAccessTokenWrongUser(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
// Register two users
|
||||
user1 := db.UserDTO{Username: "thomas", Password: "thomas"}
|
||||
register(t, s, user1)
|
||||
|
||||
// Create a private gist for user1
|
||||
gist1 := db.GistDTO{
|
||||
Title: "thomas-private-gist",
|
||||
Description: "thomas private gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: db.PrivateVisibility,
|
||||
},
|
||||
Name: []string{"file.txt"},
|
||||
Content: []string{"content"},
|
||||
}
|
||||
err := s.Request("POST", "/", gist1, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist1db, err := db.GetGistByID("1")
|
||||
require.NoError(t, err)
|
||||
|
||||
s.sessionCookie = ""
|
||||
user2 := db.UserDTO{Username: "kaguya", Password: "kaguya"}
|
||||
register(t, s, user2)
|
||||
|
||||
// Create token for user2
|
||||
user2Token := &db.AccessToken{
|
||||
Name: "kaguya-token",
|
||||
UserID: 2,
|
||||
ScopeGist: db.ReadPermission,
|
||||
}
|
||||
user2Plain, err := user2Token.GenerateToken()
|
||||
require.NoError(t, err)
|
||||
err = user2Token.Create()
|
||||
require.NoError(t, err)
|
||||
|
||||
s.sessionCookie = ""
|
||||
|
||||
// User2's token should NOT grant access to user1's private gist
|
||||
user2Headers := map[string]string{"Authorization": "Token " + user2Plain}
|
||||
err = s.RequestWithHeaders("GET", "/thomas/"+gist1db.Uuid, nil, 404, user2Headers)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create token for user1
|
||||
user1Token := &db.AccessToken{
|
||||
Name: "thomas-token",
|
||||
UserID: 1,
|
||||
ScopeGist: db.ReadPermission,
|
||||
}
|
||||
user1Plain, err := user1Token.GenerateToken()
|
||||
require.NoError(t, err)
|
||||
err = user1Token.Create()
|
||||
require.NoError(t, err)
|
||||
|
||||
// User1's token SHOULD grant access to user1's private gist
|
||||
user1Headers := map[string]string{"Authorization": "Token " + user1Plain}
|
||||
err = s.RequestWithHeaders("GET", "/thomas/"+gist1db.Uuid, nil, 200, user1Headers)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestAccessTokenLastUsedUpdate(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
// Register user and create a private gist
|
||||
user1 := db.UserDTO{Username: "thomas", Password: "thomas"}
|
||||
register(t, s, user1)
|
||||
|
||||
gist1 := db.GistDTO{
|
||||
Title: "private-gist",
|
||||
Description: "my private gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: db.PrivateVisibility,
|
||||
},
|
||||
Name: []string{"file.txt"},
|
||||
Content: []string{"content"},
|
||||
}
|
||||
err := s.Request("POST", "/", gist1, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist1db, err := db.GetGistByID("1")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create token
|
||||
token := &db.AccessToken{
|
||||
Name: "test-token",
|
||||
UserID: 1,
|
||||
ScopeGist: db.ReadPermission,
|
||||
}
|
||||
plainToken, err := token.GenerateToken()
|
||||
require.NoError(t, err)
|
||||
err = token.Create()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify LastUsedAt is 0 initially
|
||||
tokenFromDB, err := db.GetAccessTokenByID(token.ID)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(0), tokenFromDB.LastUsedAt)
|
||||
|
||||
s.sessionCookie = ""
|
||||
|
||||
// Use the token
|
||||
headers := map[string]string{"Authorization": "Token " + plainToken}
|
||||
err = s.RequestWithHeaders("GET", "/thomas/"+gist1db.Uuid, nil, 200, headers)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify LastUsedAt was updated
|
||||
tokenFromDB, err = db.GetAccessTokenByID(token.ID)
|
||||
require.NoError(t, err)
|
||||
require.NotEqual(t, int64(0), tokenFromDB.LastUsedAt)
|
||||
}
|
||||
|
||||
func TestAccessTokenWithRequireLogin(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
admin := db.UserDTO{Username: "thomas", Password: "thomas"}
|
||||
register(t, s, admin)
|
||||
|
||||
gist1 := db.GistDTO{
|
||||
Title: "private-gist",
|
||||
Description: "my private gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: db.PrivateVisibility,
|
||||
},
|
||||
Name: []string{"file.txt"},
|
||||
Content: []string{"content"},
|
||||
}
|
||||
err := s.Request("POST", "/", gist1, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist1db, err := db.GetGistByID("1")
|
||||
require.NoError(t, err)
|
||||
|
||||
gist2 := db.GistDTO{
|
||||
Title: "public-gist",
|
||||
Description: "my public gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: db.PublicVisibility,
|
||||
},
|
||||
Name: []string{"public.txt"},
|
||||
Content: []string{"public content"},
|
||||
}
|
||||
err = s.Request("POST", "/", gist2, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist2db, err := db.GetGistByID("2")
|
||||
require.NoError(t, err)
|
||||
|
||||
token := &db.AccessToken{
|
||||
Name: "read-token",
|
||||
UserID: 1,
|
||||
ScopeGist: db.ReadPermission,
|
||||
}
|
||||
plainToken, err := token.GenerateToken()
|
||||
require.NoError(t, err)
|
||||
err = token.Create()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = s.Request("PUT", "/admin-panel/set-config", settingSet{"require-login", "1"}, 200)
|
||||
require.NoError(t, err)
|
||||
|
||||
s.sessionCookie = ""
|
||||
|
||||
err = s.Request("GET", "/thomas/"+gist1db.Uuid, nil, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = s.Request("GET", "/thomas/"+gist2db.Uuid, nil, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
headers := map[string]string{"Authorization": "Token " + plainToken}
|
||||
err = s.RequestWithHeaders("GET", "/thomas/"+gist1db.Uuid, nil, 200, headers)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = s.RequestWithHeaders("GET", "/thomas/"+gist2db.Uuid, nil, 200, headers)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = s.RequestWithHeaders("GET", "/thomas/"+gist1db.Uuid+"/raw/HEAD/file.txt", nil, 200, headers)
|
||||
require.NoError(t, err)
|
||||
|
||||
invalidHeaders := map[string]string{"Authorization": "Token invalid_token"}
|
||||
err = s.RequestWithHeaders("GET", "/thomas/"+gist1db.Uuid, nil, 302, invalidHeaders)
|
||||
require.NoError(t, err)
|
||||
|
||||
noPermToken := &db.AccessToken{
|
||||
Name: "no-perm-token",
|
||||
UserID: 1,
|
||||
ScopeGist: db.NoPermission,
|
||||
}
|
||||
noPermPlain, err := noPermToken.GenerateToken()
|
||||
require.NoError(t, err)
|
||||
err = noPermToken.Create()
|
||||
require.NoError(t, err)
|
||||
|
||||
noPermHeaders := map[string]string{"Authorization": "Token " + noPermPlain}
|
||||
err = s.RequestWithHeaders("GET", "/thomas/"+gist1db.Uuid, nil, 302, noPermHeaders)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/thomiceli/opengist/internal/db"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAdminActions(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
urls := []string{
|
||||
"/admin-panel/sync-fs",
|
||||
"/admin-panel/sync-db",
|
||||
"/admin-panel/gc-repos",
|
||||
"/admin-panel/sync-previews",
|
||||
"/admin-panel/reset-hooks",
|
||||
"/admin-panel/index-gists",
|
||||
}
|
||||
|
||||
for _, url := range urls {
|
||||
err := s.Request("POST", url, nil, 404)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
user1 := db.UserDTO{Username: "admin", Password: "admin"}
|
||||
register(t, s, user1)
|
||||
login(t, s, user1)
|
||||
for _, url := range urls {
|
||||
err := s.Request("POST", url, nil, 302)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
user2 := db.UserDTO{Username: "nonadmin", Password: "nonadmin"}
|
||||
register(t, s, user2)
|
||||
login(t, s, user2)
|
||||
for _, url := range urls {
|
||||
err := s.Request("POST", url, nil, 404)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
@@ -1,260 +0,0 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/thomiceli/opengist/internal/config"
|
||||
"github.com/thomiceli/opengist/internal/db"
|
||||
"github.com/thomiceli/opengist/internal/git"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestAdminPages(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
urls := []string{
|
||||
"/admin-panel",
|
||||
"/admin-panel/users",
|
||||
"/admin-panel/gists",
|
||||
"/admin-panel/invitations",
|
||||
"/admin-panel/configuration",
|
||||
}
|
||||
|
||||
for _, url := range urls {
|
||||
err := s.Request("GET", url, nil, 404)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
user1 := db.UserDTO{Username: "admin", Password: "admin"}
|
||||
register(t, s, user1)
|
||||
login(t, s, user1)
|
||||
for _, url := range urls {
|
||||
err := s.Request("GET", url, nil, 200)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
user2 := db.UserDTO{Username: "nonadmin", Password: "nonadmin"}
|
||||
register(t, s, user2)
|
||||
login(t, s, user2)
|
||||
for _, url := range urls {
|
||||
err := s.Request("GET", url, nil, 404)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetConfig(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
settings := []string{
|
||||
db.SettingDisableSignup,
|
||||
db.SettingRequireLogin,
|
||||
db.SettingAllowGistsWithoutLogin,
|
||||
db.SettingDisableLoginForm,
|
||||
db.SettingDisableGravatar,
|
||||
}
|
||||
|
||||
user1 := db.UserDTO{Username: "admin", Password: "admin"}
|
||||
register(t, s, user1)
|
||||
login(t, s, user1)
|
||||
|
||||
for _, setting := range settings {
|
||||
val, err := db.GetSetting(setting)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "0", val)
|
||||
|
||||
err = s.Request("PUT", "/admin-panel/set-config", settingSet{setting, "1"}, 200)
|
||||
require.NoError(t, err)
|
||||
|
||||
val, err = db.GetSetting(setting)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "1", val)
|
||||
|
||||
err = s.Request("PUT", "/admin-panel/set-config", settingSet{setting, "0"}, 200)
|
||||
require.NoError(t, err)
|
||||
|
||||
val, err = db.GetSetting(setting)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "0", val)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPagination(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
user1 := db.UserDTO{Username: "admin", Password: "admin"}
|
||||
register(t, s, user1)
|
||||
for i := 0; i < 11; i++ {
|
||||
user := db.UserDTO{Username: "user" + strconv.Itoa(i), Password: "user" + strconv.Itoa(i)}
|
||||
register(t, s, user)
|
||||
}
|
||||
|
||||
login(t, s, user1)
|
||||
|
||||
err := s.Request("GET", "/admin-panel/users", nil, 200)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = s.Request("GET", "/admin-panel/users?page=2", nil, 200)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = s.Request("GET", "/admin-panel/users?page=3", nil, 404)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = s.Request("GET", "/admin-panel/users?page=0", nil, 200)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = s.Request("GET", "/admin-panel/users?page=-1", nil, 200)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = s.Request("GET", "/admin-panel/users?page=a", nil, 200)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestAdminUser(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
user1 := db.UserDTO{Username: "admin", Password: "admin"}
|
||||
user2 := db.UserDTO{Username: "nonadmin", Password: "nonadmin"}
|
||||
register(t, s, user1)
|
||||
register(t, s, user2)
|
||||
|
||||
login(t, s, user2)
|
||||
|
||||
gist1 := db.GistDTO{
|
||||
Title: "gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: 0,
|
||||
},
|
||||
Name: []string{"gist1.txt"},
|
||||
Content: []string{"yeah"},
|
||||
Topics: "",
|
||||
}
|
||||
err := s.Request("POST", "/", gist1, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = os.Stat(filepath.Join(config.GetHomeDir(), git.ReposDirectory, user2.Username))
|
||||
require.NoError(t, err)
|
||||
|
||||
count, err := db.CountAll(db.User{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(2), count)
|
||||
|
||||
login(t, s, user1)
|
||||
|
||||
err = s.Request("POST", "/admin-panel/users/2/delete", nil, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
count, err = db.CountAll(db.User{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(1), count)
|
||||
|
||||
_, err = os.Stat(filepath.Join(config.GetHomeDir(), git.ReposDirectory, user2.Username))
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestAdminGist(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
user1 := db.UserDTO{Username: "admin", Password: "admin"}
|
||||
register(t, s, user1)
|
||||
login(t, s, user1)
|
||||
|
||||
gist1 := db.GistDTO{
|
||||
Title: "gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: 0,
|
||||
},
|
||||
Name: []string{"gist1.txt"},
|
||||
Content: []string{"yeah"},
|
||||
Topics: "",
|
||||
}
|
||||
err := s.Request("POST", "/", gist1, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
count, err := db.CountAll(db.Gist{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(1), count)
|
||||
|
||||
gist1Db, err := db.GetGistByID("1")
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = os.Stat(filepath.Join(config.GetHomeDir(), git.ReposDirectory, user1.Username, gist1Db.Identifier()))
|
||||
require.NoError(t, err)
|
||||
|
||||
err = s.Request("POST", "/admin-panel/gists/1/delete", nil, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
count, err = db.CountAll(db.Gist{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(0), count)
|
||||
|
||||
_, err = os.Stat(filepath.Join(config.GetHomeDir(), git.ReposDirectory, user1.Username, gist1Db.Identifier()))
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestAdminInvitation(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
user1 := db.UserDTO{Username: "admin", Password: "admin"}
|
||||
register(t, s, user1)
|
||||
login(t, s, user1)
|
||||
|
||||
err := s.Request("POST", "/admin-panel/invitations", invitationAdmin{
|
||||
nbMax: "",
|
||||
expiredAtUnix: "",
|
||||
}, 302)
|
||||
require.NoError(t, err)
|
||||
invitation1, err := db.GetInvitationByID(1)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint(1), invitation1.ID)
|
||||
require.Equal(t, uint(0), invitation1.NbUsed)
|
||||
require.Equal(t, uint(10), invitation1.NbMax)
|
||||
require.InDelta(t, time.Now().Unix()+604800, invitation1.ExpiresAt, 10)
|
||||
|
||||
err = s.Request("POST", "/admin-panel/invitations", invitationAdmin{
|
||||
nbMax: "aa",
|
||||
expiredAtUnix: "1735722000",
|
||||
}, 302)
|
||||
require.NoError(t, err)
|
||||
invitation2, err := db.GetInvitationByID(2)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, invitation2, &db.Invitation{
|
||||
ID: 2,
|
||||
Code: invitation2.Code,
|
||||
ExpiresAt: time.Unix(1735722000, 0).Unix(),
|
||||
NbUsed: 0,
|
||||
NbMax: 10,
|
||||
})
|
||||
|
||||
err = s.Request("POST", "/admin-panel/invitations", invitationAdmin{
|
||||
nbMax: "20",
|
||||
expiredAtUnix: "1735722000",
|
||||
}, 302)
|
||||
require.NoError(t, err)
|
||||
invitation3, err := db.GetInvitationByID(3)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, invitation3, &db.Invitation{
|
||||
ID: 3,
|
||||
Code: invitation3.Code,
|
||||
ExpiresAt: time.Unix(1735722000, 0).Unix(),
|
||||
NbUsed: 0,
|
||||
NbMax: 20,
|
||||
})
|
||||
|
||||
count, err := db.CountAll(db.Invitation{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(3), count)
|
||||
|
||||
err = s.Request("POST", "/admin-panel/invitations/1/delete", nil, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
count, err = db.CountAll(db.Invitation{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(2), count)
|
||||
}
|
||||
@@ -1,414 +0,0 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/thomiceli/opengist/internal/config"
|
||||
"github.com/thomiceli/opengist/internal/db"
|
||||
)
|
||||
|
||||
func TestRegister(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
err := s.Request("GET", "/", nil, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = s.Request("GET", "/register", nil, 200)
|
||||
require.NoError(t, err)
|
||||
|
||||
user1 := db.UserDTO{Username: "thomas", Password: "thomas"}
|
||||
register(t, s, user1)
|
||||
|
||||
user1db, err := db.GetUserById(1)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, user1.Username, user1db.Username)
|
||||
require.True(t, user1db.IsAdmin)
|
||||
|
||||
err = s.Request("GET", "/", nil, 200)
|
||||
require.NoError(t, err)
|
||||
|
||||
s.sessionCookie = ""
|
||||
|
||||
user2 := db.UserDTO{Username: "thomas", Password: "azeaze"}
|
||||
err = s.Request("POST", "/register", user2, 200)
|
||||
require.Error(t, err)
|
||||
|
||||
user3 := db.UserDTO{Username: "kaguya", Password: "kaguya"}
|
||||
register(t, s, user3)
|
||||
|
||||
user3db, err := db.GetUserById(2)
|
||||
require.NoError(t, err)
|
||||
require.False(t, user3db.IsAdmin)
|
||||
|
||||
s.sessionCookie = ""
|
||||
|
||||
count, err := db.CountAll(db.User{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(2), count)
|
||||
}
|
||||
|
||||
func TestLogin(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
err := s.Request("GET", "/login", nil, 200)
|
||||
require.NoError(t, err)
|
||||
|
||||
user1 := db.UserDTO{Username: "thomas", Password: "thomas"}
|
||||
register(t, s, user1)
|
||||
|
||||
s.sessionCookie = ""
|
||||
|
||||
login(t, s, user1)
|
||||
require.NotEmpty(t, s.sessionCookie)
|
||||
|
||||
s.sessionCookie = ""
|
||||
|
||||
user2 := db.UserDTO{Username: "thomas", Password: "azeaze"}
|
||||
user3 := db.UserDTO{Username: "azeaze", Password: ""}
|
||||
|
||||
err = s.Request("POST", "/login", user2, 302)
|
||||
require.Empty(t, s.sessionCookie)
|
||||
require.Error(t, err)
|
||||
|
||||
err = s.Request("POST", "/login", user3, 302)
|
||||
require.Empty(t, s.sessionCookie)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func register(t *testing.T, s *TestServer, user db.UserDTO) {
|
||||
err := s.Request("POST", "/register", user, 302)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func login(t *testing.T, s *TestServer, user db.UserDTO) {
|
||||
err := s.Request("POST", "/login", user, 302)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestAnonymous(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
user := db.UserDTO{Username: "thomas", Password: "azeaze"}
|
||||
register(t, s, user)
|
||||
|
||||
err := s.Request("PUT", "/admin-panel/set-config", settingSet{"require-login", "1"}, 200)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist1 := db.GistDTO{
|
||||
Title: "gist1",
|
||||
Description: "my first gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: 0,
|
||||
},
|
||||
Name: []string{"gist1.txt", "gist2.txt", "gist3.txt"},
|
||||
Content: []string{"yeah", "yeah\ncool", "yeah\ncool gist actually"},
|
||||
Topics: "",
|
||||
}
|
||||
err = s.Request("POST", "/", gist1, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist1db, err := db.GetGistByID("1")
|
||||
require.NoError(t, err)
|
||||
|
||||
err = s.Request("GET", "/all", nil, 200)
|
||||
require.NoError(t, err)
|
||||
|
||||
cookie := s.sessionCookie
|
||||
s.sessionCookie = ""
|
||||
|
||||
err = s.Request("GET", "/all", nil, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Should redirect to login if RequireLogin
|
||||
err = s.Request("GET", "/"+gist1db.User.Username+"/"+gist1db.Uuid, nil, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
s.sessionCookie = cookie
|
||||
|
||||
err = s.Request("PUT", "/admin-panel/set-config", settingSet{"allow-gists-without-login", "1"}, 200)
|
||||
require.NoError(t, err)
|
||||
|
||||
s.sessionCookie = ""
|
||||
|
||||
// Should return results
|
||||
err = s.Request("GET", "/"+gist1db.User.Username+"/"+gist1db.Uuid, nil, 200)
|
||||
require.NoError(t, err)
|
||||
|
||||
}
|
||||
|
||||
func TestGitOperations(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
admin := db.UserDTO{Username: "thomas", Password: "thomas"}
|
||||
register(t, s, admin)
|
||||
s.sessionCookie = ""
|
||||
register(t, s, db.UserDTO{Username: "fujiwara", Password: "fujiwara"})
|
||||
s.sessionCookie = ""
|
||||
register(t, s, db.UserDTO{Username: "kaguya", Password: "kaguya"})
|
||||
|
||||
gist1 := db.GistDTO{
|
||||
Title: "kaguya-pub-gist",
|
||||
URL: "kaguya-pub-gist",
|
||||
Description: "kaguya's first gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: db.PublicVisibility,
|
||||
},
|
||||
Name: []string{"kaguya-file.txt"},
|
||||
Content: []string{
|
||||
"yeah",
|
||||
},
|
||||
Topics: "",
|
||||
}
|
||||
err := s.Request("POST", "/", gist1, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist2 := db.GistDTO{
|
||||
Title: "kaguya-unl-gist",
|
||||
URL: "kaguya-unl-gist",
|
||||
Description: "kaguya's second gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: db.UnlistedVisibility,
|
||||
},
|
||||
Name: []string{"kaguya-file.txt"},
|
||||
Content: []string{
|
||||
"cool",
|
||||
},
|
||||
Topics: "",
|
||||
}
|
||||
err = s.Request("POST", "/", gist2, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist3 := db.GistDTO{
|
||||
Title: "kaguya-priv-gist",
|
||||
URL: "kaguya-priv-gist",
|
||||
Description: "kaguya's second gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: db.PrivateVisibility,
|
||||
},
|
||||
Name: []string{"kaguya-file.txt"},
|
||||
Content: []string{
|
||||
"super",
|
||||
},
|
||||
Topics: "",
|
||||
}
|
||||
err = s.Request("POST", "/", gist3, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
tests := []struct {
|
||||
credentials string
|
||||
user string
|
||||
url string
|
||||
pushOptions string
|
||||
expectErrorClone bool
|
||||
expectErrorCheck bool
|
||||
expectErrorPush bool
|
||||
}{
|
||||
{":", "kaguya", "kaguya-pub-gist", "", false, false, true},
|
||||
{":", "kaguya", "kaguya-unl-gist", "", false, false, true},
|
||||
{":", "kaguya", "kaguya-priv-gist", "", true, true, true},
|
||||
{"kaguya:kaguya", "kaguya", "kaguya-pub-gist", "", false, false, false},
|
||||
{"kaguya:kaguya", "kaguya", "kaguya-unl-gist", "", false, false, false},
|
||||
{"kaguya:kaguya", "kaguya", "kaguya-priv-gist", "", false, false, false},
|
||||
{"fujiwara:fujiwara", "kaguya", "kaguya-pub-gist", "", false, false, true},
|
||||
{"fujiwara:fujiwara", "kaguya", "kaguya-unl-gist", "", false, false, true},
|
||||
{"fujiwara:fujiwara", "kaguya", "kaguya-priv-gist", "", true, true, true},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
gitCloneCheckPush(t, test.credentials, test.user, test.url, "kaguya-file.txt", test.pushOptions, test.expectErrorClone, test.expectErrorCheck, test.expectErrorPush)
|
||||
}
|
||||
|
||||
login(t, s, admin)
|
||||
err = s.Request("PUT", "/admin-panel/set-config", settingSet{"require-login", "1"}, 200)
|
||||
require.NoError(t, err)
|
||||
|
||||
testsRequireLogin := []struct {
|
||||
credentials string
|
||||
user string
|
||||
url string
|
||||
pushOptions string
|
||||
expectErrorClone bool
|
||||
expectErrorCheck bool
|
||||
expectErrorPush bool
|
||||
}{
|
||||
{":", "kaguya", "kaguya-pub-gist", "", true, true, true},
|
||||
{":", "kaguya", "kaguya-unl-gist", "", true, true, true},
|
||||
{":", "kaguya", "kaguya-priv-gist", "", true, true, true},
|
||||
{"kaguya:kaguya", "kaguya", "kaguya-pub-gist", "", false, false, false},
|
||||
{"kaguya:kaguya", "kaguya", "kaguya-unl-gist", "", false, false, false},
|
||||
{"kaguya:kaguya", "kaguya", "kaguya-priv-gist", "", false, false, false},
|
||||
{"fujiwara:fujiwara", "kaguya", "kaguya-pub-gist", "", false, false, true},
|
||||
{"fujiwara:fujiwara", "kaguya", "kaguya-unl-gist", "", false, false, true},
|
||||
{"fujiwara:fujiwara", "kaguya", "kaguya-priv-gist", "", true, true, true},
|
||||
}
|
||||
|
||||
for _, test := range testsRequireLogin {
|
||||
gitCloneCheckPush(t, test.credentials, test.user, test.url, "kaguya-file.txt", test.pushOptions, test.expectErrorClone, test.expectErrorCheck, test.expectErrorPush)
|
||||
}
|
||||
|
||||
login(t, s, admin)
|
||||
err = s.Request("PUT", "/admin-panel/set-config", settingSet{"allow-gists-without-login", "1"}, 200)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, test := range tests {
|
||||
gitCloneCheckPush(t, test.credentials, test.user, test.url, "kaguya-file.txt", test.pushOptions, test.expectErrorClone, test.expectErrorCheck, test.expectErrorPush)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGitInit(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
admin := db.UserDTO{Username: "thomas", Password: "thomas"}
|
||||
register(t, s, admin)
|
||||
s.sessionCookie = ""
|
||||
register(t, s, db.UserDTO{Username: "fujiwara", Password: "fujiwara"})
|
||||
s.sessionCookie = ""
|
||||
register(t, s, db.UserDTO{Username: "kaguya", Password: "kaguya"})
|
||||
|
||||
testsNewWithPush := []struct {
|
||||
credentials string
|
||||
user string
|
||||
url string
|
||||
pushOptions string
|
||||
expectErrorClone bool
|
||||
expectErrorCheck bool
|
||||
expectErrorPush bool
|
||||
}{
|
||||
{":", "kaguya", "gist1", "", true, true, true},
|
||||
{"kaguya:wrongpass", "kaguya", "gist2", "", true, true, true},
|
||||
{"fujiwara:fujiwara", "kaguya", "gist3", "", true, true, true},
|
||||
{"kaguya:kaguya", "kaguya", "gist4", "", false, false, false},
|
||||
{"kaguya:kaguya", "kaguya", "gist5/g", "", true, true, true},
|
||||
}
|
||||
|
||||
for _, test := range testsNewWithPush {
|
||||
gitInitPush(t, test.credentials, test.user, test.url, "newfile.txt", test.pushOptions, test.expectErrorPush)
|
||||
}
|
||||
|
||||
gist1db, err := db.GetGistByID("1")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "kaguya", gist1db.User.Username)
|
||||
|
||||
for _, test := range testsNewWithPush {
|
||||
gitCloneCheckPush(t, test.credentials, test.user, test.url, "newfile.txt", test.pushOptions, test.expectErrorClone, test.expectErrorCheck, test.expectErrorPush)
|
||||
}
|
||||
|
||||
count, err := db.CountAll(db.Gist{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(1), count)
|
||||
|
||||
testsNewWithInit := []struct {
|
||||
credentials string
|
||||
url string
|
||||
pushOptions string
|
||||
expectErrorPush bool
|
||||
}{
|
||||
{":", "init", "", true},
|
||||
{"fujiwara:wrongpass", "init", "", true},
|
||||
{"kaguya:kaguya", "init", "", false},
|
||||
{"fujiwara:fujiwara", "init", "", false},
|
||||
}
|
||||
|
||||
for _, test := range testsNewWithInit {
|
||||
gitInitPush(t, test.credentials, "kaguya", test.url, "newfile.txt", test.pushOptions, test.expectErrorPush)
|
||||
}
|
||||
|
||||
count, err = db.CountAll(db.Gist{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(3), count)
|
||||
|
||||
gist2db, err := db.GetGistByID("2")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "kaguya", gist2db.User.Username)
|
||||
|
||||
gist3db, err := db.GetGistByID("3")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "fujiwara", gist3db.User.Username)
|
||||
}
|
||||
|
||||
func clientGitClone(creds string, user string, url string) error {
|
||||
return exec.Command("git", "clone", "http://"+creds+"@localhost:6157/"+user+"/"+url, filepath.Join(config.GetHomeDir(), "tmp", url)).Run()
|
||||
}
|
||||
|
||||
func clientGitPush(url string, pushOptions string, file string) error {
|
||||
f, err := os.Create(filepath.Join(config.GetHomeDir(), "tmp", url, file))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, _ = f.WriteString("new file")
|
||||
_ = f.Close()
|
||||
|
||||
_ = exec.Command("git", "-C", filepath.Join(config.GetHomeDir(), "tmp", url), "add", file).Run()
|
||||
_ = exec.Command("git", "-C", filepath.Join(config.GetHomeDir(), "tmp", url), "commit", "-m", "new file").Run()
|
||||
if pushOptions != "" {
|
||||
err = exec.Command("git", "-C", filepath.Join(config.GetHomeDir(), "tmp", url), "push", pushOptions, "origin").Run()
|
||||
} else {
|
||||
err = exec.Command("git", "-C", filepath.Join(config.GetHomeDir(), "tmp", url), "push", "origin").Run()
|
||||
}
|
||||
_ = os.RemoveAll(filepath.Join(config.GetHomeDir(), "tmp", url))
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func clientGitInit(path string) error {
|
||||
return exec.Command("git", "init", "--initial-branch=master", filepath.Join(config.GetHomeDir(), "tmp", path)).Run()
|
||||
}
|
||||
|
||||
func clientGitSetRemote(path string, remoteName string, remoteUrl string) error {
|
||||
return exec.Command("git", "-C", filepath.Join(config.GetHomeDir(), "tmp", path), "remote", "add", remoteName, remoteUrl).Run()
|
||||
}
|
||||
|
||||
func clientCheckRepo(url string, file string) error {
|
||||
_, err := os.ReadFile(filepath.Join(config.GetHomeDir(), "tmp", url, file))
|
||||
return err
|
||||
}
|
||||
|
||||
func gitCloneCheckPush(t *testing.T, credentials, owner, url, filename, pushOptions string, expectErrorClone, expectErrorCheck, expectErrorPush bool) {
|
||||
log.Debug().Msgf("Testing %s %s %t %t %t", credentials, url, expectErrorClone, expectErrorCheck, expectErrorPush)
|
||||
err := clientGitClone(credentials, owner, url)
|
||||
if expectErrorClone {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
err = clientCheckRepo(url, filename)
|
||||
if expectErrorCheck {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
err = clientGitPush(url, pushOptions, filename)
|
||||
if expectErrorPush {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
|
||||
func gitInitPush(t *testing.T, credentials, owner, url, filename, pushOptions string, expectErrorPush bool) {
|
||||
log.Debug().Msgf("Testing %s %s %t", credentials, url, expectErrorPush)
|
||||
err := clientGitInit(url)
|
||||
require.NoError(t, err)
|
||||
if url == "init" {
|
||||
err = clientGitSetRemote(url, "origin", "http://"+credentials+"@localhost:6157/init/")
|
||||
} else {
|
||||
err = clientGitSetRemote(url, "origin", "http://"+credentials+"@localhost:6157/"+owner+"/"+url)
|
||||
}
|
||||
require.NoError(t, err)
|
||||
err = clientGitPush(url, pushOptions, filename)
|
||||
if expectErrorPush {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
}
|
||||
@@ -1,342 +0,0 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/thomiceli/opengist/internal/db"
|
||||
"github.com/thomiceli/opengist/internal/git"
|
||||
)
|
||||
|
||||
func TestGists(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
err := s.Request("GET", "/", nil, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
user1 := db.UserDTO{Username: "thomas", Password: "thomas"}
|
||||
register(t, s, user1)
|
||||
|
||||
err = s.Request("GET", "/all", nil, 200)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = s.Request("POST", "/", nil, 400)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist1 := db.GistDTO{
|
||||
Title: "gist1",
|
||||
Description: "my first gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: 0,
|
||||
},
|
||||
Name: []string{"gist1.txt", "gist2.txt", "gist3.txt"},
|
||||
Content: []string{"yeah", "yeah\ncool", "yeah\ncool gist actually"},
|
||||
Topics: "",
|
||||
}
|
||||
err = s.Request("POST", "/", gist1, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist1db, err := db.GetGistByID("1")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint(1), gist1db.ID)
|
||||
require.Equal(t, gist1.Title, gist1db.Title)
|
||||
require.Equal(t, gist1.Description, gist1db.Description)
|
||||
require.Regexp(t, "[a-f0-9]{32}", gist1db.Uuid)
|
||||
require.Equal(t, user1.Username, gist1db.User.Username)
|
||||
|
||||
err = s.Request("GET", "/"+gist1db.User.Username+"/"+gist1db.Uuid, nil, 200)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist1files, err := git.GetFilesOfRepository(gist1db.User.Username, gist1db.Uuid, "HEAD")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 3, len(gist1files))
|
||||
|
||||
gist1fileContent, _, err := git.GetFileContent(gist1db.User.Username, gist1db.Uuid, "HEAD", gist1.Name[0], false)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, gist1.Content[0], gist1fileContent)
|
||||
|
||||
gist2 := db.GistDTO{
|
||||
Title: "gist2",
|
||||
Description: "my second gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: 0,
|
||||
},
|
||||
Name: []string{"", "gist2.txt", "gist3.txt"},
|
||||
Content: []string{"", "yeah\ncool", "yeah\ncool gist actually"},
|
||||
Topics: "",
|
||||
}
|
||||
err = s.Request("POST", "/", gist2, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist3 := db.GistDTO{
|
||||
Title: "gist3",
|
||||
Description: "my third gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: 0,
|
||||
},
|
||||
Name: []string{""},
|
||||
Content: []string{"yeah"},
|
||||
Topics: "",
|
||||
}
|
||||
err = s.Request("POST", "/", gist3, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist3db, err := db.GetGistByID("3")
|
||||
require.NoError(t, err)
|
||||
|
||||
gist3files, err := git.GetFilesOfRepository(gist3db.User.Username, gist3db.Uuid, "HEAD")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "gistfile1.txt", gist3files[0])
|
||||
|
||||
err = s.Request("POST", "/"+gist1db.User.Username+"/"+gist1db.Uuid+"/edit", nil, 400)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist1.Name = []string{"gist1.txt"}
|
||||
gist1.Content = []string{"only want one gist"}
|
||||
|
||||
err = s.Request("POST", "/"+gist1db.User.Username+"/"+gist1db.Uuid+"/edit", gist1, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist1files, err = git.GetFilesOfRepository(gist1db.User.Username, gist1db.Uuid, "HEAD")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(gist1files))
|
||||
|
||||
err = s.Request("POST", "/"+gist1db.User.Username+"/"+gist1db.Uuid+"/delete", nil, 302)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestVisibility(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
user1 := db.UserDTO{Username: "thomas", Password: "thomas"}
|
||||
register(t, s, user1)
|
||||
|
||||
gist1 := db.GistDTO{
|
||||
Title: "gist1",
|
||||
Description: "my first gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: db.UnlistedVisibility,
|
||||
},
|
||||
Name: []string{""},
|
||||
Content: []string{"yeah"},
|
||||
Topics: "",
|
||||
}
|
||||
err := s.Request("POST", "/", gist1, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist1db, err := db.GetGistByID("1")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, db.UnlistedVisibility, gist1db.Private)
|
||||
|
||||
err = s.Request("POST", "/"+gist1db.User.Username+"/"+gist1db.Uuid+"/visibility", db.VisibilityDTO{Private: db.PrivateVisibility}, 302)
|
||||
require.NoError(t, err)
|
||||
gist1db, err = db.GetGistByID("1")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, db.PrivateVisibility, gist1db.Private)
|
||||
|
||||
err = s.Request("POST", "/"+gist1db.User.Username+"/"+gist1db.Uuid+"/visibility", db.VisibilityDTO{Private: db.PublicVisibility}, 302)
|
||||
require.NoError(t, err)
|
||||
gist1db, err = db.GetGistByID("1")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, db.PublicVisibility, gist1db.Private)
|
||||
|
||||
err = s.Request("POST", "/"+gist1db.User.Username+"/"+gist1db.Uuid+"/visibility", db.VisibilityDTO{Private: db.UnlistedVisibility}, 302)
|
||||
require.NoError(t, err)
|
||||
gist1db, err = db.GetGistByID("1")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, db.UnlistedVisibility, gist1db.Private)
|
||||
}
|
||||
|
||||
func TestLikeFork(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
user1 := db.UserDTO{Username: "thomas", Password: "thomas"}
|
||||
register(t, s, user1)
|
||||
|
||||
gist1 := db.GistDTO{
|
||||
Title: "gist1",
|
||||
Description: "my first gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: 1,
|
||||
},
|
||||
Name: []string{""},
|
||||
Content: []string{"yeah"},
|
||||
Topics: "",
|
||||
}
|
||||
err := s.Request("POST", "/", gist1, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
s.sessionCookie = ""
|
||||
|
||||
user2 := db.UserDTO{Username: "kaguya", Password: "kaguya"}
|
||||
register(t, s, user2)
|
||||
|
||||
gist1db, err := db.GetGistByID("1")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, gist1db.NbLikes)
|
||||
likeCount, err := db.CountAll(db.Like{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(0), likeCount)
|
||||
|
||||
err = s.Request("POST", "/"+gist1db.User.Username+"/"+gist1db.Uuid+"/like", nil, 302)
|
||||
require.NoError(t, err)
|
||||
gist1db, err = db.GetGistByID("1")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, gist1db.NbLikes)
|
||||
likeCount, err = db.CountAll(db.Like{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(1), likeCount)
|
||||
|
||||
err = s.Request("POST", "/"+gist1db.User.Username+"/"+gist1db.Uuid+"/like", nil, 302)
|
||||
require.NoError(t, err)
|
||||
gist1db, err = db.GetGistByID("1")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, gist1db.NbLikes)
|
||||
likeCount, err = db.CountAll(db.Like{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(0), likeCount)
|
||||
|
||||
err = s.Request("POST", "/"+gist1db.User.Username+"/"+gist1db.Uuid+"/fork", nil, 302)
|
||||
require.NoError(t, err)
|
||||
gist2db, err := db.GetGistByID("2")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, gist1db.Title, gist2db.Title)
|
||||
require.Equal(t, gist1db.Description, gist2db.Description)
|
||||
require.Equal(t, gist1db.Private, gist2db.Private)
|
||||
require.Equal(t, user2.Username, gist2db.User.Username)
|
||||
}
|
||||
|
||||
func TestCustomUrl(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
user1 := db.UserDTO{Username: "thomas", Password: "thomas"}
|
||||
register(t, s, user1)
|
||||
|
||||
gist1 := db.GistDTO{
|
||||
Title: "gist1",
|
||||
URL: "my-gist",
|
||||
Description: "my first gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: 0,
|
||||
},
|
||||
Name: []string{"gist1.txt", "gist2.txt", "gist3.txt"},
|
||||
Content: []string{"yeah", "yeah\ncool", "yeah\ncool gist actually"},
|
||||
Topics: "",
|
||||
}
|
||||
err := s.Request("POST", "/", gist1, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist1db, err := db.GetGistByID("1")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint(1), gist1db.ID)
|
||||
require.Equal(t, gist1.Title, gist1db.Title)
|
||||
require.Equal(t, gist1.Description, gist1db.Description)
|
||||
require.Regexp(t, "[a-f0-9]{32}", gist1db.Uuid)
|
||||
require.Equal(t, gist1.URL, gist1db.URL)
|
||||
require.Equal(t, user1.Username, gist1db.User.Username)
|
||||
|
||||
gist1dbUuid, err := db.GetGist(user1.Username, gist1db.Uuid)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, gist1db, gist1dbUuid)
|
||||
|
||||
gist1dbUrl, err := db.GetGist(user1.Username, gist1.URL)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, gist1db, gist1dbUrl)
|
||||
|
||||
require.Equal(t, gist1.URL, gist1db.Identifier())
|
||||
|
||||
gist2 := db.GistDTO{
|
||||
Title: "gist2",
|
||||
Description: "my second gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: 0,
|
||||
},
|
||||
Name: []string{"gist1.txt", "gist2.txt", "gist3.txt"},
|
||||
Content: []string{"yeah", "yeah\ncool", "yeah\ncool gist actually"},
|
||||
Topics: "",
|
||||
}
|
||||
err = s.Request("POST", "/", gist2, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist2db, err := db.GetGistByID("2")
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, gist2db.Uuid, gist2db.Identifier())
|
||||
require.NotEqual(t, gist2db.URL, gist2db.Identifier())
|
||||
}
|
||||
|
||||
func TestTopics(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
user1 := db.UserDTO{Username: "thomas", Password: "thomas"}
|
||||
register(t, s, user1)
|
||||
|
||||
gist1 := db.GistDTO{
|
||||
Title: "gist1",
|
||||
URL: "my-gist",
|
||||
Description: "my first gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: 0,
|
||||
},
|
||||
Name: []string{"gist1.txt", "gist2.txt", "gist3.txt"},
|
||||
Content: []string{"yeah", "yeah\ncool", "yeah\ncool gist actually"},
|
||||
Topics: "topic1 topic2 topic3",
|
||||
}
|
||||
err := s.Request("POST", "/", gist1, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist1db, err := db.GetGistByID("1")
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, []db.GistTopic{
|
||||
{GistID: 1, Topic: "topic1"},
|
||||
{GistID: 1, Topic: "topic2"},
|
||||
{GistID: 1, Topic: "topic3"},
|
||||
}, gist1db.Topics)
|
||||
|
||||
gist2 := db.GistDTO{
|
||||
Title: "gist2",
|
||||
URL: "my-gist",
|
||||
Description: "my second gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: 0,
|
||||
},
|
||||
Name: []string{"gist1.txt", "gist2.txt", "gist3.txt"},
|
||||
Content: []string{"yeah", "yeah\ncool", "yeah\ncool gist actually"},
|
||||
Topics: "topic1 topic2 topic3 topic2 topic4 topic1",
|
||||
}
|
||||
err = s.Request("POST", "/", gist2, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist2db, err := db.GetGistByID("2")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []db.GistTopic{
|
||||
{GistID: 2, Topic: "topic1"},
|
||||
{GistID: 2, Topic: "topic2"},
|
||||
{GistID: 2, Topic: "topic3"},
|
||||
{GistID: 2, Topic: "topic4"},
|
||||
}, gist2db.Topics)
|
||||
|
||||
gist3 := db.GistDTO{
|
||||
Title: "gist3",
|
||||
URL: "my-gist",
|
||||
Description: "my third gist",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: 0,
|
||||
},
|
||||
Name: []string{"gist1.txt", "gist2.txt", "gist3.txt"},
|
||||
Content: []string{"yeah", "yeah\ncool", "yeah\ncool gist actually"},
|
||||
Topics: "topic1 topic2 topic3 topic4 topic5 topic6 topic7 topic8 topic9 topic10 topic11",
|
||||
}
|
||||
err = s.Request("POST", "/", gist3, 400)
|
||||
require.NoError(t, err)
|
||||
|
||||
gist3.Topics = "topictoolongggggggggggggggggggggggggggggggggggggggg"
|
||||
err = s.Request("POST", "/", gist3, 400)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http/httptest"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/thomiceli/opengist/internal/db"
|
||||
)
|
||||
|
||||
var (
|
||||
SSHKey = db.SSHKeyDTO{
|
||||
Title: "Test SSH Key",
|
||||
Content: `ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSUGPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XAt3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/EnmZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbxNrRFi9wrf+M7Q== admin@admin.local`,
|
||||
}
|
||||
AdminUser = db.UserDTO{
|
||||
Username: "admin",
|
||||
Password: "admin",
|
||||
}
|
||||
|
||||
SimpleGist = db.GistDTO{
|
||||
Title: "Simple Test Gist",
|
||||
Description: "A simple gist for testing",
|
||||
VisibilityDTO: db.VisibilityDTO{
|
||||
Private: 0,
|
||||
},
|
||||
Name: []string{"file1.txt"},
|
||||
Content: []string{"This is the content of file1"},
|
||||
Topics: "",
|
||||
}
|
||||
)
|
||||
|
||||
// TestMetrics tests the metrics endpoint functionality of the application.
|
||||
// It verifies that the metrics endpoint correctly reports counts for:
|
||||
// - Total number of users
|
||||
// - Total number of gists
|
||||
// - Total number of SSH keys
|
||||
//
|
||||
// The test follows these steps:
|
||||
// 1. Sets up test environment
|
||||
// 2. Registers and logs in an admin user
|
||||
// 3. Creates a gist and adds an SSH key
|
||||
// 4. Creates a metrics server and queries the /metrics endpoint
|
||||
// 5. Verifies the reported metrics match expected values
|
||||
func TestMetrics(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
register(t, s, AdminUser)
|
||||
login(t, s, AdminUser)
|
||||
|
||||
err := s.Request("GET", "/all", nil, 200)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = s.Request("POST", "/", SimpleGist, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = s.Request("POST", "/settings/ssh-keys", SSHKey, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create a metrics server and query it
|
||||
metricsServer := NewTestMetricsServer()
|
||||
|
||||
req := httptest.NewRequest("GET", "/metrics", nil)
|
||||
w := httptest.NewRecorder()
|
||||
metricsServer.ServeHTTP(w, req)
|
||||
|
||||
require.Equal(t, 200, w.Code)
|
||||
|
||||
body, err := io.ReadAll(w.Body)
|
||||
require.NoError(t, err)
|
||||
|
||||
lines := strings.Split(string(body), "\n")
|
||||
var usersTotal float64
|
||||
var gistsTotal float64
|
||||
var sshKeysTotal float64
|
||||
|
||||
for _, line := range lines {
|
||||
if strings.HasPrefix(line, "opengist_users_total") {
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) == 2 {
|
||||
usersTotal, err = strconv.ParseFloat(parts[1], 64)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
} else if strings.HasPrefix(line, "opengist_gists_total") {
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) == 2 {
|
||||
gistsTotal, err = strconv.ParseFloat(parts[1], 64)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
} else if strings.HasPrefix(line, "opengist_ssh_keys_total") {
|
||||
parts := strings.Fields(line)
|
||||
if len(parts) == 2 {
|
||||
sshKeysTotal, err = strconv.ParseFloat(parts[1], 64)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert.Equal(t, 1.0, usersTotal, "opengist_users_total should be 1")
|
||||
assert.Equal(t, 1.0, gistsTotal, "opengist_gists_total should be 1")
|
||||
assert.Equal(t, 1.0, sshKeysTotal, "opengist_ssh_keys_total should be 1")
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@@ -10,80 +8,74 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/gorilla/schema"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/thomiceli/opengist/internal/config"
|
||||
"github.com/thomiceli/opengist/internal/db"
|
||||
"github.com/thomiceli/opengist/internal/git"
|
||||
"github.com/thomiceli/opengist/internal/index"
|
||||
"github.com/thomiceli/opengist/internal/web/context"
|
||||
"github.com/thomiceli/opengist/internal/web/handlers/metrics"
|
||||
"github.com/thomiceli/opengist/internal/web/server"
|
||||
)
|
||||
|
||||
var databaseType string
|
||||
var formEncoder *schema.Encoder
|
||||
|
||||
type TestServer struct {
|
||||
func init() {
|
||||
formEncoder = schema.NewEncoder()
|
||||
formEncoder.SetAliasTag("form")
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
server *server.Server
|
||||
sessionCookie string
|
||||
SessionCookie string
|
||||
contextData echo.Map
|
||||
}
|
||||
|
||||
func newTestServer() (*TestServer, error) {
|
||||
s := &TestServer{
|
||||
server: server.NewServer(true, filepath.Join(config.GetHomeDir(), "tmp", "sessions"), true),
|
||||
}
|
||||
|
||||
go s.start()
|
||||
return s, nil
|
||||
func (s *Server) Request(t *testing.T, method, uri string, data interface{}, expectedCode int) *http.Response {
|
||||
return s.RequestWithHeaders(t, method, uri, data, expectedCode, nil)
|
||||
}
|
||||
|
||||
func (s *TestServer) start() {
|
||||
s.server.Start()
|
||||
}
|
||||
|
||||
func (s *TestServer) stop() {
|
||||
s.server.Stop()
|
||||
}
|
||||
|
||||
func (s *TestServer) Request(method, uri string, data interface{}, expectedCode int, responsePtr ...*http.Response) error {
|
||||
return s.RequestWithHeaders(method, uri, data, expectedCode, nil, responsePtr...)
|
||||
}
|
||||
|
||||
func (s *TestServer) RequestWithHeaders(method, uri string, data interface{}, expectedCode int, headers map[string]string, responsePtr ...*http.Response) error {
|
||||
func (s *Server) RequestWithHeaders(t *testing.T, method, uri string, data interface{}, expectedCode int, headers map[string]string) *http.Response {
|
||||
var bodyReader io.Reader
|
||||
if method == http.MethodPost || method == http.MethodPut {
|
||||
values := structToURLValues(data)
|
||||
bodyReader = strings.NewReader(values.Encode())
|
||||
if method == http.MethodPost || method == http.MethodPut || method == http.MethodDelete {
|
||||
if values, ok := data.(url.Values); ok {
|
||||
bodyReader = strings.NewReader(values.Encode())
|
||||
} else if data != nil {
|
||||
values := url.Values{}
|
||||
_ = formEncoder.Encode(data, values)
|
||||
bodyReader = strings.NewReader(values.Encode())
|
||||
}
|
||||
}
|
||||
|
||||
req := httptest.NewRequest(method, "http://localhost:6157"+uri, bodyReader)
|
||||
req := httptest.NewRequest(method, uri, bodyReader)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
if method == http.MethodPost || method == http.MethodPut {
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
}
|
||||
|
||||
req.Header.Set("Sec-Fetch-Site", "same-origin")
|
||||
|
||||
for key, value := range headers {
|
||||
req.Header.Set(key, value)
|
||||
}
|
||||
|
||||
if s.sessionCookie != "" {
|
||||
req.AddCookie(&http.Cookie{Name: "session", Value: s.sessionCookie})
|
||||
if s.SessionCookie != "" {
|
||||
req.AddCookie(&http.Cookie{Name: "session", Value: s.SessionCookie})
|
||||
}
|
||||
|
||||
s.server.ServeHTTP(w, req)
|
||||
|
||||
if w.Code != expectedCode {
|
||||
return fmt.Errorf("unexpected status code %d, expected %d", w.Code, expectedCode)
|
||||
if expectedCode != 0 {
|
||||
require.Equalf(t, expectedCode, w.Code, "Unexpected status code for %s %s: got %d, expected %d", method, uri, w.Code, expectedCode)
|
||||
}
|
||||
|
||||
if method == http.MethodPost {
|
||||
if strings.Contains(uri, "/login") || strings.Contains(uri, "/register") {
|
||||
if strings.Contains(uri, "/login") {
|
||||
cookie := ""
|
||||
h := w.Header().Get("Set-Cookie")
|
||||
parts := strings.Split(h, "; ")
|
||||
@@ -93,91 +85,127 @@ func (s *TestServer) RequestWithHeaders(method, uri string, data interface{}, ex
|
||||
break
|
||||
}
|
||||
}
|
||||
if cookie == "" {
|
||||
return errors.New("unable to find access session token in response headers")
|
||||
}
|
||||
s.sessionCookie = strings.TrimPrefix(cookie, "session=")
|
||||
s.SessionCookie = strings.TrimPrefix(cookie, "session=")
|
||||
} else if strings.Contains(uri, "/logout") {
|
||||
s.sessionCookie = ""
|
||||
s.SessionCookie = ""
|
||||
}
|
||||
}
|
||||
|
||||
// If a response pointer was provided, fill it with the response data
|
||||
if len(responsePtr) > 0 && responsePtr[0] != nil {
|
||||
*responsePtr[0] = *w.Result()
|
||||
return w.Result()
|
||||
}
|
||||
|
||||
func (s *Server) RawRequest(t *testing.T, req *http.Request, expectedCode int) *http.Response {
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
req.Header.Set("Sec-Fetch-Site", "same-origin")
|
||||
|
||||
if s.SessionCookie != "" {
|
||||
req.AddCookie(&http.Cookie{Name: "session", Value: s.SessionCookie})
|
||||
}
|
||||
|
||||
s.server.ServeHTTP(w, req)
|
||||
|
||||
require.Equal(t, expectedCode, w.Code, "unexpected status code for %s %s", req.Method, req.URL.Path)
|
||||
|
||||
return w.Result()
|
||||
}
|
||||
|
||||
func (s *Server) StartHttpServer(t *testing.T) string {
|
||||
hs := httptest.NewServer(s.server)
|
||||
t.Cleanup(hs.Close)
|
||||
return hs.URL
|
||||
}
|
||||
|
||||
func (s *Server) User() *db.User {
|
||||
s.Request(nil, "GET", "/", nil, 0)
|
||||
if user, ok := s.contextData["userLogged"].(*db.User); ok {
|
||||
return user
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func structToURLValues(s interface{}) url.Values {
|
||||
v := url.Values{}
|
||||
if s == nil {
|
||||
return v
|
||||
func (s *Server) TestCtxData(t *testing.T, expected echo.Map) {
|
||||
for key, expectedValue := range expected {
|
||||
actualValue, exists := s.contextData[key]
|
||||
require.True(t, exists, "Key %q not found in context data", key)
|
||||
require.Equal(t, expectedValue, actualValue, "Context data mismatch for key %q", key)
|
||||
}
|
||||
|
||||
rValue := reflect.ValueOf(s)
|
||||
if rValue.Kind() != reflect.Struct {
|
||||
return v
|
||||
}
|
||||
|
||||
for i := 0; i < rValue.NumField(); i++ {
|
||||
field := rValue.Type().Field(i)
|
||||
tag := field.Tag.Get("form")
|
||||
if tag != "" || field.Anonymous {
|
||||
if field.Type.Kind() == reflect.Int {
|
||||
fieldValue := rValue.Field(i).Int()
|
||||
v.Add(tag, strconv.FormatInt(fieldValue, 10))
|
||||
} else if field.Type.Kind() == reflect.Uint {
|
||||
fieldValue := rValue.Field(i).Uint()
|
||||
v.Add(tag, strconv.FormatUint(fieldValue, 10))
|
||||
} else if field.Type.Kind() == reflect.Slice {
|
||||
fieldValue := rValue.Field(i).Interface().([]string)
|
||||
for _, va := range fieldValue {
|
||||
v.Add(tag, va)
|
||||
}
|
||||
} else if field.Type.Kind() == reflect.Struct {
|
||||
for key, val := range structToURLValues(rValue.Field(i).Interface()) {
|
||||
for _, vv := range val {
|
||||
v.Add(key, vv)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fieldValue := rValue.Field(i).String()
|
||||
v.Add(tag, fieldValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func Setup(t *testing.T) *TestServer {
|
||||
_ = os.Setenv("OPENGIST_SKIP_GIT_HOOKS", "1")
|
||||
func (s *Server) Register(t *testing.T, user string) {
|
||||
s.Request(t, "POST", "/register", db.UserDTO{Username: user, Password: user}, 302)
|
||||
}
|
||||
|
||||
func (s *Server) Login(t *testing.T, user string) {
|
||||
s.Request(t, "POST", "/login", db.UserDTO{Username: user, Password: user}, 302)
|
||||
}
|
||||
|
||||
func (s *Server) Logout() {
|
||||
s.SessionCookie = ""
|
||||
}
|
||||
|
||||
func (s *Server) CreateGist(t *testing.T, visibility string) (gistPath string, gist *db.Gist, username, identifier string) {
|
||||
s.Request(t, "POST", "/register", db.UserDTO{Username: "thomas", Password: "thomas"}, 0)
|
||||
s.Login(t, "thomas")
|
||||
|
||||
resp := s.Request(t, "POST", "/", url.Values{
|
||||
"title": {"Test"},
|
||||
"name": {"file.txt", "otherfile.txt"},
|
||||
"content": {"hello world", "other content"},
|
||||
"topics": {"hello opengist"},
|
||||
"private": {visibility},
|
||||
}, 302)
|
||||
|
||||
// Extract gist identifier from redirect
|
||||
location := resp.Header.Get("Location")
|
||||
parts := strings.Split(strings.TrimPrefix(location, "/"), "/")
|
||||
require.Len(t, parts, 2, "Expected redirect format: /{username}/{identifier}")
|
||||
|
||||
gistUsername := parts[0]
|
||||
gistIdentifier := parts[1]
|
||||
|
||||
gist, err := db.GetGist(gistUsername, gistIdentifier)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, gist)
|
||||
|
||||
gistPath = filepath.Join(config.GetHomeDir(), git.ReposDirectory, "thomas", gist.Uuid)
|
||||
|
||||
// Verify gist exists on filesystem
|
||||
_, err = os.Stat(gistPath)
|
||||
require.NoError(t, err, "Gist repository should exist at %s", gistPath)
|
||||
|
||||
username = gist.User.Username
|
||||
identifier = gist.Identifier()
|
||||
|
||||
s.Logout()
|
||||
return gistPath, gist, username, identifier
|
||||
}
|
||||
|
||||
func Setup(t *testing.T) *Server {
|
||||
tmpDir := t.TempDir()
|
||||
t.Setenv("OPENGIST_SKIP_GIT_HOOKS", "1")
|
||||
|
||||
err := config.InitConfig("", io.Discard)
|
||||
require.NoError(t, err, "Could not init config")
|
||||
|
||||
err = os.MkdirAll(filepath.Join(config.GetHomeDir()), 0755)
|
||||
require.NoError(t, err, "Could not create Opengist home directory")
|
||||
config.C.LogLevel = "warn"
|
||||
config.C.LogOutput = "stdout"
|
||||
config.C.GitDefaultBranch = "master"
|
||||
config.C.OpengistHome = tmpDir
|
||||
|
||||
config.SetupSecretKey()
|
||||
|
||||
git.ReposDirectory = filepath.Join("tests")
|
||||
|
||||
config.C.Index = ""
|
||||
config.C.LogLevel = "error"
|
||||
config.C.GitDefaultBranch = "master"
|
||||
config.InitLog()
|
||||
|
||||
tmpGitConfig := filepath.Join(tmpDir, "gitconfig")
|
||||
t.Setenv("GIT_CONFIG_GLOBAL", tmpGitConfig)
|
||||
|
||||
err = exec.Command("git", "config", "--global", "--type", "bool", "push.autoSetupRemote", "true").Run()
|
||||
require.NoError(t, err)
|
||||
err = exec.Command("git", "config", "--global", "user.email", "test@opengist.io").Run()
|
||||
require.NoError(t, err)
|
||||
err = exec.Command("git", "config", "--global", "user.name", "test").Run()
|
||||
require.NoError(t, err)
|
||||
|
||||
homePath := config.GetHomeDir()
|
||||
log.Info().Msg("Data directory: " + homePath)
|
||||
|
||||
var databaseDsn string
|
||||
databaseType = os.Getenv("OPENGIST_TEST_DB")
|
||||
@@ -187,70 +215,51 @@ func Setup(t *testing.T) *TestServer {
|
||||
case "mysql":
|
||||
databaseDsn = "mysql://root:opengist@localhost:3306/opengist_test"
|
||||
default:
|
||||
databaseDsn = "file:" + filepath.Join(homePath, "tmp", "opengist_test.db")
|
||||
databaseDsn = config.C.DBUri
|
||||
}
|
||||
|
||||
err = os.MkdirAll(filepath.Join(homePath, "tests"), 0755)
|
||||
require.NoError(t, err, "Could not create tests directory")
|
||||
|
||||
err = os.MkdirAll(filepath.Join(homePath, "tmp", "sessions"), 0755)
|
||||
err = os.MkdirAll(filepath.Join(homePath, "sessions"), 0755)
|
||||
require.NoError(t, err, "Could not create sessions directory")
|
||||
|
||||
err = os.MkdirAll(filepath.Join(homePath, "repos"), 0755)
|
||||
require.NoError(t, err, "Could not create repos directory")
|
||||
|
||||
err = os.MkdirAll(filepath.Join(homePath, "tmp", "repos"), 0755)
|
||||
require.NoError(t, err, "Could not create tmp repos directory")
|
||||
|
||||
err = os.MkdirAll(filepath.Join(homePath, "custom"), 0755)
|
||||
require.NoError(t, err, "Could not create custom directory")
|
||||
|
||||
err = db.Setup(databaseDsn)
|
||||
require.NoError(t, err, "Could not initialize database")
|
||||
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("Could not initialize database")
|
||||
if index.IndexEnabled() {
|
||||
go index.NewIndexer(index.IndexType())
|
||||
}
|
||||
|
||||
// err = index.Open(filepath.Join(homePath, "testsindex", "opengist.index"))
|
||||
// require.NoError(t, err, "Could not open index")
|
||||
s := &Server{
|
||||
server: server.NewServer(true),
|
||||
}
|
||||
|
||||
s, err := newTestServer()
|
||||
require.NoError(t, err, "Failed to create test server")
|
||||
s.server.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
err := next(c)
|
||||
if data, ok := c.Request().Context().Value(context.DataKeyStr).(echo.Map); ok {
|
||||
s.contextData = data
|
||||
}
|
||||
return err
|
||||
}
|
||||
})
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func Teardown(t *testing.T, s *TestServer) {
|
||||
s.stop()
|
||||
|
||||
//err := db.Close()
|
||||
//require.NoError(t, err, "Could not close database")
|
||||
|
||||
err := db.TruncateDatabase()
|
||||
require.NoError(t, err, "Could not truncate database")
|
||||
|
||||
err = os.RemoveAll(filepath.Join(config.GetHomeDir(), "tests"))
|
||||
require.NoError(t, err, "Could not remove repos directory")
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
err = db.Close()
|
||||
require.NoError(t, err, "Could not close database")
|
||||
|
||||
time.Sleep(2 * time.Second)
|
||||
func Teardown(t *testing.T) {
|
||||
switch databaseType {
|
||||
case "postgres", "mysql":
|
||||
err := db.TruncateDatabase()
|
||||
require.NoError(t, err, "Could not truncate database")
|
||||
}
|
||||
err = os.RemoveAll(filepath.Join(config.GetHomeDir(), "tmp"))
|
||||
require.NoError(t, err, "Could not remove tmp directory")
|
||||
|
||||
// err = os.RemoveAll(path.Join(config.C.OpengistHome, "testsindex"))
|
||||
// require.NoError(t, err, "Could not remove repos directory")
|
||||
|
||||
// err = index.Close()
|
||||
// require.NoError(t, err, "Could not close index")
|
||||
}
|
||||
|
||||
type settingSet struct {
|
||||
key string `form:"key"`
|
||||
value string `form:"value"`
|
||||
}
|
||||
|
||||
type invitationAdmin struct {
|
||||
nbMax string `form:"nbMax"`
|
||||
expiredAtUnix string `form:"expiredAtUnix"`
|
||||
}
|
||||
|
||||
func NewTestMetricsServer() *metrics.Server {
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
package test
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/thomiceli/opengist/internal/db"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSettingsPage(t *testing.T) {
|
||||
s := Setup(t)
|
||||
defer Teardown(t, s)
|
||||
|
||||
err := s.Request("GET", "/settings", nil, 302)
|
||||
require.NoError(t, err)
|
||||
|
||||
user1 := db.UserDTO{Username: "thomas", Password: "thomas"}
|
||||
register(t, s, user1)
|
||||
login(t, s, user1)
|
||||
|
||||
err = s.Request("GET", "/settings", nil, 200)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
المرجع في مشكلة جديدة
حظر مستخدم