a4e2bb33b9
Signed-off-by: Michael Mayer <michael@photoprism.app>
254 lines
7.6 KiB
Go
254 lines
7.6 KiB
Go
package server
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"github.com/photoprism/photoprism/internal/acl"
|
|
"github.com/photoprism/photoprism/internal/config"
|
|
"github.com/photoprism/photoprism/internal/entity"
|
|
"github.com/photoprism/photoprism/pkg/header"
|
|
"github.com/photoprism/photoprism/pkg/rnd"
|
|
)
|
|
|
|
func TestWebDAVAuth(t *testing.T) {
|
|
conf := config.TestConfig()
|
|
webdavHandler := WebDAVAuth(conf)
|
|
|
|
t.Run("Unauthorized", func(t *testing.T) {
|
|
w := httptest.NewRecorder()
|
|
c, _ := gin.CreateTestContext(w)
|
|
c.Request = &http.Request{
|
|
Header: make(http.Header),
|
|
}
|
|
|
|
webdavAuthCache.Flush()
|
|
webdavHandler(c)
|
|
|
|
assert.Equal(t, http.StatusUnauthorized, c.Writer.Status())
|
|
assert.Equal(t, BasicAuthRealm, c.Writer.Header().Get("WWW-Authenticate"))
|
|
})
|
|
t.Run("AliceToken", func(t *testing.T) {
|
|
w := httptest.NewRecorder()
|
|
c, _ := gin.CreateTestContext(w)
|
|
c.Request = &http.Request{
|
|
Header: make(http.Header),
|
|
}
|
|
|
|
webdavAuthCache.Flush()
|
|
|
|
sess := entity.SessionFixtures.Get("alice_token")
|
|
header.SetAuthorization(c.Request, sess.AuthToken())
|
|
|
|
webdavHandler(c)
|
|
|
|
assert.Equal(t, http.StatusOK, c.Writer.Status())
|
|
assert.Equal(t, "", c.Writer.Header().Get("WWW-Authenticate"))
|
|
})
|
|
t.Run("AliceTokenWebdav", func(t *testing.T) {
|
|
w := httptest.NewRecorder()
|
|
c, _ := gin.CreateTestContext(w)
|
|
c.Request = &http.Request{
|
|
Header: make(http.Header),
|
|
}
|
|
|
|
sess := entity.SessionFixtures.Get("alice_token_webdav")
|
|
basicAuth := []byte(fmt.Sprintf("alice:%s", sess.AuthToken()))
|
|
c.Request.Header.Add(header.Auth, fmt.Sprintf("%s %s", header.AuthBasic, base64.StdEncoding.EncodeToString(basicAuth)))
|
|
|
|
webdavAuthCache.Flush()
|
|
webdavHandler(c)
|
|
|
|
assert.Equal(t, http.StatusOK, c.Writer.Status())
|
|
assert.Equal(t, "", c.Writer.Header().Get("WWW-Authenticate"))
|
|
})
|
|
t.Run("AliceTokenWebdavWrongUsername", func(t *testing.T) {
|
|
w := httptest.NewRecorder()
|
|
c, _ := gin.CreateTestContext(w)
|
|
c.Request = &http.Request{
|
|
Header: make(http.Header),
|
|
}
|
|
|
|
sess := entity.SessionFixtures.Get("alice_token_webdav")
|
|
basicAuth := []byte(fmt.Sprintf("bob:%s", sess.AuthToken()))
|
|
c.Request.Header.Add(header.Auth, fmt.Sprintf("%s %s", header.AuthBasic, base64.StdEncoding.EncodeToString(basicAuth)))
|
|
|
|
webdavAuthCache.Flush()
|
|
webdavHandler(c)
|
|
|
|
assert.Equal(t, http.StatusUnauthorized, c.Writer.Status())
|
|
assert.Equal(t, BasicAuthRealm, c.Writer.Header().Get("WWW-Authenticate"))
|
|
})
|
|
t.Run("AliceTokenWebdavWithoutUsername", func(t *testing.T) {
|
|
w := httptest.NewRecorder()
|
|
c, _ := gin.CreateTestContext(w)
|
|
c.Request = &http.Request{
|
|
Header: make(http.Header),
|
|
}
|
|
|
|
sess := entity.SessionFixtures.Get("alice_token_webdav")
|
|
basicAuth := []byte(fmt.Sprintf(":%s", sess.AuthToken()))
|
|
c.Request.Header.Add(header.Auth, fmt.Sprintf("%s %s", header.AuthBasic, base64.StdEncoding.EncodeToString(basicAuth)))
|
|
|
|
webdavAuthCache.Flush()
|
|
webdavHandler(c)
|
|
|
|
assert.Equal(t, http.StatusUnauthorized, c.Writer.Status())
|
|
assert.Equal(t, BasicAuthRealm, c.Writer.Header().Get("WWW-Authenticate"))
|
|
})
|
|
t.Run("AliceTokenScope", func(t *testing.T) {
|
|
w := httptest.NewRecorder()
|
|
c, _ := gin.CreateTestContext(w)
|
|
c.Request = &http.Request{
|
|
Header: make(http.Header),
|
|
}
|
|
|
|
sess := entity.SessionFixtures.Get("alice_token_scope")
|
|
header.SetAuthorization(c.Request, sess.AuthToken())
|
|
|
|
webdavAuthCache.Flush()
|
|
webdavHandler(c)
|
|
|
|
assert.Equal(t, http.StatusUnauthorized, c.Writer.Status())
|
|
assert.Equal(t, BasicAuthRealm, c.Writer.Header().Get("WWW-Authenticate"))
|
|
})
|
|
t.Run("InvalidAuthToken", func(t *testing.T) {
|
|
w := httptest.NewRecorder()
|
|
c, _ := gin.CreateTestContext(w)
|
|
c.Request = &http.Request{
|
|
Header: make(http.Header),
|
|
}
|
|
|
|
header.SetAuthorization(c.Request, rnd.AuthToken())
|
|
|
|
webdavAuthCache.Flush()
|
|
webdavHandler(c)
|
|
|
|
assert.Equal(t, http.StatusUnauthorized, c.Writer.Status())
|
|
assert.Equal(t, BasicAuthRealm, c.Writer.Header().Get("WWW-Authenticate"))
|
|
})
|
|
t.Run("InvalidAppPassword", func(t *testing.T) {
|
|
w := httptest.NewRecorder()
|
|
c, _ := gin.CreateTestContext(w)
|
|
c.Request = &http.Request{
|
|
Header: make(http.Header),
|
|
}
|
|
|
|
header.SetAuthorization(c.Request, rnd.AppPassword())
|
|
|
|
webdavAuthCache.Flush()
|
|
webdavHandler(c)
|
|
|
|
assert.Equal(t, http.StatusUnauthorized, c.Writer.Status())
|
|
assert.Equal(t, BasicAuthRealm, c.Writer.Header().Get("WWW-Authenticate"))
|
|
})
|
|
}
|
|
|
|
func TestWebDAVAuthSession(t *testing.T) {
|
|
t.Run("AliceTokenWebdav", func(t *testing.T) {
|
|
w := httptest.NewRecorder()
|
|
c, _ := gin.CreateTestContext(w)
|
|
c.Request = &http.Request{
|
|
Header: make(http.Header),
|
|
}
|
|
|
|
s := entity.SessionFixtures.Get("alice_token_webdav")
|
|
|
|
// Get session with authorized user and webdav scope.
|
|
webdavAuthCache.Flush()
|
|
sess, user, sid, cached := WebDAVAuthSession(c, s.AuthToken())
|
|
|
|
// Check result.
|
|
assert.NotNil(t, sess)
|
|
assert.NotNil(t, user)
|
|
assert.True(t, sess.HasUser())
|
|
assert.Equal(t, user.UserUID, sess.UserUID)
|
|
assert.Equal(t, entity.UserFixtures.Get("alice").UserUID, sess.UserUID)
|
|
assert.True(t, sess.HasScope(acl.ResourceWebDAV.String()))
|
|
assert.False(t, cached)
|
|
|
|
assert.Equal(t, s.ID, sid)
|
|
assert.Equal(t, entity.UserFixtures.Get("alice").UserUID, user.UserUID)
|
|
assert.True(t, user.CanUseWebDAV())
|
|
|
|
// WebDAVAuthSession should not set a status code or any headers.
|
|
assert.Equal(t, http.StatusOK, c.Writer.Status())
|
|
assert.Equal(t, "", c.Writer.Header().Get("WWW-Authenticate"))
|
|
|
|
// Cache authentication.
|
|
webdavAuthCache.SetDefault(sid, user)
|
|
|
|
// Get cached user.
|
|
sess, user, sid, cached = WebDAVAuthSession(c, s.AuthToken())
|
|
|
|
// Check result.
|
|
assert.Nil(t, sess)
|
|
assert.NotNil(t, user)
|
|
assert.True(t, cached)
|
|
|
|
assert.Equal(t, s.ID, sid)
|
|
assert.Equal(t, entity.UserFixtures.Get("alice").UserUID, user.UserUID)
|
|
assert.True(t, user.CanUseWebDAV())
|
|
|
|
// WebDAVAuthSession should not set a status code or any headers.
|
|
assert.Equal(t, http.StatusOK, c.Writer.Status())
|
|
assert.Equal(t, "", c.Writer.Header().Get("WWW-Authenticate"))
|
|
})
|
|
t.Run("AliceTokenScope", func(t *testing.T) {
|
|
w := httptest.NewRecorder()
|
|
c, _ := gin.CreateTestContext(w)
|
|
c.Request = &http.Request{
|
|
Header: make(http.Header),
|
|
}
|
|
|
|
s := entity.SessionFixtures.Get("alice_token_scope")
|
|
|
|
// Get session without sufficient authorization scope.
|
|
sess, user, sid, cached := WebDAVAuthSession(c, s.AuthToken())
|
|
|
|
// Check result.
|
|
assert.NotNil(t, sess)
|
|
assert.NotNil(t, user)
|
|
assert.Equal(t, s.ID, sid)
|
|
assert.False(t, cached)
|
|
assert.True(t, sess.HasUser())
|
|
assert.Equal(t, user.UserUID, sess.UserUID)
|
|
assert.Equal(t, entity.UserFixtures.Get("alice").UserUID, user.UserUID)
|
|
assert.Equal(t, entity.UserFixtures.Get("alice").UserUID, sess.UserUID)
|
|
assert.True(t, user.CanUseWebDAV())
|
|
assert.False(t, sess.HasScope(acl.ResourceWebDAV.String()))
|
|
|
|
// WebDAVAuthSession should not set a status code or any headers.
|
|
assert.Equal(t, http.StatusOK, c.Writer.Status())
|
|
assert.Equal(t, "", c.Writer.Header().Get("WWW-Authenticate"))
|
|
})
|
|
t.Run("InvalidAppPassword", func(t *testing.T) {
|
|
w := httptest.NewRecorder()
|
|
c, _ := gin.CreateTestContext(w)
|
|
c.Request = &http.Request{
|
|
Header: make(http.Header),
|
|
}
|
|
|
|
appPassword := rnd.AppPassword()
|
|
authId := rnd.SessionID(appPassword)
|
|
|
|
// Get session with invalid app password.
|
|
sess, user, sid, cached := WebDAVAuthSession(c, appPassword)
|
|
|
|
// Check result.
|
|
assert.Nil(t, sess)
|
|
assert.Nil(t, user)
|
|
assert.Equal(t, authId, sid)
|
|
assert.False(t, cached)
|
|
|
|
// WebDAVAuthSession should not set a status code or any headers.
|
|
assert.Equal(t, http.StatusOK, c.Writer.Status())
|
|
assert.Equal(t, "", c.Writer.Header().Get("WWW-Authenticate"))
|
|
})
|
|
}
|