mirror of
https://git.freecumextremist.com/grumbulon/pomme.git
synced 2024-11-27 02:13:56 +00:00
333 lines
6.6 KiB
Go
333 lines
6.6 KiB
Go
package api
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"mime/multipart"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"dns.froth.zone/pomme/internal"
|
|
"dns.froth.zone/pomme/internal/db"
|
|
"github.com/go-chi/chi/v5"
|
|
"github.com/go-chi/jwtauth/v5"
|
|
"github.com/stretchr/testify/assert"
|
|
"golang.org/x/crypto/bcrypt"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type response struct {
|
|
Username string `json:"username"`
|
|
Message string `json:"message"`
|
|
Status int `json:"status"`
|
|
}
|
|
|
|
type accountTest struct {
|
|
username string
|
|
password string
|
|
token string
|
|
url string
|
|
}
|
|
|
|
func makeTestToken(username string) (tokenString string, err error) {
|
|
claim := map[string]any{"username": username, "admin": false}
|
|
|
|
jwtauth.SetExpiry(claim, time.Now().Add(time.Minute))
|
|
|
|
if _, tokenString, err = tokenAuth.Encode(claim); err == nil {
|
|
return
|
|
}
|
|
|
|
return "", fmt.Errorf("unable to generate JWT: %w", err)
|
|
}
|
|
|
|
func TestAPI(t *testing.T) {
|
|
config, err := internal.ReadConfig()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
pomme := chi.NewRouter()
|
|
|
|
pomme.Mount("/api", API())
|
|
|
|
s := &http.Server{
|
|
ReadTimeout: 3 * time.Second,
|
|
WriteTimeout: 15 * time.Second,
|
|
Addr: ":" + config.Port,
|
|
Handler: pomme,
|
|
}
|
|
|
|
ts := httptest.NewUnstartedServer(pomme)
|
|
ts.Config = s
|
|
ts.Start()
|
|
|
|
defer ts.Close()
|
|
|
|
tester := Init(ts.URL)
|
|
// test mode
|
|
mode = "test"
|
|
db, err, ok := db.InitDb(config.DB, mode)
|
|
|
|
if err != nil && !ok {
|
|
assert.NotNil(t, err)
|
|
}
|
|
|
|
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(tester.password), bcrypt.DefaultCost)
|
|
if err != nil {
|
|
assert.NotNil(t, err)
|
|
}
|
|
|
|
db.Create(&internal.User{Username: tester.username, HashedPassword: string(hashedPassword)})
|
|
|
|
tester.TestMakeAccount(t)
|
|
tester.TestLogin(t)
|
|
tester.TestLogout(t)
|
|
tester.TestUpload(t)
|
|
tester.CleanUp(db)
|
|
}
|
|
|
|
func Init(url string) accountTest {
|
|
user := autoUname()
|
|
|
|
user += "-testUser"
|
|
|
|
token, err := makeTestToken(user)
|
|
if err != nil {
|
|
return accountTest{}
|
|
}
|
|
|
|
test := accountTest{
|
|
username: user,
|
|
password: "merde",
|
|
url: url,
|
|
token: token,
|
|
}
|
|
|
|
return test
|
|
}
|
|
|
|
func (a *accountTest) TestMakeAccount(t *testing.T) {
|
|
var target response
|
|
|
|
client := http.Client{}
|
|
|
|
form := url.Values{}
|
|
|
|
form.Add("username", a.username)
|
|
|
|
form.Add("password", a.password)
|
|
|
|
if req, err := http.NewRequest(http.MethodPost, a.url+`api/create`, strings.NewReader(form.Encode())); err == nil {
|
|
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
|
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
assert.NotNil(t, err)
|
|
}
|
|
|
|
respBody, _ := io.ReadAll(resp.Body)
|
|
|
|
err = json.Unmarshal(respBody, &target)
|
|
if err != nil {
|
|
assert.NotNil(t, err)
|
|
}
|
|
|
|
assert.Equal(t, http.StatusCreated, target.Status)
|
|
}
|
|
}
|
|
|
|
func (a *accountTest) TestLogin(t *testing.T) {
|
|
var target response
|
|
|
|
client := http.Client{}
|
|
|
|
form := url.Values{}
|
|
|
|
form.Add("username", a.username)
|
|
|
|
form.Add("password", a.password)
|
|
|
|
if req, err := http.NewRequest(http.MethodPost, a.url+`/api/login`, strings.NewReader(form.Encode())); err == nil {
|
|
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
|
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
assert.NotNil(t, err)
|
|
}
|
|
|
|
respBody, _ := io.ReadAll(resp.Body)
|
|
|
|
err = json.Unmarshal(respBody, &target)
|
|
if err != nil {
|
|
assert.NotNil(t, err)
|
|
}
|
|
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
}
|
|
}
|
|
|
|
func (a *accountTest) TestLogout(t *testing.T) {
|
|
var target response
|
|
|
|
client := http.Client{}
|
|
|
|
form := url.Values{}
|
|
|
|
form.Add("username", a.username)
|
|
|
|
if req, err := http.NewRequest(http.MethodPost, a.url+`/api/logout`, strings.NewReader(form.Encode())); err == nil {
|
|
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
|
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
assert.NotNil(t, err)
|
|
}
|
|
|
|
respBody, _ := io.ReadAll(resp.Body)
|
|
|
|
err = json.Unmarshal(respBody, &target)
|
|
if err != nil {
|
|
assert.NotNil(t, err)
|
|
}
|
|
|
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
|
}
|
|
}
|
|
|
|
type expectedValues struct {
|
|
response int
|
|
}
|
|
|
|
func (a *accountTest) TestUpload(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
file string
|
|
contentType string
|
|
fileContents []byte
|
|
expected expectedValues
|
|
}{
|
|
{
|
|
name: "Should fail to upload an empty file",
|
|
file: "badzonefile",
|
|
contentType: "audio/aac",
|
|
expected: expectedValues{
|
|
response: http.StatusInternalServerError,
|
|
},
|
|
},
|
|
{
|
|
name: "Should upload a valid file",
|
|
file: "zonefile",
|
|
contentType: "multipart/form-data",
|
|
fileContents: []byte{},
|
|
expected: expectedValues{
|
|
response: http.StatusCreated,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
var (
|
|
f *os.File
|
|
target response
|
|
err error
|
|
buf = new(bytes.Buffer)
|
|
w = multipart.NewWriter(buf)
|
|
)
|
|
|
|
switch tc.name {
|
|
case "Should fail to upload an empty file":
|
|
f, err = os.CreateTemp(".", tc.file)
|
|
if err != nil {
|
|
assert.NotNil(t, err)
|
|
}
|
|
default:
|
|
f, err = os.CreateTemp(".", "zonefile")
|
|
if err != nil {
|
|
assert.NotNil(t, err)
|
|
}
|
|
|
|
if err = os.WriteFile(f.Name(), zonebytes, 0o600); err != nil {
|
|
assert.NotNil(t, err)
|
|
}
|
|
}
|
|
|
|
defer os.Remove(f.Name()) //nolint: errcheck
|
|
|
|
client := http.Client{}
|
|
|
|
part, err := w.CreateFormFile("file", filepath.Base(f.Name()))
|
|
if err != nil {
|
|
assert.NotNil(t, err)
|
|
}
|
|
|
|
b, err := os.ReadFile(f.Name())
|
|
if err != nil {
|
|
assert.NotNil(t, err)
|
|
}
|
|
|
|
_, err = part.Write(b)
|
|
if err != nil {
|
|
assert.NotNil(t, err)
|
|
}
|
|
|
|
err = w.Close()
|
|
if err != nil {
|
|
assert.NotNil(t, err)
|
|
}
|
|
|
|
if req, err := http.NewRequest(http.MethodPost, a.url+`/api/upload`, buf); err == nil {
|
|
switch tc.name {
|
|
case "Should fail to upload an empty file":
|
|
req.Header.Add("Content-Type", tc.contentType)
|
|
default:
|
|
req.Header.Add("Content-Type", w.FormDataContentType())
|
|
}
|
|
|
|
req.Header.Add("Authorization", `Bearer:`+a.token)
|
|
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
assert.NotNil(t, err)
|
|
}
|
|
|
|
respBody, _ := io.ReadAll(resp.Body)
|
|
|
|
err = json.Unmarshal(respBody, &target)
|
|
if err != nil {
|
|
assert.NotNil(t, err)
|
|
}
|
|
|
|
assert.Equal(t, tc.expected.response, resp.StatusCode)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func (a *accountTest) CleanUp(db *gorm.DB) {
|
|
var (
|
|
user internal.User
|
|
req internal.ZoneRequest
|
|
)
|
|
|
|
db.Where("username = ?", a.username).Delete(&user)
|
|
|
|
db.Where("user = ?", a.username).Delete(&req)
|
|
|
|
if err := os.Remove("pomme-test.sqlite"); err != nil {
|
|
l := newResponder(Response[any]{
|
|
Message: "unable to clean up test DB",
|
|
Err: err.Error(),
|
|
})
|
|
l.writeLogEntry()
|
|
}
|
|
}
|