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

GO-4459: Add endpoint to delete object

This commit is contained in:
Jannis Metrikat 2025-01-09 00:17:58 +01:00
parent a9eb7259a1
commit d8c8ce4b00
No known key found for this signature in database
GPG key ID: B223CAC5AAF85615
8 changed files with 242 additions and 68 deletions

View file

@ -66,6 +66,7 @@ func main() {
// objects
// {"GET", "/spaces/{space_id}/objects?limit={limit}&offset={offset}", map[string]interface{}{"space_id": testSpaceId, "limit": 100, "offset": 0}, nil},
// {"GET", "/spaces/{space_id}/objects/{object_id}", map[string]interface{}{"space_id": testSpaceId, "object_id": testObjectId}, nil},
// {"DELETE", "/spaces/{space_id}/objects/{object_id}", map[string]interface{}{"space_id": "asd", "object_id": "asd"}, nil},
// {"POST", "/spaces/{space_id}/objects", map[string]interface{}{"space_id": testSpaceId}, map[string]interface{}{"name": "New Object from demo", "icon": "💥", "template_id": "", "object_type_unique_key": "ot-page", "with_chat": false}},
// {"PUT", "/spaces/{space_id}/objects/{object_id}", map[string]interface{}{"space_id": testSpaceId, "object_id": testObjectId}, map[string]interface{}{"name": "Updated Object"}},
// {"GET", "/spaces/{space_id}/object_types?limit={limit}&offset={offset}", map[string]interface{}{"space_id": testSpaceId, "limit": 100, "offset": 0}, nil},

View file

@ -588,7 +588,7 @@ const docTemplate = `{
"200": {
"description": "The created object",
"schema": {
"$ref": "#/definitions/object.CreateObjectResponse"
"$ref": "#/definitions/object.ObjectResponse"
}
},
"400": {
@ -644,7 +644,7 @@ const docTemplate = `{
"200": {
"description": "The requested object",
"schema": {
"$ref": "#/definitions/object.Object"
"$ref": "#/definitions/object.ObjectResponse"
}
},
"403": {
@ -707,7 +707,7 @@ const docTemplate = `{
"200": {
"description": "The updated object",
"schema": {
"$ref": "#/definitions/object.UpdateObjectResponse"
"$ref": "#/definitions/object.ObjectResponse"
}
},
"400": {
@ -735,6 +735,60 @@ const docTemplate = `{
}
}
}
},
"delete": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"objects"
],
"summary": "Delete a specific object in a space",
"parameters": [
{
"type": "string",
"description": "The ID of the space",
"name": "space_id",
"in": "path",
"required": true
},
{
"type": "string",
"description": "The ID of the object",
"name": "object_id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "The deleted object",
"schema": {
"$ref": "#/definitions/object.ObjectResponse"
}
},
"403": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/util.UnauthorizedError"
}
},
"404": {
"description": "Resource not found",
"schema": {
"$ref": "#/definitions/util.NotFoundError"
}
},
"502": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/util.ServerError"
}
}
}
}
},
"/spaces/{space_id}/objects/{object_id}/export/{format}": {
@ -867,14 +921,6 @@ const docTemplate = `{
}
}
},
"object.CreateObjectResponse": {
"type": "object",
"properties": {
"object": {
"$ref": "#/definitions/object.Object"
}
}
},
"object.Detail": {
"type": "object",
"properties": {
@ -967,6 +1013,14 @@ const docTemplate = `{
}
}
},
"object.ObjectResponse": {
"type": "object",
"properties": {
"object": {
"$ref": "#/definitions/object.Object"
}
}
},
"object.ObjectTemplate": {
"type": "object",
"properties": {
@ -1033,14 +1087,6 @@ const docTemplate = `{
}
}
},
"object.UpdateObjectResponse": {
"type": "object",
"properties": {
"object": {
"$ref": "#/definitions/object.Object"
}
}
},
"pagination.PaginatedResponse-space_Member": {
"type": "object",
"properties": {

View file

@ -582,7 +582,7 @@
"200": {
"description": "The created object",
"schema": {
"$ref": "#/definitions/object.CreateObjectResponse"
"$ref": "#/definitions/object.ObjectResponse"
}
},
"400": {
@ -638,7 +638,7 @@
"200": {
"description": "The requested object",
"schema": {
"$ref": "#/definitions/object.Object"
"$ref": "#/definitions/object.ObjectResponse"
}
},
"403": {
@ -701,7 +701,7 @@
"200": {
"description": "The updated object",
"schema": {
"$ref": "#/definitions/object.UpdateObjectResponse"
"$ref": "#/definitions/object.ObjectResponse"
}
},
"400": {
@ -729,6 +729,60 @@
}
}
}
},
"delete": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"objects"
],
"summary": "Delete a specific object in a space",
"parameters": [
{
"type": "string",
"description": "The ID of the space",
"name": "space_id",
"in": "path",
"required": true
},
{
"type": "string",
"description": "The ID of the object",
"name": "object_id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "The deleted object",
"schema": {
"$ref": "#/definitions/object.ObjectResponse"
}
},
"403": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/util.UnauthorizedError"
}
},
"404": {
"description": "Resource not found",
"schema": {
"$ref": "#/definitions/util.NotFoundError"
}
},
"502": {
"description": "Internal server error",
"schema": {
"$ref": "#/definitions/util.ServerError"
}
}
}
}
},
"/spaces/{space_id}/objects/{object_id}/export/{format}": {
@ -861,14 +915,6 @@
}
}
},
"object.CreateObjectResponse": {
"type": "object",
"properties": {
"object": {
"$ref": "#/definitions/object.Object"
}
}
},
"object.Detail": {
"type": "object",
"properties": {
@ -961,6 +1007,14 @@
}
}
},
"object.ObjectResponse": {
"type": "object",
"properties": {
"object": {
"$ref": "#/definitions/object.Object"
}
}
},
"object.ObjectTemplate": {
"type": "object",
"properties": {
@ -1027,14 +1081,6 @@
}
}
},
"object.UpdateObjectResponse": {
"type": "object",
"properties": {
"object": {
"$ref": "#/definitions/object.Object"
}
}
},
"pagination.PaginatedResponse-space_Member": {
"type": "object",
"properties": {

View file

@ -39,11 +39,6 @@ definitions:
vertical_align:
type: string
type: object
object.CreateObjectResponse:
properties:
object:
$ref: '#/definitions/object.Object'
type: object
object.Detail:
properties:
details:
@ -107,6 +102,11 @@ definitions:
example: object
type: string
type: object
object.ObjectResponse:
properties:
object:
$ref: '#/definitions/object.Object'
type: object
object.ObjectTemplate:
properties:
icon:
@ -153,11 +153,6 @@ definitions:
text:
type: string
type: object
object.UpdateObjectResponse:
properties:
object:
$ref: '#/definitions/object.Object'
type: object
pagination.PaginatedResponse-space_Member:
properties:
data:
@ -712,7 +707,7 @@ paths:
"200":
description: The created object
schema:
$ref: '#/definitions/object.CreateObjectResponse'
$ref: '#/definitions/object.ObjectResponse'
"400":
description: Bad request
schema:
@ -729,6 +724,42 @@ paths:
tags:
- objects
/spaces/{space_id}/objects/{object_id}:
delete:
consumes:
- application/json
parameters:
- description: The ID of the space
in: path
name: space_id
required: true
type: string
- description: The ID of the object
in: path
name: object_id
required: true
type: string
produces:
- application/json
responses:
"200":
description: The deleted object
schema:
$ref: '#/definitions/object.ObjectResponse'
"403":
description: Unauthorized
schema:
$ref: '#/definitions/util.UnauthorizedError'
"404":
description: Resource not found
schema:
$ref: '#/definitions/util.NotFoundError'
"502":
description: Internal server error
schema:
$ref: '#/definitions/util.ServerError'
summary: Delete a specific object in a space
tags:
- objects
get:
consumes:
- application/json
@ -749,7 +780,7 @@ paths:
"200":
description: The requested object
schema:
$ref: '#/definitions/object.Object'
$ref: '#/definitions/object.ObjectResponse'
"403":
description: Unauthorized
schema:
@ -791,7 +822,7 @@ paths:
"200":
description: The updated object
schema:
$ref: '#/definitions/object.UpdateObjectResponse'
$ref: '#/definitions/object.ObjectResponse'
"400":
description: Bad request
schema:

View file

@ -55,7 +55,7 @@ func GetObjectsHandler(s *ObjectService) gin.HandlerFunc {
// @Produce json
// @Param space_id path string true "The ID of the space"
// @Param object_id path string true "The ID of the object"
// @Success 200 {object} Object "The requested object"
// @Success 200 {object} ObjectResponse "The requested object"
// @Failure 403 {object} util.UnauthorizedError "Unauthorized"
// @Failure 404 {object} util.NotFoundError "Resource not found"
// @Failure 502 {object} util.ServerError "Internal server error"
@ -77,7 +77,42 @@ func GetObjectHandler(s *ObjectService) gin.HandlerFunc {
return
}
c.JSON(http.StatusOK, GetObjectResponse{Object: object})
c.JSON(http.StatusOK, ObjectResponse{Object: object})
}
}
// DeleteObjectHandler deletes a specific object in a space
//
// @Summary Delete a specific object in a space
// @Tags objects
// @Accept json
// @Produce json
// @Param space_id path string true "The ID of the space"
// @Param object_id path string true "The ID of the object"
// @Success 200 {object} ObjectResponse "The deleted object"
// @Failure 403 {object} util.UnauthorizedError "Unauthorized"
// @Failure 404 {object} util.NotFoundError "Resource not found"
// @Failure 502 {object} util.ServerError "Internal server error"
// @Router /spaces/{space_id}/objects/{object_id} [delete]
func DeleteObjectHandler(s *ObjectService) gin.HandlerFunc {
return func(c *gin.Context) {
spaceId := c.Param("space_id")
objectId := c.Param("object_id")
object, err := s.DeleteObject(c.Request.Context(), spaceId, objectId)
code := util.MapErrorCode(err,
util.ErrToCode(ErrObjectNotFound, http.StatusNotFound),
util.ErrToCode(ErrFailedRetrieveObject, http.StatusInternalServerError),
util.ErrToCode(ErrFailedDeleteObject, http.StatusInternalServerError),
)
if code != http.StatusOK {
apiErr := util.CodeToAPIError(code, err.Error())
c.JSON(code, apiErr)
return
}
c.JSON(http.StatusOK, ObjectResponse{Object: object})
}
}
@ -89,7 +124,7 @@ func GetObjectHandler(s *ObjectService) gin.HandlerFunc {
// @Produce json
// @Param space_id path string true "The ID of the space"
// @Param object body map[string]string true "Object details (e.g., name)"
// @Success 200 {object} CreateObjectResponse "The created object"
// @Success 200 {object} ObjectResponse "The created object"
// @Failure 400 {object} util.ValidationError "Bad request"
// @Failure 403 {object} util.UnauthorizedError "Unauthorized"
// @Failure 502 {object} util.ServerError "Internal server error"
@ -121,7 +156,7 @@ func CreateObjectHandler(s *ObjectService) gin.HandlerFunc {
return
}
c.JSON(http.StatusOK, CreateObjectResponse{Object: object})
c.JSON(http.StatusOK, ObjectResponse{Object: object})
}
}
@ -134,7 +169,7 @@ func CreateObjectHandler(s *ObjectService) gin.HandlerFunc {
// @Param space_id path string true "The ID of the space"
// @Param object_id path string true "The ID of the object"
// @Param object body Object true "The updated object details"
// @Success 200 {object} UpdateObjectResponse "The updated object"
// @Success 200 {object} ObjectResponse "The updated object"
// @Failure 400 {object} util.ValidationError "Bad request"
// @Failure 403 {object} util.UnauthorizedError "Unauthorized"
// @Failure 404 {object} util.NotFoundError "Resource not found"
@ -165,7 +200,7 @@ func UpdateObjectHandler(s *ObjectService) gin.HandlerFunc {
return
}
c.JSON(http.StatusNotImplemented, UpdateObjectResponse{Object: object})
c.JSON(http.StatusNotImplemented, ObjectResponse{Object: object})
}
}

View file

@ -1,9 +1,5 @@
package object
type GetObjectResponse struct {
Object Object `json:"object"`
}
type CreateObjectRequest struct {
Name string `json:"name"`
Icon string `json:"icon"`
@ -15,15 +11,12 @@ type CreateObjectRequest struct {
WithChat bool `json:"with_chat"`
}
type CreateObjectResponse struct {
Object Object `json:"object"`
}
// TODO: Add fields to the request
type UpdateObjectRequest struct {
Object Object `json:"object"`
}
type UpdateObjectResponse struct {
type ObjectResponse struct {
Object Object `json:"object"`
}

View file

@ -20,6 +20,7 @@ var (
ErrFailedRetrieveObject = errors.New("failed to retrieve object")
ErrorFailedRetrieveObjects = errors.New("failed to retrieve list of objects")
ErrNoObjectsFound = errors.New("no objects found")
ErrFailedDeleteObject = errors.New("failed to delete object")
ErrFailedCreateObject = errors.New("failed to create object")
ErrInputMissingSource = errors.New("source is missing for bookmark")
ErrFailedSetRelationFeatured = errors.New("failed to set relation featured")
@ -39,8 +40,9 @@ var (
type Service interface {
ListObjects(ctx context.Context, spaceId string, offset int, limit int) ([]Object, int, bool, error)
GetObject(ctx context.Context, spaceId string, objectId string) (Object, error)
CreateObject(ctx context.Context, spaceId string, obj Object) (Object, error)
UpdateObject(ctx context.Context, spaceId string, obj Object) (Object, error)
DeleteObject(ctx context.Context, spaceId string, objectId string) error
CreateObject(ctx context.Context, spaceId string, request CreateObjectRequest) (Object, error)
UpdateObject(ctx context.Context, spaceId string, objectId string, request UpdateObjectRequest) (Object, error)
ListTypes(ctx context.Context, spaceId string, offset int, limit int) ([]ObjectType, int, bool, error)
ListTemplates(ctx context.Context, spaceId string, typeId string, offset int, limit int) ([]ObjectTemplate, int, bool, error)
}
@ -148,6 +150,25 @@ func (s *ObjectService) GetObject(ctx context.Context, spaceId string, objectId
return object, nil
}
// DeleteObject deletes an existing object in a specific space.
func (s *ObjectService) DeleteObject(ctx context.Context, spaceId string, objectId string) (Object, error) {
object, err := s.GetObject(ctx, spaceId, objectId)
if err != nil {
return Object{}, err
}
resp := s.mw.ObjectListSetIsArchived(ctx, &pb.RpcObjectListSetIsArchivedRequest{
ObjectIds: []string{objectId},
IsArchived: true,
})
if resp.Error.Code != pb.RpcObjectListSetIsArchivedResponseError_NULL {
return Object{}, ErrFailedDeleteObject
}
return object, nil
}
// CreateObject creates a new object in a specific space.
func (s *ObjectService) CreateObject(ctx context.Context, spaceId string, request CreateObjectRequest) (Object, error) {
if request.ObjectTypeUniqueKey == "ot-bookmark" && request.Source == "" {

View file

@ -46,6 +46,7 @@ func (s *Server) NewRouter() *gin.Engine {
// Object
v1.GET("/spaces/:space_id/objects", paginator, object.GetObjectsHandler(s.objectService))
v1.GET("/spaces/:space_id/objects/:object_id", object.GetObjectHandler(s.objectService))
v1.DELETE("/spaces/:space_id/objects/:object_id", object.DeleteObjectHandler(s.objectService))
v1.GET("/spaces/:space_id/object_types", paginator, object.GetTypesHandler(s.objectService))
v1.GET("/spaces/:space_id/object_types/:typeId/templates", paginator, object.GetTemplatesHandler(s.objectService))
v1.POST("/spaces/:space_id/objects", object.CreateObjectHandler(s.objectService))