Adjust + Test

This commit is contained in:
mr
2026-02-18 12:24:19 +01:00
parent 842e09f22f
commit fa5c3a3c60
45 changed files with 1166 additions and 1192 deletions

View File

@@ -1,7 +1,10 @@
package utils
import (
"crypto/sha256"
"encoding/json"
"errors"
"slices"
"time"
"cloud.o-forge.io/core/oc-lib/dbs"
@@ -37,20 +40,43 @@ type AbstractObject struct {
UpdaterID string `json:"updater_id,omitempty" bson:"updater_id,omitempty"`
UserUpdaterID string `json:"user_updater_id,omitempty" bson:"user_updater_id,omitempty"`
AccessMode AccessMode `json:"access_mode" bson:"access_mode" default:"0"`
Signature []byte `bson:"signature,omitempty" json:"signature,omitempty"`
}
func (ri *AbstractObject) GetAccessor(request *tools.APIRequest) Accessor {
return nil
}
func (r *AbstractObject) Unsign() {}
func (r *AbstractObject) Unsign() {
r.Signature = nil
}
func (r *AbstractObject) Sign() {}
func (r *AbstractObject) Sign() {
priv, err := tools.LoadKeyFromFilePrivate() // your node private key
if err != nil {
return
}
b, _ := json.Marshal(r.DeepCopy())
hash := sha256.Sum256(b)
r.Signature, err = priv.Sign(hash[:])
}
func (r *AbstractObject) SetID(id string) {
r.UUID = id
}
func (r *AbstractObject) DeepCopy() *AbstractObject {
var obj AbstractObject
b, err := json.Marshal(r)
if err != nil {
return nil
}
if err := json.Unmarshal(b, &obj); err != nil {
return nil
}
return &obj
}
func (r *AbstractObject) SetName(name string) {
r.Name = name
}
@@ -82,6 +108,10 @@ func (ao AbstractObject) GetID() string {
return ao.UUID
}
func (ao AbstractObject) GetSignature() []byte {
return ao.Signature
}
// GetName implements ShallowDBObject.
func (ao AbstractObject) GetName() string {
return ao.Name
@@ -103,7 +133,7 @@ func (ao *AbstractObject) UpToDate(user string, peer string, create bool) {
}
func (ao *AbstractObject) VerifyAuth(callName string, request *tools.APIRequest) bool {
return (ao.AccessMode == Public && callName == "get") || request.Admin || (request != nil && ao.CreatorID == request.PeerID && request.PeerID != "")
return (ao.AccessMode == Public && callName == "get") || (request != nil && (request.Admin || (ao.CreatorID == request.PeerID && request.PeerID != "")))
}
// TODO : check write per auth
@@ -137,50 +167,104 @@ func (dma *AbstractObject) Serialize(obj DBObject) map[string]interface{} {
return m
}
type AbstractAccessor struct {
type AbstractAccessor[T DBObject] struct {
Logger zerolog.Logger // Logger is the logger of the accessor, it's a specilized logger for the accessor
Type tools.DataType // Type is the data type of the accessor
Request *tools.APIRequest // Caller is the http caller of the accessor (optionnal) only need in a peer connection
ResourceModelAccessor Accessor
New func() T
NotImplemented []string
}
func (r *AbstractAccessor) ShouldVerifyAuth() bool {
func (r *AbstractAccessor[T]) ShouldVerifyAuth() bool {
return true
}
func (r *AbstractAccessor) GetRequest() *tools.APIRequest {
func (r *AbstractAccessor[T]) GetRequest() *tools.APIRequest {
return r.Request
}
func (dma *AbstractAccessor) GetUser() string {
func (dma *AbstractAccessor[T]) GetUser() string {
if dma.Request == nil {
return ""
}
return dma.Request.Username
}
func (dma *AbstractAccessor) GetPeerID() string {
func (dma *AbstractAccessor[T]) GetPeerID() string {
if dma.Request == nil {
return ""
}
return dma.Request.PeerID
}
func (dma *AbstractAccessor) GetGroups() []string {
func (dma *AbstractAccessor[T]) GetGroups() []string {
if dma.Request == nil {
return []string{}
}
return dma.Request.Groups
}
func (dma *AbstractAccessor) GetLogger() *zerolog.Logger {
func (dma *AbstractAccessor[T]) GetLogger() *zerolog.Logger {
return &dma.Logger
}
func (dma *AbstractAccessor) GetType() tools.DataType {
func (dma *AbstractAccessor[T]) GetType() tools.DataType {
return dma.Type
}
func (dma *AbstractAccessor) GetCaller() *tools.HTTPCaller {
func (dma *AbstractAccessor[T]) GetCaller() *tools.HTTPCaller {
if dma.Request == nil {
return nil
}
return dma.Request.Caller
}
/*
* Nothing special here, just the basic CRUD operations
*/
func (a *AbstractAccessor[T]) DeleteOne(id string) (DBObject, int, error) {
if len(a.NotImplemented) > 0 && slices.Contains(a.NotImplemented, "DeleteOne") {
return nil, 404, errors.New("not implemented")
}
return GenericDeleteOne(id, a)
}
func (a *AbstractAccessor[T]) UpdateOne(set DBObject, id string) (DBObject, int, error) {
if len(a.NotImplemented) > 0 && slices.Contains(a.NotImplemented, "UpdateOne") {
return nil, 404, errors.New("not implemented")
}
// should verify if a source is existing...
return GenericUpdateOne(set, id, a, a.New())
}
func (a *AbstractAccessor[T]) StoreOne(data DBObject) (DBObject, int, error) {
if len(a.NotImplemented) > 0 && slices.Contains(a.NotImplemented, "StoreOne") {
return nil, 404, errors.New("not implemented")
}
return GenericStoreOne(data.(T), a)
}
func (a *AbstractAccessor[T]) CopyOne(data DBObject) (DBObject, int, error) {
if len(a.NotImplemented) > 0 && slices.Contains(a.NotImplemented, "CopyOne") {
return nil, 404, errors.New("not implemented")
}
return GenericStoreOne(data.(T), a)
}
func (a *AbstractAccessor[T]) LoadOne(id string) (DBObject, int, error) {
return GenericLoadOne[T](id, func(d DBObject) (DBObject, int, error) {
return d, 200, nil
}, a)
}
func (a *AbstractAccessor[T]) LoadAll(isDraft bool) ([]ShallowDBObject, int, error) {
return GenericLoadAll[T](a.GetExec(isDraft), isDraft, a)
}
func (a *AbstractAccessor[T]) Search(filters *dbs.Filters, search string, isDraft bool) ([]ShallowDBObject, int, error) {
return GenericSearch[T](filters, search, a.New().GetObjectFilters(search), a.GetExec(isDraft), isDraft, a)
}
func (a *AbstractAccessor[T]) GetExec(isDraft bool) func(DBObject) ShallowDBObject {
return func(d DBObject) ShallowDBObject {
return d
}
}

View File

@@ -34,6 +34,8 @@ func GenericStoreOne(data DBObject, a Accessor) (DBObject, int, error) {
data.SetID(data.GetID())
data.StoreDraftDefault()
data.UpToDate(a.GetUser(), a.GetPeerID(), true)
data.Unsign()
data.Sign()
f := dbs.Filters{
Or: map[string][]dbs.Filter{
"abstractresource.abstractobject.name": {{
@@ -97,6 +99,8 @@ func GenericUpdateOne(set DBObject, id string, a Accessor, new DBObject) (DBObje
}
set = newSet
r.UpToDate(a.GetUser(), a.GetPeerID(), false)
r.Unsign()
r.Sign()
if a.ShouldVerifyAuth() && !r.VerifyAuth("update", a.GetRequest()) {
return nil, 403, errors.New("you are not allowed to access :" + a.GetType().String())
}

View File

@@ -34,6 +34,8 @@ type DBObject interface {
Deserialize(j map[string]interface{}, obj DBObject) DBObject
Sign()
Unsign()
GetSignature() []byte
GetObjectFilters(search string) *dbs.Filters
}
// Accessor is an interface that defines the basic methods for an Accessor
@@ -53,4 +55,5 @@ type Accessor interface {
LoadAll(isDraft bool) ([]ShallowDBObject, int, error)
UpdateOne(set DBObject, id string) (DBObject, int, error)
Search(filters *dbs.Filters, search string, isDraft bool) ([]ShallowDBObject, int, error)
GetExec(isDraft bool) func(DBObject) ShallowDBObject
}

View File

@@ -1,128 +1,263 @@
package models_test
package utils_test
import (
"testing"
"time"
"cloud.o-forge.io/core/oc-lib/dbs"
"cloud.o-forge.io/core/oc-lib/models/utils"
"cloud.o-forge.io/core/oc-lib/tools"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
)
func TestGenerateID(t *testing.T) {
ao := &utils.AbstractObject{}
ao.GenerateID()
assert.NotEmpty(t, ao.UUID)
_, err := uuid.Parse(ao.UUID)
assert.NoError(t, err)
// ---- AbstractObject ----
func TestAbstractObject_GetID(t *testing.T) {
obj := &utils.AbstractObject{UUID: "abc-123"}
assert.Equal(t, "abc-123", obj.GetID())
}
func TestStoreDraftDefault(t *testing.T) {
ao := &utils.AbstractObject{IsDraft: true}
ao.StoreDraftDefault()
assert.False(t, ao.IsDraft)
func TestAbstractObject_GetName(t *testing.T) {
obj := &utils.AbstractObject{Name: "test-name"}
assert.Equal(t, "test-name", obj.GetName())
}
func TestCanUpdate(t *testing.T) {
ao := &utils.AbstractObject{}
res, set := ao.CanUpdate(nil)
assert.True(t, res)
assert.Nil(t, set)
func TestAbstractObject_GetCreatorID(t *testing.T) {
obj := &utils.AbstractObject{CreatorID: "peer-xyz"}
assert.Equal(t, "peer-xyz", obj.GetCreatorID())
}
func TestCanDelete(t *testing.T) {
ao := &utils.AbstractObject{}
assert.True(t, ao.CanDelete())
func TestAbstractObject_SetID(t *testing.T) {
obj := &utils.AbstractObject{}
obj.SetID("new-id")
assert.Equal(t, "new-id", obj.UUID)
}
func TestIsDrafted(t *testing.T) {
ao := &utils.AbstractObject{IsDraft: true}
assert.True(t, ao.IsDrafted())
func TestAbstractObject_SetName(t *testing.T) {
obj := &utils.AbstractObject{}
obj.SetName("hello")
assert.Equal(t, "hello", obj.Name)
}
func TestGetID(t *testing.T) {
u := uuid.New().String()
ao := &utils.AbstractObject{UUID: u}
assert.Equal(t, u, ao.GetID())
func TestAbstractObject_GenerateID_WhenEmpty(t *testing.T) {
obj := &utils.AbstractObject{}
obj.GenerateID()
assert.NotEmpty(t, obj.UUID)
}
func TestGetName(t *testing.T) {
name := "MyObject"
ao := &utils.AbstractObject{Name: name}
assert.Equal(t, name, ao.GetName())
func TestAbstractObject_GenerateID_KeepsExisting(t *testing.T) {
obj := &utils.AbstractObject{UUID: "existing-id"}
obj.GenerateID()
assert.Equal(t, "existing-id", obj.UUID)
}
func TestGetCreatorID(t *testing.T) {
id := "creator-123"
ao := &utils.AbstractObject{CreatorID: id}
assert.Equal(t, id, ao.GetCreatorID())
func TestAbstractObject_StoreDraftDefault(t *testing.T) {
obj := &utils.AbstractObject{IsDraft: true}
obj.StoreDraftDefault()
assert.False(t, obj.IsDraft)
}
func TestUpToDate_CreateFalse(t *testing.T) {
ao := &utils.AbstractObject{}
now := time.Now()
time.Sleep(time.Millisecond) // ensure time difference
ao.UpToDate("user123", "peer456", false)
assert.WithinDuration(t, now, ao.UpdateDate, time.Second)
assert.Equal(t, "peer456", ao.UpdaterID)
assert.Equal(t, "user123", ao.UserUpdaterID)
assert.True(t, ao.CreationDate.IsZero())
func TestAbstractObject_IsDrafted(t *testing.T) {
obj := &utils.AbstractObject{IsDraft: true}
assert.True(t, obj.IsDrafted())
obj.IsDraft = false
assert.False(t, obj.IsDrafted())
}
func TestUpToDate_CreateTrue(t *testing.T) {
ao := &utils.AbstractObject{}
now := time.Now()
time.Sleep(time.Millisecond)
ao.UpToDate("user123", "peer456", true)
assert.WithinDuration(t, now, ao.UpdateDate, time.Second)
assert.WithinDuration(t, now, ao.CreationDate, time.Second)
assert.Equal(t, "peer456", ao.UpdaterID)
assert.Equal(t, "peer456", ao.CreatorID)
assert.Equal(t, "user123", ao.UserUpdaterID)
assert.Equal(t, "user123", ao.UserCreatorID)
func TestAbstractObject_CanDelete(t *testing.T) {
obj := &utils.AbstractObject{}
assert.True(t, obj.CanDelete())
}
func TestVerifyAuth(t *testing.T) {
request := &tools.APIRequest{PeerID: "peer123"}
ao := &utils.AbstractObject{CreatorID: "peer123"}
assert.True(t, ao.VerifyAuth("get", request))
ao = &utils.AbstractObject{AccessMode: utils.Public}
assert.True(t, ao.VerifyAuth("get", nil))
ao = &utils.AbstractObject{AccessMode: utils.Private, CreatorID: "peer123"}
request = &tools.APIRequest{PeerID: "wrong"}
assert.False(t, ao.VerifyAuth("get", request))
func TestAbstractObject_CanUpdate(t *testing.T) {
obj := &utils.AbstractObject{UUID: "id-1"}
other := &utils.AbstractObject{UUID: "id-2"}
ok, returned := obj.CanUpdate(other)
assert.True(t, ok)
assert.Equal(t, other, returned)
}
func TestGetObjectFilters(t *testing.T) {
ao := &utils.AbstractObject{}
f := ao.GetObjectFilters("*")
func TestAbstractObject_Unsign(t *testing.T) {
obj := &utils.AbstractObject{Signature: []byte("sig")}
obj.Unsign()
assert.Nil(t, obj.Signature)
}
func TestAbstractObject_GetSignature(t *testing.T) {
obj := &utils.AbstractObject{Signature: []byte("sig")}
assert.Equal(t, []byte("sig"), obj.GetSignature())
}
func TestAbstractObject_DeepCopy(t *testing.T) {
obj := &utils.AbstractObject{UUID: "id-1", Name: "original"}
copy := obj.DeepCopy()
assert.NotNil(t, copy)
assert.Equal(t, obj.UUID, copy.UUID)
assert.Equal(t, obj.Name, copy.Name)
// Mutating the copy should not affect the original
copy.Name = "modified"
assert.Equal(t, "original", obj.Name)
}
func TestAbstractObject_UpToDate_Create(t *testing.T) {
obj := &utils.AbstractObject{CreatorID: ""}
obj.UpToDate("user1", "peer1", true)
assert.Equal(t, "peer1", obj.UpdaterID)
assert.Equal(t, "user1", obj.UserUpdaterID)
// CreatorID was empty so create branch is skipped
assert.Empty(t, obj.CreatorID)
}
func TestAbstractObject_UpToDate_CreateWithExistingCreator(t *testing.T) {
obj := &utils.AbstractObject{CreatorID: "existing-peer"}
obj.UpToDate("user1", "peer1", true)
assert.Equal(t, "peer1", obj.CreatorID)
assert.Equal(t, "user1", obj.UserCreatorID)
}
func TestAbstractObject_UpToDate_Update(t *testing.T) {
obj := &utils.AbstractObject{CreatorID: "original-peer"}
obj.UpToDate("user2", "peer2", false)
assert.Equal(t, "peer2", obj.UpdaterID)
assert.Equal(t, "original-peer", obj.CreatorID) // unchanged
}
// ---- VerifyAuth ----
func TestAbstractObject_VerifyAuth_NilRequest_GetPublic(t *testing.T) {
obj := &utils.AbstractObject{AccessMode: 1} // Public = 1
assert.True(t, obj.VerifyAuth("get", nil))
}
func TestAbstractObject_VerifyAuth_NilRequest_DeletePublic(t *testing.T) {
obj := &utils.AbstractObject{AccessMode: 1} // Public = 1
// non-"get" call with nil request → false
assert.False(t, obj.VerifyAuth("delete", nil))
}
func TestAbstractObject_VerifyAuth_NilRequest_Private(t *testing.T) {
obj := &utils.AbstractObject{AccessMode: 0} // Private
assert.False(t, obj.VerifyAuth("get", nil))
}
func TestAbstractObject_VerifyAuth_AdminRequest(t *testing.T) {
obj := &utils.AbstractObject{}
req := &tools.APIRequest{Admin: true}
assert.True(t, obj.VerifyAuth("get", req))
assert.True(t, obj.VerifyAuth("delete", req))
}
func TestAbstractObject_VerifyAuth_MatchingPeerID(t *testing.T) {
obj := &utils.AbstractObject{CreatorID: "peer-abc"}
req := &tools.APIRequest{PeerID: "peer-abc"}
assert.True(t, obj.VerifyAuth("get", req))
}
func TestAbstractObject_VerifyAuth_MismatchedPeerID(t *testing.T) {
obj := &utils.AbstractObject{CreatorID: "peer-abc"}
req := &tools.APIRequest{PeerID: "peer-xyz"}
assert.False(t, obj.VerifyAuth("get", req))
}
func TestAbstractObject_VerifyAuth_EmptyPeerID(t *testing.T) {
obj := &utils.AbstractObject{CreatorID: ""}
req := &tools.APIRequest{PeerID: ""}
// both empty → condition `ao.CreatorID == request.PeerID && request.PeerID != ""` is false
assert.False(t, obj.VerifyAuth("get", req))
}
// ---- GetObjectFilters ----
func TestAbstractObject_GetObjectFilters_Star(t *testing.T) {
obj := &utils.AbstractObject{}
f := obj.GetObjectFilters("*")
assert.NotNil(t, f)
assert.Contains(t, f.Or, "abstractobject.name")
assert.Equal(t, dbs.LIKE.String(), f.Or["abstractobject.name"][0].Operator)
}
func TestDeserialize(t *testing.T) {
ao := &utils.AbstractObject{}
input := map[string]interface{}{"name": "test", "id": uuid.New().String()}
res := ao.Deserialize(input, &utils.AbstractObject{})
assert.NotNil(t, res)
func TestAbstractObject_GetObjectFilters_Search(t *testing.T) {
obj := &utils.AbstractObject{}
f := obj.GetObjectFilters("my-search")
assert.NotNil(t, f)
}
func TestSerialize(t *testing.T) {
ao := &utils.AbstractObject{Name: "test", UUID: uuid.New().String()}
m := ao.Serialize(ao)
assert.Equal(t, "test", m["name"])
// ---- Serialize / Deserialize ----
func TestAbstractObject_SerializeDeserialize(t *testing.T) {
obj := &utils.AbstractObject{UUID: "serial-id", Name: "serial-name"}
m := obj.Serialize(obj)
assert.NotNil(t, m)
dst := &utils.AbstractObject{}
result := obj.Deserialize(m, dst)
assert.NotNil(t, result)
assert.Equal(t, "serial-id", result.GetID())
}
func TestAbstractAccessorMethods(t *testing.T) {
r := &utils.AbstractAccessor{Request: &tools.APIRequest{Username: "alice", PeerID: "peer1", Groups: []string{"dev"}}}
assert.True(t, r.ShouldVerifyAuth())
assert.Equal(t, "alice", r.GetUser())
assert.Equal(t, "peer1", r.GetPeerID())
assert.Equal(t, []string{"dev"}, r.GetGroups())
assert.Equal(t, r.Request.Caller, r.GetCaller())
// ---- GetAccessor ----
func TestAbstractObject_GetAccessor_ReturnsNil(t *testing.T) {
obj := &utils.AbstractObject{}
acc := obj.GetAccessor(nil)
assert.Nil(t, acc)
}
// ---- AbstractAccessor ----
func TestAbstractAccessor_GetUser_NilRequest(t *testing.T) {
acc := &utils.AbstractAccessor[*utils.AbstractObject]{Request: nil}
assert.Equal(t, "", acc.GetUser())
}
func TestAbstractAccessor_GetUser_WithRequest(t *testing.T) {
acc := &utils.AbstractAccessor[*utils.AbstractObject]{
Request: &tools.APIRequest{Username: "alice"},
}
assert.Equal(t, "alice", acc.GetUser())
}
func TestAbstractAccessor_GetPeerID_NilRequest(t *testing.T) {
acc := &utils.AbstractAccessor[*utils.AbstractObject]{Request: nil}
assert.Equal(t, "", acc.GetPeerID())
}
func TestAbstractAccessor_GetPeerID_WithRequest(t *testing.T) {
acc := &utils.AbstractAccessor[*utils.AbstractObject]{
Request: &tools.APIRequest{PeerID: "peer-42"},
}
assert.Equal(t, "peer-42", acc.GetPeerID())
}
func TestAbstractAccessor_GetGroups_NilRequest(t *testing.T) {
acc := &utils.AbstractAccessor[*utils.AbstractObject]{Request: nil}
assert.Equal(t, []string{}, acc.GetGroups())
}
func TestAbstractAccessor_GetGroups_WithRequest(t *testing.T) {
acc := &utils.AbstractAccessor[*utils.AbstractObject]{
Request: &tools.APIRequest{Groups: []string{"g1", "g2"}},
}
assert.Equal(t, []string{"g1", "g2"}, acc.GetGroups())
}
func TestAbstractAccessor_ShouldVerifyAuth(t *testing.T) {
acc := &utils.AbstractAccessor[*utils.AbstractObject]{}
assert.True(t, acc.ShouldVerifyAuth())
}
func TestAbstractAccessor_GetType(t *testing.T) {
acc := &utils.AbstractAccessor[*utils.AbstractObject]{
Type: tools.WORKFLOW,
}
assert.Equal(t, tools.WORKFLOW, acc.GetType())
}
func TestAbstractAccessor_GetRequest(t *testing.T) {
req := &tools.APIRequest{Admin: true}
acc := &utils.AbstractAccessor[*utils.AbstractObject]{Request: req}
assert.Equal(t, req, acc.GetRequest())
}
func TestAbstractAccessor_GetCaller_NilRequest(t *testing.T) {
acc := &utils.AbstractAccessor[*utils.AbstractObject]{Request: nil}
assert.Nil(t, acc.GetCaller())
}

View File

@@ -1,168 +0,0 @@
package models_test
import (
"errors"
"testing"
"cloud.o-forge.io/core/oc-lib/dbs"
"cloud.o-forge.io/core/oc-lib/models/utils"
"cloud.o-forge.io/core/oc-lib/tools"
"github.com/rs/zerolog"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
// --- Mock Definitions ---
type MockDBObject struct {
mock.Mock
}
func (m *MockAccessor) GetLogger() *zerolog.Logger {
return nil
}
func (m *MockAccessor) GetGroups() []string {
return []string{}
}
func (m *MockAccessor) GetCaller() *tools.HTTPCaller {
return nil
}
func (m *MockDBObject) GenerateID() { m.Called() }
func (m *MockDBObject) StoreDraftDefault() { m.Called() }
func (m *MockDBObject) UpToDate(user, peer string, create bool) {
m.Called(user, peer, create)
}
func (m *MockDBObject) VerifyAuth(req *tools.APIRequest) bool {
args := m.Called(req)
return args.Bool(0)
}
func (m *MockDBObject) CanDelete() bool {
args := m.Called()
return args.Bool(0)
}
func (m *MockDBObject) CanUpdate(set utils.DBObject) (bool, utils.DBObject) {
args := m.Called(set)
return args.Bool(0), args.Get(1).(utils.DBObject)
}
func (m *MockDBObject) IsDrafted() bool {
args := m.Called()
return args.Bool(0)
}
func (m *MockDBObject) Serialize(obj utils.DBObject) map[string]interface{} {
args := m.Called(obj)
return args.Get(0).(map[string]interface{})
}
func (m *MockDBObject) Deserialize(mdata map[string]interface{}, obj utils.DBObject) utils.DBObject {
args := m.Called(mdata, obj)
return args.Get(0).(utils.DBObject)
}
func (m *MockDBObject) GetID() string {
args := m.Called()
return args.String(0)
}
func (m *MockDBObject) GetName() string {
args := m.Called()
return args.String(0)
}
type MockAccessor struct {
mock.Mock
}
func (m *MockAccessor) DeleteOne(id string) (utils.DBObject, int, error) {
args := m.Called(id)
return args.Get(0).(utils.DBObject), args.Int(1), args.Error(2)
}
func (m *MockAccessor) LoadOne(id string) (utils.DBObject, int, error) {
args := m.Called(id)
return args.Get(0).(utils.DBObject), args.Int(1), args.Error(2)
}
func (m *MockAccessor) LoadAll(isDraft bool) ([]utils.ShallowDBObject, int, error) {
args := m.Called(isDraft)
return args.Get(0).([]utils.ShallowDBObject), args.Int(1), args.Error(2)
}
func (m *MockAccessor) UpdateOne(set utils.DBObject, id string) (utils.DBObject, int, error) {
args := m.Called(set, id)
return args.Get(0).(utils.DBObject), args.Int(1), args.Error(2)
}
func (m *MockAccessor) CopyOne(data utils.DBObject) (utils.DBObject, int, error) {
args := m.Called(data)
return args.Get(0).(utils.DBObject), args.Int(1), args.Error(2)
}
func (m *MockAccessor) StoreOne(data utils.DBObject) (utils.DBObject, int, error) {
args := m.Called(data)
return args.Get(0).(utils.DBObject), args.Int(1), args.Error(2)
}
func (m *MockAccessor) ShouldVerifyAuth() bool {
args := m.Called()
return args.Bool(0)
}
func (m *MockAccessor) GetRequest() *tools.APIRequest {
args := m.Called()
return args.Get(0).(*tools.APIRequest)
}
func (m *MockAccessor) GetType() tools.DataType {
args := m.Called()
return args.Get(0).(tools.DataType)
}
func (m *MockAccessor) Search(filters *dbs.Filters, s string, d bool) ([]utils.ShallowDBObject, int, error) {
args := m.Called(filters, s, d)
return args.Get(0).([]utils.ShallowDBObject), args.Int(1), args.Error(2)
}
func (m *MockAccessor) GetUser() string {
args := m.Called()
return args.String(0)
}
func (m *MockAccessor) GetPeerID() string {
args := m.Called()
return args.String(0)
}
// --- Test Cases ---
func TestVerifyAccess_Authorized(t *testing.T) {
mockObj := new(MockDBObject)
mockAcc := new(MockAccessor)
req := &tools.APIRequest{PeerID: "peer"}
mockAcc.On("LoadOne", "123").Return(mockObj, 200, nil)
mockAcc.On("ShouldVerifyAuth").Return(true)
mockObj.On("VerifyAuth", req).Return(true)
mockAcc.On("GetRequest").Return(req)
err := utils.VerifyAccess(mockAcc, "123")
assert.NoError(t, err)
}
func TestVerifyAccess_Unauthorized(t *testing.T) {
mockObj := new(MockDBObject)
mockAcc := new(MockAccessor)
req := &tools.APIRequest{PeerID: "peer"}
mockAcc.On("LoadOne", "123").Return(mockObj, 200, nil)
mockAcc.On("ShouldVerifyAuth").Return(true)
mockObj.On("VerifyAuth", req).Return(false)
mockAcc.On("GetRequest").Return(req)
err := utils.VerifyAccess(mockAcc, "123")
assert.Error(t, err)
assert.Contains(t, err.Error(), "not allowed")
}
func TestVerifyAccess_LoadError(t *testing.T) {
mockAcc := new(MockAccessor)
mockAcc.On("LoadOne", "bad-id").Return(nil, 404, errors.New("not found"))
err := utils.VerifyAccess(mockAcc, "bad-id")
assert.Error(t, err)
assert.Equal(t, "not found", err.Error())
}