Adds BoxActivity model to track actions taken on a box. Updates related endpoints and UI for activity feed.
220 lines
8.2 KiB
Go
220 lines
8.2 KiB
Go
package server
|
|
|
|
import (
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"os"
|
|
"strings"
|
|
"testing"
|
|
|
|
"warpbox/lib/boxstore"
|
|
"warpbox/lib/metastore"
|
|
)
|
|
|
|
func TestAccountBoxManagerAdminCanViewAndEdit(t *testing.T) {
|
|
app, admin := setupAccountTestApp(t)
|
|
router := setupAccountTestRouter(t, app)
|
|
session := createAccountTestSession(t, app, admin)
|
|
id := "abababababababababababababababab"
|
|
createIndexedBox(t, app, id, "", "", 10, false)
|
|
|
|
response := getAccountBoxManager(router, session, id)
|
|
if response.Code != http.StatusOK {
|
|
t.Fatalf("expected manager page, got %d body=%s", response.Code, response.Body.String())
|
|
}
|
|
if !strings.Contains(response.Body.String(), "WarpBox Box Manager") {
|
|
t.Fatal("expected manager UI")
|
|
}
|
|
|
|
form := url.Values{"disable_zip": []string{"true"}}
|
|
response = postAccountBoxForm(router, session, "/account/boxes/"+id, form)
|
|
if response.Code != http.StatusSeeOther {
|
|
t.Fatalf("expected update redirect, got %d", response.Code)
|
|
}
|
|
manifest, err := boxstore.ReadManifest(id)
|
|
if err != nil {
|
|
t.Fatalf("ReadManifest returned error: %v", err)
|
|
}
|
|
if !manifest.DisableZip {
|
|
t.Fatal("expected sharing rule update")
|
|
}
|
|
}
|
|
|
|
func TestAccountBoxManagerOwnerViewAllowedAndDeniedByPolicy(t *testing.T) {
|
|
app, _ := setupAccountTestApp(t)
|
|
user, err := app.store.CreateUserWithPassword("owner-view", "owner-view@example.test", "secret", nil)
|
|
if err != nil {
|
|
t.Fatalf("CreateUserWithPassword returned error: %v", err)
|
|
}
|
|
router := setupAccountTestRouter(t, app)
|
|
session := createAccountTestSession(t, app, user)
|
|
id := "bcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbc"
|
|
createIndexedBox(t, app, id, user.ID, user.Username, 10, false)
|
|
|
|
response := getAccountBoxManager(router, session, id)
|
|
if response.Code != http.StatusOK {
|
|
t.Fatalf("expected owner manager page, got %d", response.Code)
|
|
}
|
|
|
|
app.config.BoxOwnerEditEnabled = false
|
|
response = getAccountBoxManager(router, session, id)
|
|
if response.Code != http.StatusForbidden {
|
|
t.Fatalf("expected owner denied by policy, got %d", response.Code)
|
|
}
|
|
}
|
|
|
|
func TestAccountBoxManagerOwnerRefreshLimits(t *testing.T) {
|
|
app, _ := setupAccountTestApp(t)
|
|
app.config.BoxOwnerMaxRefreshCount = 1
|
|
app.config.BoxOwnerMaxRefreshAmountSeconds = 60
|
|
app.config.BoxOwnerMaxTotalExpirySeconds = 7200
|
|
user, err := app.store.CreateUserWithPassword("owner-refresh", "owner-refresh@example.test", "secret", nil)
|
|
if err != nil {
|
|
t.Fatalf("CreateUserWithPassword returned error: %v", err)
|
|
}
|
|
router := setupAccountTestRouter(t, app)
|
|
session := createAccountTestSession(t, app, user)
|
|
id := "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"
|
|
createIndexedBox(t, app, id, user.ID, user.Username, 10, false)
|
|
|
|
response := postAccountBoxForm(router, session, "/account/boxes/"+id+"/extend", url.Values{"extend_seconds": []string{"60"}})
|
|
if response.Code != http.StatusSeeOther {
|
|
t.Fatalf("expected owner refresh success, got %d body=%s", response.Code, response.Body.String())
|
|
}
|
|
record, ok, err := app.store.GetBoxRecord(id)
|
|
if err != nil || !ok {
|
|
t.Fatalf("GetBoxRecord returned ok=%v err=%v", ok, err)
|
|
}
|
|
if record.RefreshCount != 1 {
|
|
t.Fatalf("expected refresh count 1, got %d", record.RefreshCount)
|
|
}
|
|
|
|
response = postAccountBoxForm(router, session, "/account/boxes/"+id+"/extend", url.Values{"extend_seconds": []string{"60"}})
|
|
if response.Code != http.StatusOK {
|
|
t.Fatalf("expected refresh count rejection render, got %d", response.Code)
|
|
}
|
|
if !strings.Contains(response.Body.String(), "refresh count") {
|
|
t.Fatal("expected refresh count error")
|
|
}
|
|
}
|
|
|
|
func TestAccountBoxManagerOwnerRefreshRejectedOverMaxDuration(t *testing.T) {
|
|
app, _ := setupAccountTestApp(t)
|
|
app.config.BoxOwnerMaxRefreshAmountSeconds = 60
|
|
user, err := app.store.CreateUserWithPassword("owner-duration", "owner-duration@example.test", "secret", nil)
|
|
if err != nil {
|
|
t.Fatalf("CreateUserWithPassword returned error: %v", err)
|
|
}
|
|
router := setupAccountTestRouter(t, app)
|
|
session := createAccountTestSession(t, app, user)
|
|
id := "dededededededededededededededede"
|
|
createIndexedBox(t, app, id, user.ID, user.Username, 10, false)
|
|
|
|
response := postAccountBoxForm(router, session, "/account/boxes/"+id+"/extend", url.Values{"extend_seconds": []string{"120"}})
|
|
if response.Code != http.StatusOK {
|
|
t.Fatalf("expected max duration rejection render, got %d", response.Code)
|
|
}
|
|
if !strings.Contains(response.Body.String(), "maximum single extension") {
|
|
t.Fatal("expected max duration error")
|
|
}
|
|
}
|
|
|
|
func TestAccountBoxManagerPasswordSetRemovePermissions(t *testing.T) {
|
|
app, _ := setupAccountTestApp(t)
|
|
user, err := app.store.CreateUserWithPassword("owner-pass", "owner-pass@example.test", "secret", nil)
|
|
if err != nil {
|
|
t.Fatalf("CreateUserWithPassword returned error: %v", err)
|
|
}
|
|
router := setupAccountTestRouter(t, app)
|
|
session := createAccountTestSession(t, app, user)
|
|
id := "efefefefefefefefefefefefefefefef"
|
|
createIndexedBox(t, app, id, user.ID, user.Username, 10, false)
|
|
|
|
response := postAccountBoxForm(router, session, "/account/boxes/"+id+"/password", url.Values{"password": []string{"new-secret"}})
|
|
if response.Code != http.StatusSeeOther {
|
|
t.Fatalf("expected password set redirect, got %d", response.Code)
|
|
}
|
|
manifest, err := boxstore.ReadManifest(id)
|
|
if err != nil {
|
|
t.Fatalf("ReadManifest returned error: %v", err)
|
|
}
|
|
if manifest.PasswordHash == "" || manifest.AuthToken == "" {
|
|
t.Fatal("expected password set")
|
|
}
|
|
|
|
app.config.BoxOwnerPasswordEditEnabled = false
|
|
response = postAccountBoxForm(router, session, "/account/boxes/"+id+"/password/remove", nil)
|
|
if response.Code != http.StatusOK {
|
|
t.Fatalf("expected password permission render, got %d", response.Code)
|
|
}
|
|
if !strings.Contains(response.Body.String(), "password editing disabled") {
|
|
t.Fatal("expected password permission error")
|
|
}
|
|
}
|
|
|
|
func TestAccountBoxManagerFileDeleteAndBoxDeletePermissions(t *testing.T) {
|
|
app, _ := setupAccountTestApp(t)
|
|
user, err := app.store.CreateUserWithPassword("owner-delete", "owner-delete@example.test", "secret", nil)
|
|
if err != nil {
|
|
t.Fatalf("CreateUserWithPassword returned error: %v", err)
|
|
}
|
|
router := setupAccountTestRouter(t, app)
|
|
session := createAccountTestSession(t, app, user)
|
|
id := "fafafafafafafafafafafafafafafafa"
|
|
createIndexedBox(t, app, id, user.ID, user.Username, 10, false)
|
|
manifest, err := boxstore.ReadManifest(id)
|
|
if err != nil {
|
|
t.Fatalf("ReadManifest returned error: %v", err)
|
|
}
|
|
fileID := manifest.Files[0].ID
|
|
|
|
response := postAccountBoxForm(router, session, "/account/boxes/"+id+"/files/delete", url.Values{"file_ids": []string{fileID}})
|
|
if response.Code != http.StatusSeeOther {
|
|
t.Fatalf("expected file delete redirect, got %d", response.Code)
|
|
}
|
|
manifest, err = boxstore.ReadManifest(id)
|
|
if err != nil {
|
|
t.Fatalf("ReadManifest returned error: %v", err)
|
|
}
|
|
if len(manifest.Files) != 0 {
|
|
t.Fatalf("expected file removed, got %#v", manifest.Files)
|
|
}
|
|
|
|
app.config.BoxOwnerEditEnabled = false
|
|
response = postAccountBoxForm(router, session, "/account/boxes/"+id+"/delete", nil)
|
|
if response.Code != http.StatusForbidden {
|
|
t.Fatalf("expected delete permission denied after policy disabled, got %d", response.Code)
|
|
}
|
|
|
|
app.config.BoxOwnerEditEnabled = true
|
|
response = postAccountBoxForm(router, session, "/account/boxes/"+id+"/delete", nil)
|
|
if response.Code != http.StatusSeeOther {
|
|
t.Fatalf("expected box delete redirect, got %d", response.Code)
|
|
}
|
|
if _, err := os.Stat(boxstore.BoxPath(id)); !os.IsNotExist(err) {
|
|
t.Fatalf("expected box directory deleted, stat err=%v", err)
|
|
}
|
|
}
|
|
|
|
func getAccountBoxManager(router http.Handler, session metastore.Session, id string) *httptest.ResponseRecorder {
|
|
request := httptest.NewRequest(http.MethodGet, "/account/boxes/"+id, nil)
|
|
request.AddCookie(&http.Cookie{Name: accountSessionCookie, Value: session.Token})
|
|
response := httptest.NewRecorder()
|
|
router.ServeHTTP(response, request)
|
|
return response
|
|
}
|
|
|
|
func postAccountBoxForm(router http.Handler, session metastore.Session, path string, values url.Values) *httptest.ResponseRecorder {
|
|
if values == nil {
|
|
values = url.Values{}
|
|
}
|
|
values.Set("csrf_token", session.CSRFToken)
|
|
request := httptest.NewRequest(http.MethodPost, path, strings.NewReader(values.Encode()))
|
|
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
|
request.AddCookie(&http.Cookie{Name: accountSessionCookie, Value: session.Token})
|
|
response := httptest.NewRecorder()
|
|
router.ServeHTTP(response, request)
|
|
return response
|
|
}
|