vikunja/pkg/webtests/huma_backgrounds_misc_test.go

113 lines
4.8 KiB
Go

// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-present Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package webtests
import (
"net/http"
"testing"
"code.vikunja.io/api/pkg/config"
"code.vikunja.io/api/pkg/db"
"code.vikunja.io/api/pkg/models"
"code.vikunja.io/api/pkg/routes"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// TestHumaProjectBackgroundDelete covers removing a project background. It
// mirrors the v1 background_test.go matrix: the owner clears the background
// (and keeps the title), a read-only user is refused.
func TestHumaProjectBackgroundDelete(t *testing.T) {
e, err := setupTestEnv()
require.NoError(t, err)
t.Run("Owner clears the background, title preserved", func(t *testing.T) {
// testuser6 owns project 35 (title "Test35 with background", background_file_id 1).
rec := humaRequest(t, e, http.MethodDelete, "/api/v2/projects/35/background", "", humaTokenFor(t, &testuser6), "")
require.Equal(t, http.StatusOK, rec.Code, "body: %s", rec.Body.String())
s := db.NewSession()
defer s.Close()
project := models.Project{ID: 35}
has, err := s.Get(&project)
require.NoError(t, err)
require.True(t, has)
assert.Equal(t, "Test35 with background", project.Title)
assert.Equal(t, int64(0), project.BackgroundFileID)
})
t.Run("Read-only user is forbidden", func(t *testing.T) {
// testuser15 has read-only (permission 0) access to project 35.
rec := humaRequest(t, e, http.MethodDelete, "/api/v2/projects/35/background", "", humaTokenFor(t, &testuser15), "")
assert.Equal(t, http.StatusForbidden, rec.Code, "body: %s", rec.Body.String())
})
t.Run("No access at all is forbidden", func(t *testing.T) {
// testuser1 has no access to project 35.
rec := humaRequest(t, e, http.MethodDelete, "/api/v2/projects/35/background", "", humaTokenFor(t, &testuser1), "")
assert.Equal(t, http.StatusForbidden, rec.Code, "body: %s", rec.Body.String())
})
}
// TestHumaBackgroundDisabledByConfig verifies the registrar early-returns when
// project backgrounds are disabled: the DELETE route is then absent (404).
func TestHumaBackgroundDisabledByConfig(t *testing.T) {
_, err := setupTestEnv()
require.NoError(t, err)
config.BackgroundsEnabled.Set(false)
defer config.BackgroundsEnabled.Set(true)
e := routes.NewEcho()
routes.RegisterRoutes(e)
rec := humaRequest(t, e, http.MethodDelete, "/api/v2/projects/35/background", "", humaTokenFor(t, &testuser6), "")
assert.Equal(t, http.StatusNotFound, rec.Code, "route must be absent when backgrounds are disabled; body: %s", rec.Body.String())
}
// TestHumaUnsplashBackground covers the Unsplash routes' auth and permission
// gates. They are only registered when the unsplash provider is enabled (off by
// default), so the router is rebuilt with the flag on. The set route's
// permission check runs before any Unsplash network call, so the negative cases
// are exercised without hitting the real API; the happy path needs the network
// and is therefore not covered here (matching v1).
func TestHumaUnsplashBackground(t *testing.T) {
_, err := setupTestEnv()
require.NoError(t, err)
config.BackgroundsEnabled.Set(true)
config.BackgroundsUnsplashEnabled.Set(true)
defer config.BackgroundsUnsplashEnabled.Set(false)
e := routes.NewEcho()
routes.RegisterRoutes(e)
t.Run("Search requires auth", func(t *testing.T) {
rec := humaRequest(t, e, http.MethodGet, "/api/v2/backgrounds/unsplash/search?q=mountain", "", "", "")
assert.Equal(t, http.StatusUnauthorized, rec.Code, "body: %s", rec.Body.String())
})
t.Run("Set requires auth", func(t *testing.T) {
rec := humaRequest(t, e, http.MethodPut, "/api/v2/projects/35/backgrounds/unsplash", `{"id":"abc"}`, "", "")
assert.Equal(t, http.StatusUnauthorized, rec.Code, "body: %s", rec.Body.String())
})
t.Run("Set forbidden for read-only user", func(t *testing.T) {
// testuser15 has read-only access to project 35; CanUpdate fails before
// p.Set reaches Unsplash.
rec := humaRequest(t, e, http.MethodPut, "/api/v2/projects/35/backgrounds/unsplash", `{"id":"abc"}`, humaTokenFor(t, &testuser15), "")
assert.Equal(t, http.StatusForbidden, rec.Code, "body: %s", rec.Body.String())
})
}