package test import ( "fmt" "github.com/stretchr/testify/require" "github.com/thomiceli/opengist/internal/config" "github.com/thomiceli/opengist/internal/db" "os" "os/exec" "path" "testing" ) 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) } type settingSet struct { key string `form:"key"` value string `form:"value"` } 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"}, } 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", }, } 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", }, } 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", }, } err = s.request("POST", "/", gist3, 302) require.NoError(t, err) gitOperations := func(credentials, owner, url, filename string, expectErrorClone, expectErrorCheck, expectErrorPush bool) { fmt.Println("Testing", 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) if expectErrorPush { require.Error(t, err) } else { require.NoError(t, err) } } tests := []struct { credentials string user string url 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 { gitOperations(test.credentials, test.user, test.url, "kaguya-file.txt", 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 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 { gitOperations(test.credentials, test.user, test.url, "kaguya-file.txt", 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 { gitOperations(test.credentials, test.user, test.url, "kaguya-file.txt", test.expectErrorClone, test.expectErrorCheck, test.expectErrorPush) } } func clientGitClone(creds string, user string, url string) error { return exec.Command("git", "clone", "http://"+creds+"@localhost:6157/"+user+"/"+url, path.Join(config.GetHomeDir(), "tmp", url)).Run() } func clientGitPush(url string) error { f, err := os.Create(path.Join(config.GetHomeDir(), "tmp", url, "newfile.txt")) if err != nil { return err } f.Close() _ = exec.Command("git", "-C", path.Join(config.GetHomeDir(), "tmp", url), "add", "newfile.txt").Run() _ = exec.Command("git", "-C", path.Join(config.GetHomeDir(), "tmp", url), "commit", "-m", "new file").Run() err = exec.Command("git", "-C", path.Join(config.GetHomeDir(), "tmp", url), "push", "origin", "master").Run() _ = os.RemoveAll(path.Join(config.GetHomeDir(), "tmp", url)) return err } func clientCheckRepo(url string, file string) error { _, err := os.ReadFile(path.Join(config.GetHomeDir(), "tmp", url, file)) return err }