1
0
Fork 0
mirror of https://github.com/anyproto/anytype-heart.git synced 2025-06-08 05:47:07 +09:00

GO-5589: Enforce uniqueness of type and property keys

This commit is contained in:
Jannis Metrikat 2025-05-22 00:30:43 +02:00
parent 049b1f4a0d
commit 93c87d21f8
No known key found for this signature in database
GPG key ID: B223CAC5AAF85615
2 changed files with 48 additions and 4 deletions

View file

@ -200,7 +200,15 @@ func (s *Service) CreateProperty(ctx context.Context, spaceId string, request ap
}
if request.Key != "" {
details.Fields[bundle.RelationKeyApiObjectKey.String()] = pbtypes.String(strcase.ToSnake(s.sanitizedString(request.Key)))
apiKey := strcase.ToSnake(s.sanitizedString(request.Key))
propMap, err := s.getPropertyMapFromStore(ctx, spaceId, false)
if err != nil {
return apimodel.Property{}, err
}
if _, exists := propMap[apiKey]; exists {
return apimodel.Property{}, util.ErrBadInput(fmt.Sprintf("property key %q already exists", apiKey))
}
details.Fields[bundle.RelationKeyApiObjectKey.String()] = pbtypes.String(apiKey)
}
resp := s.mw.ObjectCreateRelation(ctx, &pb.RpcObjectCreateRelationRequest{
@ -235,12 +243,20 @@ func (s *Service) UpdateProperty(ctx context.Context, spaceId string, propertyId
})
}
if request.Key != nil {
newKey := strcase.ToSnake(s.sanitizedString(*request.Key))
propMap, err := s.getPropertyMapFromStore(ctx, spaceId, false)
if err != nil {
return apimodel.Property{}, err
}
if existing, exists := propMap[newKey]; exists && existing.Id != propertyId {
return apimodel.Property{}, util.ErrBadInput(fmt.Sprintf("property key %q already exists", newKey))
}
if bundle.HasRelation(domain.RelationKey(prop.RelationKey)) {
return apimodel.Property{}, util.ErrBadInput("property key of bundled properties cannot be changed")
}
detailsToUpdate = append(detailsToUpdate, &model.Detail{
Key: bundle.RelationKeyApiObjectKey.String(),
Value: pbtypes.String(strcase.ToSnake(s.sanitizedString(*request.Key))),
Value: pbtypes.String(newKey),
})
}

View file

@ -3,6 +3,7 @@ package service
import (
"context"
"errors"
"fmt"
"github.com/gogo/protobuf/types"
"github.com/iancoleman/strcase"
@ -119,6 +120,21 @@ func (s *Service) GetType(ctx context.Context, spaceId string, typeId string) (a
// CreateType creates a new type in a specific space.
func (s *Service) CreateType(ctx context.Context, spaceId string, request apimodel.CreateTypeRequest) (apimodel.Type, error) {
if request.Key != "" {
newKey := strcase.ToSnake(s.sanitizedString(request.Key))
propertyMap, err := s.getPropertyMapFromStore(ctx, spaceId, true)
if err != nil {
return apimodel.Type{}, err
}
typeMap, err := s.getTypeMapFromStore(ctx, spaceId, propertyMap, true)
if err != nil {
return apimodel.Type{}, err
}
if _, exists := typeMap[newKey]; exists {
return apimodel.Type{}, util.ErrBadInput(fmt.Sprintf("type key %q already exists", newKey))
}
}
details, err := s.buildTypeDetails(ctx, spaceId, request)
if err != nil {
return apimodel.Type{}, err
@ -267,7 +283,7 @@ func (s *Service) getTypeFromStruct(details *types.Struct, propertyMap map[strin
Archived: details.Fields[bundle.RelationKeyIsArchived.String()].GetBoolValue(),
Layout: s.otLayoutToObjectLayout(model.ObjectTypeLayout(details.Fields[bundle.RelationKeyRecommendedLayout.String()].GetNumberValue())),
Properties: s.getRecommendedPropertiesFromLists(details.Fields[bundle.RelationKeyRecommendedFeaturedRelations.String()].GetListValue(), details.Fields[bundle.RelationKeyRecommendedRelations.String()].GetListValue(), propertyMap),
UniqueKey: uk,
UniqueKey: uk, // internal only for simplified lookup
}
}
@ -353,10 +369,22 @@ func (s *Service) buildUpdatedTypeDetails(ctx context.Context, spaceId string, t
fields[bundle.RelationKeyRecommendedLayout.String()] = pbtypes.Int64(int64(s.typeLayoutToObjectTypeLayout(*request.Layout)))
}
if request.Key != nil {
newKey := strcase.ToSnake(s.sanitizedString(*request.Key))
propertyMap, err := s.getPropertyMapFromStore(ctx, spaceId, true)
if err != nil {
return nil, err
}
typeMap, err := s.getTypeMapFromStore(ctx, spaceId, propertyMap, true)
if err != nil {
return nil, err
}
if existing, exists := typeMap[newKey]; exists && existing.Id != t.Id {
return nil, util.ErrBadInput(fmt.Sprintf("type key %q already exists", newKey))
}
if bundle.HasObjectTypeByKey(domain.TypeKey(util.ToTypeApiKey(t.UniqueKey))) {
return nil, util.ErrBadInput("type key of bundled types cannot be changed")
}
fields[bundle.RelationKeyApiObjectKey.String()] = pbtypes.String(strcase.ToSnake(s.sanitizedString(*request.Key)))
fields[bundle.RelationKeyApiObjectKey.String()] = pbtypes.String(newKey)
}
if request.Icon != nil {