diff --git a/.run/Run.run.xml b/.run/Run.run.xml
index 47b924fe55..78502fd86d 100644
--- a/.run/Run.run.xml
+++ b/.run/Run.run.xml
@@ -9,6 +9,7 @@
+
diff --git a/core/api/docs/docs.go b/core/api/docs/docs.go
index 838673118d..79214ab946 100644
--- a/core/api/docs/docs.go
+++ b/core/api/docs/docs.go
@@ -253,7 +253,7 @@ const docTemplate = `{
"200": {
"description": "Space created successfully",
"schema": {
- "$ref": "#/definitions/space.CreateSpaceResponse"
+ "$ref": "#/definitions/space.SpaceResponse"
}
},
"400": {
@@ -268,6 +268,61 @@ const docTemplate = `{
"$ref": "#/definitions/util.UnauthorizedError"
}
},
+ "423": {
+ "description": "Rate limit exceeded",
+ "schema": {
+ "$ref": "#/definitions/util.RateLimitError"
+ }
+ },
+ "500": {
+ "description": "Internal server error",
+ "schema": {
+ "$ref": "#/definitions/util.ServerError"
+ }
+ }
+ }
+ }
+ },
+ "/spaces/{space_id}": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "spaces"
+ ],
+ "summary": "Get space",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "Space ID",
+ "name": "space_id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Space",
+ "schema": {
+ "$ref": "#/definitions/space.SpaceResponse"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/util.UnauthorizedError"
+ }
+ },
+ "404": {
+ "description": "Space not found",
+ "schema": {
+ "$ref": "#/definitions/util.NotFoundError"
+ }
+ },
"500": {
"description": "Internal server error",
"schema": {
@@ -335,6 +390,62 @@ const docTemplate = `{
}
}
},
+ "/spaces/{space_id}/members/{member_id}": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "spaces"
+ ],
+ "summary": "Get member",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "Space ID",
+ "name": "space_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "Member ID",
+ "name": "member_id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Member",
+ "schema": {
+ "$ref": "#/definitions/space.MemberResponse"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/util.UnauthorizedError"
+ }
+ },
+ "404": {
+ "description": "Member not found",
+ "schema": {
+ "$ref": "#/definitions/util.NotFoundError"
+ }
+ },
+ "500": {
+ "description": "Internal server error",
+ "schema": {
+ "$ref": "#/definitions/util.ServerError"
+ }
+ }
+ }
+ }
+ },
"/spaces/{space_id}/objects": {
"get": {
"consumes": [
@@ -440,6 +551,12 @@ const docTemplate = `{
"$ref": "#/definitions/util.UnauthorizedError"
}
},
+ "423": {
+ "description": "Rate limit exceeded",
+ "schema": {
+ "$ref": "#/definitions/util.RateLimitError"
+ }
+ },
"500": {
"description": "Internal server error",
"schema": {
@@ -556,6 +673,12 @@ const docTemplate = `{
"$ref": "#/definitions/util.NotFoundError"
}
},
+ "423": {
+ "description": "Rate limit exceeded",
+ "schema": {
+ "$ref": "#/definitions/util.RateLimitError"
+ }
+ },
"500": {
"description": "Internal server error",
"schema": {
@@ -947,6 +1070,7 @@ const docTemplate = `{
"type": "object",
"properties": {
"challenge_id": {
+ "description": "The challenge id associated with the displayed code and needed to solve the challenge for token",
"type": "string",
"example": "67647f5ecda913e9a2e11b26"
}
@@ -956,10 +1080,12 @@ const docTemplate = `{
"type": "object",
"properties": {
"app_key": {
+ "description": "The permanent app key",
"type": "string",
"example": "zhSG/zQRmgADyilWPtgdnfo1qD60oK02/SVgi1GaFt6="
},
"session_token": {
+ "description": "The ephemeral session token",
"type": "string",
"example": "eyJhbGciOeJIRzI1NiIsInR5cCI6IkpXVCJ1.eyJzZWVkIjaiY0dmVndlUnAifQ.Y1EZecYnwmvMkrXKOa2XJnAbaRt34urBabe06tmDQII"
}
@@ -969,6 +1095,7 @@ const docTemplate = `{
"type": "object",
"properties": {
"path": {
+ "description": "The path the object was exported to",
"type": "string",
"example": "/path/to/export"
}
@@ -978,6 +1105,7 @@ const docTemplate = `{
"type": "object",
"properties": {
"align": {
+ "description": "The alignment of the block",
"type": "string",
"enum": [
"AlignLeft",
@@ -988,10 +1116,12 @@ const docTemplate = `{
"example": "AlignLeft"
},
"background_color": {
+ "description": "The background color of the block",
"type": "string",
"example": "red"
},
"children_ids": {
+ "description": "The ids of the block's children",
"type": "array",
"items": {
"type": "string"
@@ -1001,16 +1131,28 @@ const docTemplate = `{
]
},
"file": {
- "$ref": "#/definitions/object.File"
+ "description": "The file of the block, if applicable",
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.File"
+ }
+ ]
},
"id": {
+ "description": "The id of the block",
"type": "string",
"example": "64394517de52ad5acb89c66c"
},
"text": {
- "$ref": "#/definitions/object.Text"
+ "description": "The text of the block, if applicable",
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.Text"
+ }
+ ]
},
"vertical_align": {
+ "description": "The vertical alignment of the block",
"type": "string",
"enum": [
"VerticalAlignTop",
@@ -1025,30 +1167,37 @@ const docTemplate = `{
"type": "object",
"properties": {
"body": {
+ "description": "The body of the object",
"type": "string",
- "example": "Object Body"
+ "example": "This is the body of the object. Markdown syntax is supported here."
},
"description": {
+ "description": "The description of the object",
"type": "string",
- "example": "Object Description"
+ "example": "This is a description of the object."
},
"icon": {
+ "description": "The icon of the object",
"type": "string",
"example": "📄"
},
"name": {
+ "description": "The name of the object",
"type": "string",
- "example": "Object Name"
+ "example": "My object"
},
"object_type_unique_key": {
+ "description": "The unique key of the object type",
"type": "string",
"example": "ot-page"
},
"source": {
+ "description": "The source url, only applicable for bookmarks",
"type": "string",
- "example": "https://source.com"
+ "example": "https://bookmark-source.com"
},
"template_id": {
+ "description": "The id of the template to use",
"type": "string",
"example": "bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge"
}
@@ -1058,10 +1207,12 @@ const docTemplate = `{
"type": "object",
"properties": {
"details": {
+ "description": "The details",
"type": "object",
"additionalProperties": true
},
"id": {
+ "description": "The id of the detail",
"type": "string",
"enum": [
"last_modified_date",
@@ -1079,30 +1230,39 @@ const docTemplate = `{
"type": "object",
"properties": {
"added_at": {
+ "description": "The added at of the file",
"type": "integer"
},
"hash": {
+ "description": "The hash of the file",
"type": "string"
},
"mime": {
+ "description": "The mime of the file",
"type": "string"
},
"name": {
+ "description": "The name of the file",
"type": "string"
},
"size": {
+ "description": "The size of the file",
"type": "integer"
},
"state": {
+ "description": "The state of the file",
"type": "string"
},
"style": {
+ "description": "The style of the file",
"type": "string"
},
"target_object_id": {
+ "description": "The target object id of the file",
"type": "string"
},
"type": {
+ "description": "The type of the file",
"type": "string"
}
}
@@ -1111,46 +1271,56 @@ const docTemplate = `{
"type": "object",
"properties": {
"blocks": {
+ "description": "The blocks of the object",
"type": "array",
"items": {
"$ref": "#/definitions/object.Block"
}
},
"details": {
+ "description": "The details of the object",
"type": "array",
"items": {
"$ref": "#/definitions/object.Detail"
}
},
"icon": {
+ "description": "The icon of the object",
"type": "string",
"example": "📄"
},
"id": {
+ "description": "The id of the object",
"type": "string",
"example": "bafyreie6n5l5nkbjal37su54cha4coy7qzuhrnajluzv5qd5jvtsrxkequ"
},
"layout": {
+ "description": "The layout of the object",
"type": "string",
"example": "basic"
},
"name": {
+ "description": "The name of the object",
"type": "string",
- "example": "Object Name"
+ "example": "My object"
},
"root_id": {
+ "description": "The id of the object's root",
"type": "string",
"example": "bafyreicypzj6uvu54664ucv3hmbsd5cmdy2dv4fwua26sciq74khzpyn4u"
},
"snippet": {
+ "description": "The snippet of the object, especially important for notes as they don't have a name",
"type": "string",
"example": "The beginning of the object body..."
},
"space_id": {
+ "description": "The id of the space the object is in",
"type": "string",
"example": "bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1"
},
"type": {
+ "description": "The type of the object",
"type": "string",
"example": "Page"
}
@@ -1160,7 +1330,12 @@ const docTemplate = `{
"type": "object",
"properties": {
"object": {
- "$ref": "#/definitions/object.Object"
+ "description": "The object",
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.Object"
+ }
+ ]
}
}
},
@@ -1168,18 +1343,22 @@ const docTemplate = `{
"type": "object",
"properties": {
"icon": {
+ "description": "The icon of the template",
"type": "string",
"example": "📄"
},
"id": {
+ "description": "The id of the template",
"type": "string",
"example": "bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge"
},
"name": {
+ "description": "The name of the template",
"type": "string",
- "example": "Template Name"
+ "example": "My template"
},
"type": {
+ "description": "The type of the object",
"type": "string",
"example": "template"
}
@@ -1189,7 +1368,12 @@ const docTemplate = `{
"type": "object",
"properties": {
"template": {
- "$ref": "#/definitions/object.Template"
+ "description": "The template",
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.Template"
+ }
+ ]
}
}
},
@@ -1197,18 +1381,22 @@ const docTemplate = `{
"type": "object",
"properties": {
"checked": {
+ "description": "Whether the text is checked",
"type": "boolean",
"example": true
},
"color": {
+ "description": "The color of the text",
"type": "string",
"example": "red"
},
"icon": {
+ "description": "The icon of the text",
"type": "string",
"example": "📄"
},
"style": {
+ "description": "The style of the text",
"type": "string",
"enum": [
"Paragraph",
@@ -1229,8 +1417,9 @@ const docTemplate = `{
"example": "Paragraph"
},
"text": {
+ "description": "The text",
"type": "string",
- "example": "Some text"
+ "example": "Some text..."
}
}
},
@@ -1238,26 +1427,32 @@ const docTemplate = `{
"type": "object",
"properties": {
"icon": {
+ "description": "The icon of the type",
"type": "string",
"example": "📄"
},
"id": {
+ "description": "The id of the type",
"type": "string",
"example": "bafyreigyb6l5szohs32ts26ku2j42yd65e6hqy2u3gtzgdwqv6hzftsetu"
},
"name": {
+ "description": "The name of the type",
"type": "string",
"example": "Page"
},
"recommended_layout": {
+ "description": "The recommended layout of the type",
"type": "string",
"example": "todo"
},
"type": {
+ "description": "The type of the object",
"type": "string",
"example": "type"
},
"unique_key": {
+ "description": "The unique key of the type",
"type": "string",
"example": "ot-page"
}
@@ -1267,7 +1462,12 @@ const docTemplate = `{
"type": "object",
"properties": {
"type": {
- "$ref": "#/definitions/object.Type"
+ "description": "The type",
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.Type"
+ }
+ ]
}
}
},
@@ -1275,13 +1475,19 @@ const docTemplate = `{
"type": "object",
"properties": {
"data": {
+ "description": "The list of items in the current result set",
"type": "array",
"items": {
"$ref": "#/definitions/object.Object"
}
},
"pagination": {
- "$ref": "#/definitions/pagination.PaginationMeta"
+ "description": "The pagination metadata for the response",
+ "allOf": [
+ {
+ "$ref": "#/definitions/pagination.PaginationMeta"
+ }
+ ]
}
}
},
@@ -1289,13 +1495,19 @@ const docTemplate = `{
"type": "object",
"properties": {
"data": {
+ "description": "The list of items in the current result set",
"type": "array",
"items": {
"$ref": "#/definitions/object.Template"
}
},
"pagination": {
- "$ref": "#/definitions/pagination.PaginationMeta"
+ "description": "The pagination metadata for the response",
+ "allOf": [
+ {
+ "$ref": "#/definitions/pagination.PaginationMeta"
+ }
+ ]
}
}
},
@@ -1303,13 +1515,19 @@ const docTemplate = `{
"type": "object",
"properties": {
"data": {
+ "description": "The list of items in the current result set",
"type": "array",
"items": {
"$ref": "#/definitions/object.Type"
}
},
"pagination": {
- "$ref": "#/definitions/pagination.PaginationMeta"
+ "description": "The pagination metadata for the response",
+ "allOf": [
+ {
+ "$ref": "#/definitions/pagination.PaginationMeta"
+ }
+ ]
}
}
},
@@ -1317,13 +1535,19 @@ const docTemplate = `{
"type": "object",
"properties": {
"data": {
+ "description": "The list of items in the current result set",
"type": "array",
"items": {
"$ref": "#/definitions/space.Member"
}
},
"pagination": {
- "$ref": "#/definitions/pagination.PaginationMeta"
+ "description": "The pagination metadata for the response",
+ "allOf": [
+ {
+ "$ref": "#/definitions/pagination.PaginationMeta"
+ }
+ ]
}
}
},
@@ -1331,13 +1555,19 @@ const docTemplate = `{
"type": "object",
"properties": {
"data": {
+ "description": "The list of items in the current result set",
"type": "array",
"items": {
"$ref": "#/definitions/space.Space"
}
},
"pagination": {
- "$ref": "#/definitions/pagination.PaginationMeta"
+ "description": "The pagination metadata for the response",
+ "allOf": [
+ {
+ "$ref": "#/definitions/pagination.PaginationMeta"
+ }
+ ]
}
}
},
@@ -1345,22 +1575,22 @@ const docTemplate = `{
"type": "object",
"properties": {
"has_more": {
- "description": "whether there are more items available",
+ "description": "Indicates if there are more items available beyond the current result set",
"type": "boolean",
"example": true
},
"limit": {
- "description": "the current limit",
+ "description": "The maximum number of items returned in the result set",
"type": "integer",
"example": 100
},
"offset": {
- "description": "the current offset",
+ "description": "The number of items skipped before starting to collect the result set",
"type": "integer",
"example": 0
},
"total": {
- "description": "the total number of items available on that endpoint",
+ "description": "The total number of items available for the endpoint",
"type": "integer",
"example": 1024
}
@@ -1370,16 +1600,30 @@ const docTemplate = `{
"type": "object",
"properties": {
"query": {
- "type": "string"
+ "description": "The search term to look for in object names and snippets",
+ "type": "string",
+ "example": "test"
},
"sort": {
- "$ref": "#/definitions/search.SortOptions"
+ "description": "The sorting criteria and direction for the search results",
+ "allOf": [
+ {
+ "$ref": "#/definitions/search.SortOptions"
+ }
+ ]
},
"types": {
+ "description": "The types of objects to search for, specified by unique key or ID",
"type": "array",
"items": {
"type": "string"
- }
+ },
+ "example": [
+ "ot-note",
+ "ot-page",
+ "ot-678043f0cda9133be777049f",
+ "bafyreightzrdts2ymxyaeyzspwdfo2juspyam76ewq6qq7ixnw3523gs7q"
+ ]
}
}
},
@@ -1387,6 +1631,7 @@ const docTemplate = `{
"type": "object",
"properties": {
"direction": {
+ "description": "The direction to sort the search results",
"type": "string",
"default": "desc",
"enum": [
@@ -1395,6 +1640,7 @@ const docTemplate = `{
]
},
"timestamp": {
+ "description": "The timestamp to sort the search results by",
"type": "string",
"default": "last_modified_date",
"enum": [
@@ -1409,43 +1655,42 @@ const docTemplate = `{
"type": "object",
"properties": {
"name": {
+ "description": "The name of the space",
"type": "string",
"example": "New Space"
}
}
},
- "space.CreateSpaceResponse": {
- "type": "object",
- "properties": {
- "space": {
- "$ref": "#/definitions/space.Space"
- }
- }
- },
"space.Member": {
"type": "object",
"properties": {
"global_name": {
+ "description": "The global name of the member in the network",
"type": "string",
"example": "john.any"
},
"icon": {
+ "description": "The icon of the member",
"type": "string",
"example": "http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay?width=100"
},
"id": {
+ "description": "The profile object id of the member",
"type": "string",
"example": "_participant_bafyreigyfkt6rbv24sbv5aq2hko1bhmv5xxlf22b4bypdu6j7hnphm3psq_23me69r569oi1_AAjEaEwPF4nkEh9AWkqEnzcQ8HziBB4ETjiTpvRCQvWnSMDZ"
},
"identity": {
+ "description": "The identity of the member in the network",
"type": "string",
"example": "AAjEaEwPF4nkEh7AWkqEnzcQ8HziGB4ETjiTpvRCQvWnSMDZ"
},
"name": {
+ "description": "The name of the member",
"type": "string",
"example": "John Doe"
},
"role": {
+ "description": "The role of the member",
"type": "string",
"enum": [
"Reader",
@@ -1456,92 +1701,138 @@ const docTemplate = `{
"example": "Owner"
},
"type": {
+ "description": "The type of the object",
"type": "string",
"example": "member"
}
}
},
+ "space.MemberResponse": {
+ "type": "object",
+ "properties": {
+ "member": {
+ "description": "The member",
+ "allOf": [
+ {
+ "$ref": "#/definitions/space.Member"
+ }
+ ]
+ }
+ }
+ },
"space.Space": {
"type": "object",
"properties": {
"account_space_id": {
+ "description": "The id of the account space",
"type": "string",
"example": "bafyreihpd2knon5wbljhtfeg3fcqtg3i2pomhhnigui6lrjmzcjzep7gcy.23me69r569oi1"
},
"analytics_id": {
+ "description": "The analytics id of the account",
"type": "string",
"example": "624aecdd-4797-4611-9d61-a2ae5f53cf1c"
},
"archive_object_id": {
+ "description": "The id of the archive object",
"type": "string",
"example": "bafyreialsgoyflf3etjm3parzurivyaukzivwortf32b4twnlwpwocsrri"
},
"device_id": {
+ "description": "The id of the device",
"type": "string",
"example": "12D3KooWGZMJ4kQVyQVXaj7gJPZr3RZ2nvd9M2Eq2pprEoPih9WF"
},
"gateway_url": {
+ "description": "The gateway url to serve files and media",
"type": "string",
"example": "http://127.0.0.1:31006"
},
"home_object_id": {
+ "description": "The id of the home object",
"type": "string",
"example": "bafyreie4qcl3wczb4cw5hrfyycikhjyh6oljdis3ewqrk5boaav3sbwqya"
},
"icon": {
+ "description": "The icon of the space",
"type": "string",
"example": "http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay"
},
"id": {
+ "description": "The id of the space",
"type": "string",
"example": "bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1"
},
"local_storage_path": {
+ "description": "The local storage path of the account",
"type": "string",
"example": "/Users/johndoe/Library/Application Support/Anytype/data/AAHTtt1wuQEnaYBNZ2Cyfcvs6DqPqxgn8VXDVk4avsUkMuha"
},
"marketplace_workspace_id": {
+ "description": "The id of the marketplace workspace",
"type": "string",
"example": "_anytype_marketplace"
},
"name": {
+ "description": "The name of the space",
"type": "string",
- "example": "Space Name"
+ "example": "My Space"
},
"network_id": {
+ "description": "The network id of the space",
"type": "string",
"example": "N83gJpVd9MuNRZAuJLZ7LiMntTThhPc6DtzWWVjb1M3PouVU"
},
"profile_object_id": {
+ "description": "The id of the profile object",
"type": "string",
"example": "bafyreiaxhwreshjqwndpwtdsu4mtihaqhhmlygqnyqpfyfwlqfq3rm3gw4"
},
"space_view_id": {
+ "description": "The id of the space view",
"type": "string",
"example": "bafyreigzv3vq7qwlrsin6njoduq727ssnhwd6bgyfj6nm4hv3pxoc2rxhy"
},
"tech_space_id": {
+ "description": "The id of tech space, where objects outside of user's actual spaces are stored, e.g. spaces itself",
"type": "string",
"example": "bafyreif4xuwncrjl6jajt4zrrfnylpki476nv2w64yf42ovt7gia7oypii.23me69r569oi1"
},
"timezone": {
+ "description": "The timezone of the account",
"type": "string",
"example": ""
},
"type": {
+ "description": "The type of the object",
"type": "string",
"example": "space"
},
"widgets_id": {
+ "description": "The id of the widgets",
"type": "string",
"example": "bafyreialj7pceh53mifm5dixlho47ke4qjmsn2uh4wsjf7xq2pnlo5xfva"
},
"workspace_object_id": {
+ "description": "The id of the workspace object",
"type": "string",
"example": "bafyreiapey2g6e6za4zfxvlgwdy4hbbfu676gmwrhnqvjbxvrchr7elr3y"
}
}
},
+ "space.SpaceResponse": {
+ "type": "object",
+ "properties": {
+ "space": {
+ "description": "The space",
+ "allOf": [
+ {
+ "$ref": "#/definitions/space.Space"
+ }
+ ]
+ }
+ }
+ },
"util.ForbiddenError": {
"type": "object",
"properties": {
@@ -1549,7 +1840,8 @@ const docTemplate = `{
"type": "object",
"properties": {
"message": {
- "type": "string"
+ "type": "string",
+ "example": "Forbidden"
}
}
}
@@ -1562,7 +1854,22 @@ const docTemplate = `{
"type": "object",
"properties": {
"message": {
- "type": "string"
+ "type": "string",
+ "example": "Resource not found"
+ }
+ }
+ }
+ }
+ },
+ "util.RateLimitError": {
+ "type": "object",
+ "properties": {
+ "error": {
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string",
+ "example": "Rate limit exceeded"
}
}
}
@@ -1575,7 +1882,8 @@ const docTemplate = `{
"type": "object",
"properties": {
"message": {
- "type": "string"
+ "type": "string",
+ "example": "Internal server error"
}
}
}
@@ -1588,7 +1896,8 @@ const docTemplate = `{
"type": "object",
"properties": {
"message": {
- "type": "string"
+ "type": "string",
+ "example": "Unauthorized"
}
}
}
@@ -1601,7 +1910,8 @@ const docTemplate = `{
"type": "object",
"properties": {
"message": {
- "type": "string"
+ "type": "string",
+ "example": "Bad request"
}
}
}
diff --git a/core/api/docs/swagger.json b/core/api/docs/swagger.json
index cf8fe16d36..7978d53c05 100644
--- a/core/api/docs/swagger.json
+++ b/core/api/docs/swagger.json
@@ -247,7 +247,7 @@
"200": {
"description": "Space created successfully",
"schema": {
- "$ref": "#/definitions/space.CreateSpaceResponse"
+ "$ref": "#/definitions/space.SpaceResponse"
}
},
"400": {
@@ -262,6 +262,61 @@
"$ref": "#/definitions/util.UnauthorizedError"
}
},
+ "423": {
+ "description": "Rate limit exceeded",
+ "schema": {
+ "$ref": "#/definitions/util.RateLimitError"
+ }
+ },
+ "500": {
+ "description": "Internal server error",
+ "schema": {
+ "$ref": "#/definitions/util.ServerError"
+ }
+ }
+ }
+ }
+ },
+ "/spaces/{space_id}": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "spaces"
+ ],
+ "summary": "Get space",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "Space ID",
+ "name": "space_id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Space",
+ "schema": {
+ "$ref": "#/definitions/space.SpaceResponse"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/util.UnauthorizedError"
+ }
+ },
+ "404": {
+ "description": "Space not found",
+ "schema": {
+ "$ref": "#/definitions/util.NotFoundError"
+ }
+ },
"500": {
"description": "Internal server error",
"schema": {
@@ -329,6 +384,62 @@
}
}
},
+ "/spaces/{space_id}/members/{member_id}": {
+ "get": {
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "spaces"
+ ],
+ "summary": "Get member",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "Space ID",
+ "name": "space_id",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "Member ID",
+ "name": "member_id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "Member",
+ "schema": {
+ "$ref": "#/definitions/space.MemberResponse"
+ }
+ },
+ "401": {
+ "description": "Unauthorized",
+ "schema": {
+ "$ref": "#/definitions/util.UnauthorizedError"
+ }
+ },
+ "404": {
+ "description": "Member not found",
+ "schema": {
+ "$ref": "#/definitions/util.NotFoundError"
+ }
+ },
+ "500": {
+ "description": "Internal server error",
+ "schema": {
+ "$ref": "#/definitions/util.ServerError"
+ }
+ }
+ }
+ }
+ },
"/spaces/{space_id}/objects": {
"get": {
"consumes": [
@@ -434,6 +545,12 @@
"$ref": "#/definitions/util.UnauthorizedError"
}
},
+ "423": {
+ "description": "Rate limit exceeded",
+ "schema": {
+ "$ref": "#/definitions/util.RateLimitError"
+ }
+ },
"500": {
"description": "Internal server error",
"schema": {
@@ -550,6 +667,12 @@
"$ref": "#/definitions/util.NotFoundError"
}
},
+ "423": {
+ "description": "Rate limit exceeded",
+ "schema": {
+ "$ref": "#/definitions/util.RateLimitError"
+ }
+ },
"500": {
"description": "Internal server error",
"schema": {
@@ -941,6 +1064,7 @@
"type": "object",
"properties": {
"challenge_id": {
+ "description": "The challenge id associated with the displayed code and needed to solve the challenge for token",
"type": "string",
"example": "67647f5ecda913e9a2e11b26"
}
@@ -950,10 +1074,12 @@
"type": "object",
"properties": {
"app_key": {
+ "description": "The permanent app key",
"type": "string",
"example": "zhSG/zQRmgADyilWPtgdnfo1qD60oK02/SVgi1GaFt6="
},
"session_token": {
+ "description": "The ephemeral session token",
"type": "string",
"example": "eyJhbGciOeJIRzI1NiIsInR5cCI6IkpXVCJ1.eyJzZWVkIjaiY0dmVndlUnAifQ.Y1EZecYnwmvMkrXKOa2XJnAbaRt34urBabe06tmDQII"
}
@@ -963,6 +1089,7 @@
"type": "object",
"properties": {
"path": {
+ "description": "The path the object was exported to",
"type": "string",
"example": "/path/to/export"
}
@@ -972,6 +1099,7 @@
"type": "object",
"properties": {
"align": {
+ "description": "The alignment of the block",
"type": "string",
"enum": [
"AlignLeft",
@@ -982,10 +1110,12 @@
"example": "AlignLeft"
},
"background_color": {
+ "description": "The background color of the block",
"type": "string",
"example": "red"
},
"children_ids": {
+ "description": "The ids of the block's children",
"type": "array",
"items": {
"type": "string"
@@ -995,16 +1125,28 @@
]
},
"file": {
- "$ref": "#/definitions/object.File"
+ "description": "The file of the block, if applicable",
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.File"
+ }
+ ]
},
"id": {
+ "description": "The id of the block",
"type": "string",
"example": "64394517de52ad5acb89c66c"
},
"text": {
- "$ref": "#/definitions/object.Text"
+ "description": "The text of the block, if applicable",
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.Text"
+ }
+ ]
},
"vertical_align": {
+ "description": "The vertical alignment of the block",
"type": "string",
"enum": [
"VerticalAlignTop",
@@ -1019,30 +1161,37 @@
"type": "object",
"properties": {
"body": {
+ "description": "The body of the object",
"type": "string",
- "example": "Object Body"
+ "example": "This is the body of the object. Markdown syntax is supported here."
},
"description": {
+ "description": "The description of the object",
"type": "string",
- "example": "Object Description"
+ "example": "This is a description of the object."
},
"icon": {
+ "description": "The icon of the object",
"type": "string",
"example": "📄"
},
"name": {
+ "description": "The name of the object",
"type": "string",
- "example": "Object Name"
+ "example": "My object"
},
"object_type_unique_key": {
+ "description": "The unique key of the object type",
"type": "string",
"example": "ot-page"
},
"source": {
+ "description": "The source url, only applicable for bookmarks",
"type": "string",
- "example": "https://source.com"
+ "example": "https://bookmark-source.com"
},
"template_id": {
+ "description": "The id of the template to use",
"type": "string",
"example": "bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge"
}
@@ -1052,10 +1201,12 @@
"type": "object",
"properties": {
"details": {
+ "description": "The details",
"type": "object",
"additionalProperties": true
},
"id": {
+ "description": "The id of the detail",
"type": "string",
"enum": [
"last_modified_date",
@@ -1073,30 +1224,39 @@
"type": "object",
"properties": {
"added_at": {
+ "description": "The added at of the file",
"type": "integer"
},
"hash": {
+ "description": "The hash of the file",
"type": "string"
},
"mime": {
+ "description": "The mime of the file",
"type": "string"
},
"name": {
+ "description": "The name of the file",
"type": "string"
},
"size": {
+ "description": "The size of the file",
"type": "integer"
},
"state": {
+ "description": "The state of the file",
"type": "string"
},
"style": {
+ "description": "The style of the file",
"type": "string"
},
"target_object_id": {
+ "description": "The target object id of the file",
"type": "string"
},
"type": {
+ "description": "The type of the file",
"type": "string"
}
}
@@ -1105,46 +1265,56 @@
"type": "object",
"properties": {
"blocks": {
+ "description": "The blocks of the object",
"type": "array",
"items": {
"$ref": "#/definitions/object.Block"
}
},
"details": {
+ "description": "The details of the object",
"type": "array",
"items": {
"$ref": "#/definitions/object.Detail"
}
},
"icon": {
+ "description": "The icon of the object",
"type": "string",
"example": "📄"
},
"id": {
+ "description": "The id of the object",
"type": "string",
"example": "bafyreie6n5l5nkbjal37su54cha4coy7qzuhrnajluzv5qd5jvtsrxkequ"
},
"layout": {
+ "description": "The layout of the object",
"type": "string",
"example": "basic"
},
"name": {
+ "description": "The name of the object",
"type": "string",
- "example": "Object Name"
+ "example": "My object"
},
"root_id": {
+ "description": "The id of the object's root",
"type": "string",
"example": "bafyreicypzj6uvu54664ucv3hmbsd5cmdy2dv4fwua26sciq74khzpyn4u"
},
"snippet": {
+ "description": "The snippet of the object, especially important for notes as they don't have a name",
"type": "string",
"example": "The beginning of the object body..."
},
"space_id": {
+ "description": "The id of the space the object is in",
"type": "string",
"example": "bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1"
},
"type": {
+ "description": "The type of the object",
"type": "string",
"example": "Page"
}
@@ -1154,7 +1324,12 @@
"type": "object",
"properties": {
"object": {
- "$ref": "#/definitions/object.Object"
+ "description": "The object",
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.Object"
+ }
+ ]
}
}
},
@@ -1162,18 +1337,22 @@
"type": "object",
"properties": {
"icon": {
+ "description": "The icon of the template",
"type": "string",
"example": "📄"
},
"id": {
+ "description": "The id of the template",
"type": "string",
"example": "bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge"
},
"name": {
+ "description": "The name of the template",
"type": "string",
- "example": "Template Name"
+ "example": "My template"
},
"type": {
+ "description": "The type of the object",
"type": "string",
"example": "template"
}
@@ -1183,7 +1362,12 @@
"type": "object",
"properties": {
"template": {
- "$ref": "#/definitions/object.Template"
+ "description": "The template",
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.Template"
+ }
+ ]
}
}
},
@@ -1191,18 +1375,22 @@
"type": "object",
"properties": {
"checked": {
+ "description": "Whether the text is checked",
"type": "boolean",
"example": true
},
"color": {
+ "description": "The color of the text",
"type": "string",
"example": "red"
},
"icon": {
+ "description": "The icon of the text",
"type": "string",
"example": "📄"
},
"style": {
+ "description": "The style of the text",
"type": "string",
"enum": [
"Paragraph",
@@ -1223,8 +1411,9 @@
"example": "Paragraph"
},
"text": {
+ "description": "The text",
"type": "string",
- "example": "Some text"
+ "example": "Some text..."
}
}
},
@@ -1232,26 +1421,32 @@
"type": "object",
"properties": {
"icon": {
+ "description": "The icon of the type",
"type": "string",
"example": "📄"
},
"id": {
+ "description": "The id of the type",
"type": "string",
"example": "bafyreigyb6l5szohs32ts26ku2j42yd65e6hqy2u3gtzgdwqv6hzftsetu"
},
"name": {
+ "description": "The name of the type",
"type": "string",
"example": "Page"
},
"recommended_layout": {
+ "description": "The recommended layout of the type",
"type": "string",
"example": "todo"
},
"type": {
+ "description": "The type of the object",
"type": "string",
"example": "type"
},
"unique_key": {
+ "description": "The unique key of the type",
"type": "string",
"example": "ot-page"
}
@@ -1261,7 +1456,12 @@
"type": "object",
"properties": {
"type": {
- "$ref": "#/definitions/object.Type"
+ "description": "The type",
+ "allOf": [
+ {
+ "$ref": "#/definitions/object.Type"
+ }
+ ]
}
}
},
@@ -1269,13 +1469,19 @@
"type": "object",
"properties": {
"data": {
+ "description": "The list of items in the current result set",
"type": "array",
"items": {
"$ref": "#/definitions/object.Object"
}
},
"pagination": {
- "$ref": "#/definitions/pagination.PaginationMeta"
+ "description": "The pagination metadata for the response",
+ "allOf": [
+ {
+ "$ref": "#/definitions/pagination.PaginationMeta"
+ }
+ ]
}
}
},
@@ -1283,13 +1489,19 @@
"type": "object",
"properties": {
"data": {
+ "description": "The list of items in the current result set",
"type": "array",
"items": {
"$ref": "#/definitions/object.Template"
}
},
"pagination": {
- "$ref": "#/definitions/pagination.PaginationMeta"
+ "description": "The pagination metadata for the response",
+ "allOf": [
+ {
+ "$ref": "#/definitions/pagination.PaginationMeta"
+ }
+ ]
}
}
},
@@ -1297,13 +1509,19 @@
"type": "object",
"properties": {
"data": {
+ "description": "The list of items in the current result set",
"type": "array",
"items": {
"$ref": "#/definitions/object.Type"
}
},
"pagination": {
- "$ref": "#/definitions/pagination.PaginationMeta"
+ "description": "The pagination metadata for the response",
+ "allOf": [
+ {
+ "$ref": "#/definitions/pagination.PaginationMeta"
+ }
+ ]
}
}
},
@@ -1311,13 +1529,19 @@
"type": "object",
"properties": {
"data": {
+ "description": "The list of items in the current result set",
"type": "array",
"items": {
"$ref": "#/definitions/space.Member"
}
},
"pagination": {
- "$ref": "#/definitions/pagination.PaginationMeta"
+ "description": "The pagination metadata for the response",
+ "allOf": [
+ {
+ "$ref": "#/definitions/pagination.PaginationMeta"
+ }
+ ]
}
}
},
@@ -1325,13 +1549,19 @@
"type": "object",
"properties": {
"data": {
+ "description": "The list of items in the current result set",
"type": "array",
"items": {
"$ref": "#/definitions/space.Space"
}
},
"pagination": {
- "$ref": "#/definitions/pagination.PaginationMeta"
+ "description": "The pagination metadata for the response",
+ "allOf": [
+ {
+ "$ref": "#/definitions/pagination.PaginationMeta"
+ }
+ ]
}
}
},
@@ -1339,22 +1569,22 @@
"type": "object",
"properties": {
"has_more": {
- "description": "whether there are more items available",
+ "description": "Indicates if there are more items available beyond the current result set",
"type": "boolean",
"example": true
},
"limit": {
- "description": "the current limit",
+ "description": "The maximum number of items returned in the result set",
"type": "integer",
"example": 100
},
"offset": {
- "description": "the current offset",
+ "description": "The number of items skipped before starting to collect the result set",
"type": "integer",
"example": 0
},
"total": {
- "description": "the total number of items available on that endpoint",
+ "description": "The total number of items available for the endpoint",
"type": "integer",
"example": 1024
}
@@ -1364,16 +1594,30 @@
"type": "object",
"properties": {
"query": {
- "type": "string"
+ "description": "The search term to look for in object names and snippets",
+ "type": "string",
+ "example": "test"
},
"sort": {
- "$ref": "#/definitions/search.SortOptions"
+ "description": "The sorting criteria and direction for the search results",
+ "allOf": [
+ {
+ "$ref": "#/definitions/search.SortOptions"
+ }
+ ]
},
"types": {
+ "description": "The types of objects to search for, specified by unique key or ID",
"type": "array",
"items": {
"type": "string"
- }
+ },
+ "example": [
+ "ot-note",
+ "ot-page",
+ "ot-678043f0cda9133be777049f",
+ "bafyreightzrdts2ymxyaeyzspwdfo2juspyam76ewq6qq7ixnw3523gs7q"
+ ]
}
}
},
@@ -1381,6 +1625,7 @@
"type": "object",
"properties": {
"direction": {
+ "description": "The direction to sort the search results",
"type": "string",
"default": "desc",
"enum": [
@@ -1389,6 +1634,7 @@
]
},
"timestamp": {
+ "description": "The timestamp to sort the search results by",
"type": "string",
"default": "last_modified_date",
"enum": [
@@ -1403,43 +1649,42 @@
"type": "object",
"properties": {
"name": {
+ "description": "The name of the space",
"type": "string",
"example": "New Space"
}
}
},
- "space.CreateSpaceResponse": {
- "type": "object",
- "properties": {
- "space": {
- "$ref": "#/definitions/space.Space"
- }
- }
- },
"space.Member": {
"type": "object",
"properties": {
"global_name": {
+ "description": "The global name of the member in the network",
"type": "string",
"example": "john.any"
},
"icon": {
+ "description": "The icon of the member",
"type": "string",
"example": "http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay?width=100"
},
"id": {
+ "description": "The profile object id of the member",
"type": "string",
"example": "_participant_bafyreigyfkt6rbv24sbv5aq2hko1bhmv5xxlf22b4bypdu6j7hnphm3psq_23me69r569oi1_AAjEaEwPF4nkEh9AWkqEnzcQ8HziBB4ETjiTpvRCQvWnSMDZ"
},
"identity": {
+ "description": "The identity of the member in the network",
"type": "string",
"example": "AAjEaEwPF4nkEh7AWkqEnzcQ8HziGB4ETjiTpvRCQvWnSMDZ"
},
"name": {
+ "description": "The name of the member",
"type": "string",
"example": "John Doe"
},
"role": {
+ "description": "The role of the member",
"type": "string",
"enum": [
"Reader",
@@ -1450,92 +1695,138 @@
"example": "Owner"
},
"type": {
+ "description": "The type of the object",
"type": "string",
"example": "member"
}
}
},
+ "space.MemberResponse": {
+ "type": "object",
+ "properties": {
+ "member": {
+ "description": "The member",
+ "allOf": [
+ {
+ "$ref": "#/definitions/space.Member"
+ }
+ ]
+ }
+ }
+ },
"space.Space": {
"type": "object",
"properties": {
"account_space_id": {
+ "description": "The id of the account space",
"type": "string",
"example": "bafyreihpd2knon5wbljhtfeg3fcqtg3i2pomhhnigui6lrjmzcjzep7gcy.23me69r569oi1"
},
"analytics_id": {
+ "description": "The analytics id of the account",
"type": "string",
"example": "624aecdd-4797-4611-9d61-a2ae5f53cf1c"
},
"archive_object_id": {
+ "description": "The id of the archive object",
"type": "string",
"example": "bafyreialsgoyflf3etjm3parzurivyaukzivwortf32b4twnlwpwocsrri"
},
"device_id": {
+ "description": "The id of the device",
"type": "string",
"example": "12D3KooWGZMJ4kQVyQVXaj7gJPZr3RZ2nvd9M2Eq2pprEoPih9WF"
},
"gateway_url": {
+ "description": "The gateway url to serve files and media",
"type": "string",
"example": "http://127.0.0.1:31006"
},
"home_object_id": {
+ "description": "The id of the home object",
"type": "string",
"example": "bafyreie4qcl3wczb4cw5hrfyycikhjyh6oljdis3ewqrk5boaav3sbwqya"
},
"icon": {
+ "description": "The icon of the space",
"type": "string",
"example": "http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay"
},
"id": {
+ "description": "The id of the space",
"type": "string",
"example": "bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1"
},
"local_storage_path": {
+ "description": "The local storage path of the account",
"type": "string",
"example": "/Users/johndoe/Library/Application Support/Anytype/data/AAHTtt1wuQEnaYBNZ2Cyfcvs6DqPqxgn8VXDVk4avsUkMuha"
},
"marketplace_workspace_id": {
+ "description": "The id of the marketplace workspace",
"type": "string",
"example": "_anytype_marketplace"
},
"name": {
+ "description": "The name of the space",
"type": "string",
- "example": "Space Name"
+ "example": "My Space"
},
"network_id": {
+ "description": "The network id of the space",
"type": "string",
"example": "N83gJpVd9MuNRZAuJLZ7LiMntTThhPc6DtzWWVjb1M3PouVU"
},
"profile_object_id": {
+ "description": "The id of the profile object",
"type": "string",
"example": "bafyreiaxhwreshjqwndpwtdsu4mtihaqhhmlygqnyqpfyfwlqfq3rm3gw4"
},
"space_view_id": {
+ "description": "The id of the space view",
"type": "string",
"example": "bafyreigzv3vq7qwlrsin6njoduq727ssnhwd6bgyfj6nm4hv3pxoc2rxhy"
},
"tech_space_id": {
+ "description": "The id of tech space, where objects outside of user's actual spaces are stored, e.g. spaces itself",
"type": "string",
"example": "bafyreif4xuwncrjl6jajt4zrrfnylpki476nv2w64yf42ovt7gia7oypii.23me69r569oi1"
},
"timezone": {
+ "description": "The timezone of the account",
"type": "string",
"example": ""
},
"type": {
+ "description": "The type of the object",
"type": "string",
"example": "space"
},
"widgets_id": {
+ "description": "The id of the widgets",
"type": "string",
"example": "bafyreialj7pceh53mifm5dixlho47ke4qjmsn2uh4wsjf7xq2pnlo5xfva"
},
"workspace_object_id": {
+ "description": "The id of the workspace object",
"type": "string",
"example": "bafyreiapey2g6e6za4zfxvlgwdy4hbbfu676gmwrhnqvjbxvrchr7elr3y"
}
}
},
+ "space.SpaceResponse": {
+ "type": "object",
+ "properties": {
+ "space": {
+ "description": "The space",
+ "allOf": [
+ {
+ "$ref": "#/definitions/space.Space"
+ }
+ ]
+ }
+ }
+ },
"util.ForbiddenError": {
"type": "object",
"properties": {
@@ -1543,7 +1834,8 @@
"type": "object",
"properties": {
"message": {
- "type": "string"
+ "type": "string",
+ "example": "Forbidden"
}
}
}
@@ -1556,7 +1848,22 @@
"type": "object",
"properties": {
"message": {
- "type": "string"
+ "type": "string",
+ "example": "Resource not found"
+ }
+ }
+ }
+ }
+ },
+ "util.RateLimitError": {
+ "type": "object",
+ "properties": {
+ "error": {
+ "type": "object",
+ "properties": {
+ "message": {
+ "type": "string",
+ "example": "Rate limit exceeded"
}
}
}
@@ -1569,7 +1876,8 @@
"type": "object",
"properties": {
"message": {
- "type": "string"
+ "type": "string",
+ "example": "Internal server error"
}
}
}
@@ -1582,7 +1890,8 @@
"type": "object",
"properties": {
"message": {
- "type": "string"
+ "type": "string",
+ "example": "Unauthorized"
}
}
}
@@ -1595,7 +1904,8 @@
"type": "object",
"properties": {
"message": {
- "type": "string"
+ "type": "string",
+ "example": "Bad request"
}
}
}
diff --git a/core/api/docs/swagger.yaml b/core/api/docs/swagger.yaml
index 550a59d1c6..1f1b9a7690 100644
--- a/core/api/docs/swagger.yaml
+++ b/core/api/docs/swagger.yaml
@@ -3,27 +3,33 @@ definitions:
auth.DisplayCodeResponse:
properties:
challenge_id:
+ description: The challenge id associated with the displayed code and needed
+ to solve the challenge for token
example: 67647f5ecda913e9a2e11b26
type: string
type: object
auth.TokenResponse:
properties:
app_key:
+ description: The permanent app key
example: zhSG/zQRmgADyilWPtgdnfo1qD60oK02/SVgi1GaFt6=
type: string
session_token:
+ description: The ephemeral session token
example: eyJhbGciOeJIRzI1NiIsInR5cCI6IkpXVCJ1.eyJzZWVkIjaiY0dmVndlUnAifQ.Y1EZecYnwmvMkrXKOa2XJnAbaRt34urBabe06tmDQII
type: string
type: object
export.ObjectExportResponse:
properties:
path:
+ description: The path the object was exported to
example: /path/to/export
type: string
type: object
object.Block:
properties:
align:
+ description: The alignment of the block
enum:
- AlignLeft
- AlignCenter
@@ -32,22 +38,30 @@ definitions:
example: AlignLeft
type: string
background_color:
+ description: The background color of the block
example: red
type: string
children_ids:
+ description: The ids of the block's children
example:
- '[''6797ce8ecda913cde14b02dc'']'
items:
type: string
type: array
file:
- $ref: '#/definitions/object.File'
+ allOf:
+ - $ref: '#/definitions/object.File'
+ description: The file of the block, if applicable
id:
+ description: The id of the block
example: 64394517de52ad5acb89c66c
type: string
text:
- $ref: '#/definitions/object.Text'
+ allOf:
+ - $ref: '#/definitions/object.Text'
+ description: The text of the block, if applicable
vertical_align:
+ description: The vertical alignment of the block
enum:
- VerticalAlignTop
- VerticalAlignMiddle
@@ -58,24 +72,31 @@ definitions:
object.CreateObjectRequest:
properties:
body:
- example: Object Body
+ description: The body of the object
+ example: This is the body of the object. Markdown syntax is supported here.
type: string
description:
- example: Object Description
+ description: The description of the object
+ example: This is a description of the object.
type: string
icon:
+ description: The icon of the object
example: "\U0001F4C4"
type: string
name:
- example: Object Name
+ description: The name of the object
+ example: My object
type: string
object_type_unique_key:
+ description: The unique key of the object type
example: ot-page
type: string
source:
- example: https://source.com
+ description: The source url, only applicable for bookmarks
+ example: https://bookmark-source.com
type: string
template_id:
+ description: The id of the template to use
example: bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge
type: string
type: object
@@ -83,8 +104,10 @@ definitions:
properties:
details:
additionalProperties: true
+ description: The details
type: object
id:
+ description: The id of the detail
enum:
- last_modified_date
- last_modified_by
@@ -98,96 +121,128 @@ definitions:
object.File:
properties:
added_at:
+ description: The added at of the file
type: integer
hash:
+ description: The hash of the file
type: string
mime:
+ description: The mime of the file
type: string
name:
+ description: The name of the file
type: string
size:
+ description: The size of the file
type: integer
state:
+ description: The state of the file
type: string
style:
+ description: The style of the file
type: string
target_object_id:
+ description: The target object id of the file
type: string
type:
+ description: The type of the file
type: string
type: object
object.Object:
properties:
blocks:
+ description: The blocks of the object
items:
$ref: '#/definitions/object.Block'
type: array
details:
+ description: The details of the object
items:
$ref: '#/definitions/object.Detail'
type: array
icon:
+ description: The icon of the object
example: "\U0001F4C4"
type: string
id:
+ description: The id of the object
example: bafyreie6n5l5nkbjal37su54cha4coy7qzuhrnajluzv5qd5jvtsrxkequ
type: string
layout:
+ description: The layout of the object
example: basic
type: string
name:
- example: Object Name
+ description: The name of the object
+ example: My object
type: string
root_id:
+ description: The id of the object's root
example: bafyreicypzj6uvu54664ucv3hmbsd5cmdy2dv4fwua26sciq74khzpyn4u
type: string
snippet:
+ description: The snippet of the object, especially important for notes as
+ they don't have a name
example: The beginning of the object body...
type: string
space_id:
+ description: The id of the space the object is in
example: bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1
type: string
type:
+ description: The type of the object
example: Page
type: string
type: object
object.ObjectResponse:
properties:
object:
- $ref: '#/definitions/object.Object'
+ allOf:
+ - $ref: '#/definitions/object.Object'
+ description: The object
type: object
object.Template:
properties:
icon:
+ description: The icon of the template
example: "\U0001F4C4"
type: string
id:
+ description: The id of the template
example: bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge
type: string
name:
- example: Template Name
+ description: The name of the template
+ example: My template
type: string
type:
+ description: The type of the object
example: template
type: string
type: object
object.TemplateResponse:
properties:
template:
- $ref: '#/definitions/object.Template'
+ allOf:
+ - $ref: '#/definitions/object.Template'
+ description: The template
type: object
object.Text:
properties:
checked:
+ description: Whether the text is checked
example: true
type: boolean
color:
+ description: The color of the text
example: red
type: string
icon:
+ description: The icon of the text
example: "\U0001F4C4"
type: string
style:
+ description: The style of the text
enum:
- Paragraph
- Header1
@@ -206,106 +261,143 @@ definitions:
example: Paragraph
type: string
text:
- example: Some text
+ description: The text
+ example: Some text...
type: string
type: object
object.Type:
properties:
icon:
+ description: The icon of the type
example: "\U0001F4C4"
type: string
id:
+ description: The id of the type
example: bafyreigyb6l5szohs32ts26ku2j42yd65e6hqy2u3gtzgdwqv6hzftsetu
type: string
name:
+ description: The name of the type
example: Page
type: string
recommended_layout:
+ description: The recommended layout of the type
example: todo
type: string
type:
+ description: The type of the object
example: type
type: string
unique_key:
+ description: The unique key of the type
example: ot-page
type: string
type: object
object.TypeResponse:
properties:
type:
- $ref: '#/definitions/object.Type'
+ allOf:
+ - $ref: '#/definitions/object.Type'
+ description: The type
type: object
pagination.PaginatedResponse-object_Object:
properties:
data:
+ description: The list of items in the current result set
items:
$ref: '#/definitions/object.Object'
type: array
pagination:
- $ref: '#/definitions/pagination.PaginationMeta'
+ allOf:
+ - $ref: '#/definitions/pagination.PaginationMeta'
+ description: The pagination metadata for the response
type: object
pagination.PaginatedResponse-object_Template:
properties:
data:
+ description: The list of items in the current result set
items:
$ref: '#/definitions/object.Template'
type: array
pagination:
- $ref: '#/definitions/pagination.PaginationMeta'
+ allOf:
+ - $ref: '#/definitions/pagination.PaginationMeta'
+ description: The pagination metadata for the response
type: object
pagination.PaginatedResponse-object_Type:
properties:
data:
+ description: The list of items in the current result set
items:
$ref: '#/definitions/object.Type'
type: array
pagination:
- $ref: '#/definitions/pagination.PaginationMeta'
+ allOf:
+ - $ref: '#/definitions/pagination.PaginationMeta'
+ description: The pagination metadata for the response
type: object
pagination.PaginatedResponse-space_Member:
properties:
data:
+ description: The list of items in the current result set
items:
$ref: '#/definitions/space.Member'
type: array
pagination:
- $ref: '#/definitions/pagination.PaginationMeta'
+ allOf:
+ - $ref: '#/definitions/pagination.PaginationMeta'
+ description: The pagination metadata for the response
type: object
pagination.PaginatedResponse-space_Space:
properties:
data:
+ description: The list of items in the current result set
items:
$ref: '#/definitions/space.Space'
type: array
pagination:
- $ref: '#/definitions/pagination.PaginationMeta'
+ allOf:
+ - $ref: '#/definitions/pagination.PaginationMeta'
+ description: The pagination metadata for the response
type: object
pagination.PaginationMeta:
properties:
has_more:
- description: whether there are more items available
+ description: Indicates if there are more items available beyond the current
+ result set
example: true
type: boolean
limit:
- description: the current limit
+ description: The maximum number of items returned in the result set
example: 100
type: integer
offset:
- description: the current offset
+ description: The number of items skipped before starting to collect the result
+ set
example: 0
type: integer
total:
- description: the total number of items available on that endpoint
+ description: The total number of items available for the endpoint
example: 1024
type: integer
type: object
search.SearchRequest:
properties:
query:
+ description: The search term to look for in object names and snippets
+ example: test
type: string
sort:
- $ref: '#/definitions/search.SortOptions'
+ allOf:
+ - $ref: '#/definitions/search.SortOptions'
+ description: The sorting criteria and direction for the search results
types:
+ description: The types of objects to search for, specified by unique key or
+ ID
+ example:
+ - ot-note
+ - ot-page
+ - ot-678043f0cda9133be777049f
+ - bafyreightzrdts2ymxyaeyzspwdfo2juspyam76ewq6qq7ixnw3523gs7q
items:
type: string
type: array
@@ -314,12 +406,14 @@ definitions:
properties:
direction:
default: desc
+ description: The direction to sort the search results
enum:
- asc
- desc
type: string
timestamp:
default: last_modified_date
+ description: The timestamp to sort the search results by
enum:
- created_date
- last_modified_date
@@ -329,32 +423,34 @@ definitions:
space.CreateSpaceRequest:
properties:
name:
+ description: The name of the space
example: New Space
type: string
type: object
- space.CreateSpaceResponse:
- properties:
- space:
- $ref: '#/definitions/space.Space'
- type: object
space.Member:
properties:
global_name:
+ description: The global name of the member in the network
example: john.any
type: string
icon:
+ description: The icon of the member
example: http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay?width=100
type: string
id:
+ description: The profile object id of the member
example: _participant_bafyreigyfkt6rbv24sbv5aq2hko1bhmv5xxlf22b4bypdu6j7hnphm3psq_23me69r569oi1_AAjEaEwPF4nkEh9AWkqEnzcQ8HziBB4ETjiTpvRCQvWnSMDZ
type: string
identity:
+ description: The identity of the member in the network
example: AAjEaEwPF4nkEh7AWkqEnzcQ8HziGB4ETjiTpvRCQvWnSMDZ
type: string
name:
+ description: The name of the member
example: John Doe
type: string
role:
+ description: The role of the member
enum:
- Reader
- Writer
@@ -363,74 +459,110 @@ definitions:
example: Owner
type: string
type:
+ description: The type of the object
example: member
type: string
type: object
+ space.MemberResponse:
+ properties:
+ member:
+ allOf:
+ - $ref: '#/definitions/space.Member'
+ description: The member
+ type: object
space.Space:
properties:
account_space_id:
+ description: The id of the account space
example: bafyreihpd2knon5wbljhtfeg3fcqtg3i2pomhhnigui6lrjmzcjzep7gcy.23me69r569oi1
type: string
analytics_id:
+ description: The analytics id of the account
example: 624aecdd-4797-4611-9d61-a2ae5f53cf1c
type: string
archive_object_id:
+ description: The id of the archive object
example: bafyreialsgoyflf3etjm3parzurivyaukzivwortf32b4twnlwpwocsrri
type: string
device_id:
+ description: The id of the device
example: 12D3KooWGZMJ4kQVyQVXaj7gJPZr3RZ2nvd9M2Eq2pprEoPih9WF
type: string
gateway_url:
+ description: The gateway url to serve files and media
example: http://127.0.0.1:31006
type: string
home_object_id:
+ description: The id of the home object
example: bafyreie4qcl3wczb4cw5hrfyycikhjyh6oljdis3ewqrk5boaav3sbwqya
type: string
icon:
+ description: The icon of the space
example: http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay
type: string
id:
+ description: The id of the space
example: bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1
type: string
local_storage_path:
+ description: The local storage path of the account
example: /Users/johndoe/Library/Application Support/Anytype/data/AAHTtt1wuQEnaYBNZ2Cyfcvs6DqPqxgn8VXDVk4avsUkMuha
type: string
marketplace_workspace_id:
+ description: The id of the marketplace workspace
example: _anytype_marketplace
type: string
name:
- example: Space Name
+ description: The name of the space
+ example: My Space
type: string
network_id:
+ description: The network id of the space
example: N83gJpVd9MuNRZAuJLZ7LiMntTThhPc6DtzWWVjb1M3PouVU
type: string
profile_object_id:
+ description: The id of the profile object
example: bafyreiaxhwreshjqwndpwtdsu4mtihaqhhmlygqnyqpfyfwlqfq3rm3gw4
type: string
space_view_id:
+ description: The id of the space view
example: bafyreigzv3vq7qwlrsin6njoduq727ssnhwd6bgyfj6nm4hv3pxoc2rxhy
type: string
tech_space_id:
+ description: The id of tech space, where objects outside of user's actual
+ spaces are stored, e.g. spaces itself
example: bafyreif4xuwncrjl6jajt4zrrfnylpki476nv2w64yf42ovt7gia7oypii.23me69r569oi1
type: string
timezone:
+ description: The timezone of the account
example: ""
type: string
type:
+ description: The type of the object
example: space
type: string
widgets_id:
+ description: The id of the widgets
example: bafyreialj7pceh53mifm5dixlho47ke4qjmsn2uh4wsjf7xq2pnlo5xfva
type: string
workspace_object_id:
+ description: The id of the workspace object
example: bafyreiapey2g6e6za4zfxvlgwdy4hbbfu676gmwrhnqvjbxvrchr7elr3y
type: string
type: object
+ space.SpaceResponse:
+ properties:
+ space:
+ allOf:
+ - $ref: '#/definitions/space.Space'
+ description: The space
+ type: object
util.ForbiddenError:
properties:
error:
properties:
message:
+ example: Forbidden
type: string
type: object
type: object
@@ -439,6 +571,16 @@ definitions:
error:
properties:
message:
+ example: Resource not found
+ type: string
+ type: object
+ type: object
+ util.RateLimitError:
+ properties:
+ error:
+ properties:
+ message:
+ example: Rate limit exceeded
type: string
type: object
type: object
@@ -447,6 +589,7 @@ definitions:
error:
properties:
message:
+ example: Internal server error
type: string
type: object
type: object
@@ -455,6 +598,7 @@ definitions:
error:
properties:
message:
+ example: Unauthorized
type: string
type: object
type: object
@@ -463,6 +607,7 @@ definitions:
error:
properties:
message:
+ example: Bad request
type: string
type: object
type: object
@@ -637,7 +782,7 @@ paths:
"200":
description: Space created successfully
schema:
- $ref: '#/definitions/space.CreateSpaceResponse'
+ $ref: '#/definitions/space.SpaceResponse'
"400":
description: Bad request
schema:
@@ -646,6 +791,10 @@ paths:
description: Unauthorized
schema:
$ref: '#/definitions/util.UnauthorizedError'
+ "423":
+ description: Rate limit exceeded
+ schema:
+ $ref: '#/definitions/util.RateLimitError'
"500":
description: Internal server error
schema:
@@ -653,6 +802,38 @@ paths:
summary: Create space
tags:
- spaces
+ /spaces/{space_id}:
+ get:
+ consumes:
+ - application/json
+ parameters:
+ - description: Space ID
+ in: path
+ name: space_id
+ required: true
+ type: string
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: Space
+ schema:
+ $ref: '#/definitions/space.SpaceResponse'
+ "401":
+ description: Unauthorized
+ schema:
+ $ref: '#/definitions/util.UnauthorizedError'
+ "404":
+ description: Space not found
+ schema:
+ $ref: '#/definitions/util.NotFoundError'
+ "500":
+ description: Internal server error
+ schema:
+ $ref: '#/definitions/util.ServerError'
+ summary: Get space
+ tags:
+ - spaces
/spaces/{space_id}/members:
get:
consumes:
@@ -693,6 +874,43 @@ paths:
summary: List members
tags:
- spaces
+ /spaces/{space_id}/members/{member_id}:
+ get:
+ consumes:
+ - application/json
+ parameters:
+ - description: Space ID
+ in: path
+ name: space_id
+ required: true
+ type: string
+ - description: Member ID
+ in: path
+ name: member_id
+ required: true
+ type: string
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: Member
+ schema:
+ $ref: '#/definitions/space.MemberResponse'
+ "401":
+ description: Unauthorized
+ schema:
+ $ref: '#/definitions/util.UnauthorizedError'
+ "404":
+ description: Member not found
+ schema:
+ $ref: '#/definitions/util.NotFoundError'
+ "500":
+ description: Internal server error
+ schema:
+ $ref: '#/definitions/util.ServerError'
+ summary: Get member
+ tags:
+ - spaces
/spaces/{space_id}/objects:
get:
consumes:
@@ -763,6 +981,10 @@ paths:
description: Unauthorized
schema:
$ref: '#/definitions/util.UnauthorizedError'
+ "423":
+ description: Rate limit exceeded
+ schema:
+ $ref: '#/definitions/util.RateLimitError'
"500":
description: Internal server error
schema:
@@ -804,6 +1026,10 @@ paths:
description: Resource not found
schema:
$ref: '#/definitions/util.NotFoundError'
+ "423":
+ description: Rate limit exceeded
+ schema:
+ $ref: '#/definitions/util.RateLimitError'
"500":
description: Internal server error
schema:
diff --git a/core/api/internal/auth/model.go b/core/api/internal/auth/model.go
index 2d34926f56..221797cd36 100644
--- a/core/api/internal/auth/model.go
+++ b/core/api/internal/auth/model.go
@@ -1,10 +1,10 @@
package auth
type DisplayCodeResponse struct {
- ChallengeId string `json:"challenge_id" example:"67647f5ecda913e9a2e11b26"`
+ ChallengeId string `json:"challenge_id" example:"67647f5ecda913e9a2e11b26"` // The challenge id associated with the displayed code and needed to solve the challenge for token
}
type TokenResponse struct {
- SessionToken string `json:"session_token" example:"eyJhbGciOeJIRzI1NiIsInR5cCI6IkpXVCJ1.eyJzZWVkIjaiY0dmVndlUnAifQ.Y1EZecYnwmvMkrXKOa2XJnAbaRt34urBabe06tmDQII"`
- AppKey string `json:"app_key" example:"zhSG/zQRmgADyilWPtgdnfo1qD60oK02/SVgi1GaFt6="`
+ SessionToken string `json:"session_token" example:"eyJhbGciOeJIRzI1NiIsInR5cCI6IkpXVCJ1.eyJzZWVkIjaiY0dmVndlUnAifQ.Y1EZecYnwmvMkrXKOa2XJnAbaRt34urBabe06tmDQII"` // The ephemeral session token
+ AppKey string `json:"app_key" example:"zhSG/zQRmgADyilWPtgdnfo1qD60oK02/SVgi1GaFt6="` // The permanent app key
}
diff --git a/core/api/internal/export/model.go b/core/api/internal/export/model.go
index dde2422462..e6541b62bc 100644
--- a/core/api/internal/export/model.go
+++ b/core/api/internal/export/model.go
@@ -1,9 +1,9 @@
package export
type ObjectExportRequest struct {
- Path string `json:"path" example:"/path/to/export"`
+ Path string `json:"path" example:"/path/to/export"` // The path to export the object to
}
type ObjectExportResponse struct {
- Path string `json:"path" example:"/path/to/export"`
+ Path string `json:"path" example:"/path/to/export"` // The path the object was exported to
}
diff --git a/core/api/internal/object/handler.go b/core/api/internal/object/handler.go
index 671f255839..57c1e2e877 100644
--- a/core/api/internal/object/handler.go
+++ b/core/api/internal/object/handler.go
@@ -91,6 +91,7 @@ func GetObjectHandler(s *ObjectService) gin.HandlerFunc {
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
// @Failure 403 {object} util.ForbiddenError "Forbidden"
// @Failure 404 {object} util.NotFoundError "Resource not found"
+// @Failure 423 {object} util.RateLimitError "Rate limit exceeded"
// @Failure 500 {object} util.ServerError "Internal server error"
// @Router /spaces/{space_id}/objects/{object_id} [delete]
func DeleteObjectHandler(s *ObjectService) gin.HandlerFunc {
@@ -126,6 +127,7 @@ func DeleteObjectHandler(s *ObjectService) gin.HandlerFunc {
// @Success 200 {object} ObjectResponse "The created object"
// @Failure 400 {object} util.ValidationError "Bad request"
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 423 {object} util.RateLimitError "Rate limit exceeded"
// @Failure 500 {object} util.ServerError "Internal server error"
// @Router /spaces/{space_id}/objects [post]
func CreateObjectHandler(s *ObjectService) gin.HandlerFunc {
diff --git a/core/api/internal/object/model.go b/core/api/internal/object/model.go
index 70ba449aa0..d591214913 100644
--- a/core/api/internal/object/model.go
+++ b/core/api/internal/object/model.go
@@ -1,93 +1,93 @@
package object
type CreateObjectRequest struct {
- Name string `json:"name" example:"Object Name"`
- Icon string `json:"icon" example:"📄"`
- Description string `json:"description" example:"Object Description"`
- Body string `json:"body" example:"Object Body"`
- Source string `json:"source" example:"https://source.com"`
- TemplateId string `json:"template_id" example:"bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge"`
- ObjectTypeUniqueKey string `json:"object_type_unique_key" example:"ot-page"`
+ Name string `json:"name" example:"My object"` // The name of the object
+ Icon string `json:"icon" example:"📄"` // The icon of the object
+ Description string `json:"description" example:"This is a description of the object."` // The description of the object
+ Body string `json:"body" example:"This is the body of the object. Markdown syntax is supported here."` // The body of the object
+ Source string `json:"source" example:"https://bookmark-source.com"` // The source url, only applicable for bookmarks
+ TemplateId string `json:"template_id" example:"bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge"` // The id of the template to use
+ ObjectTypeUniqueKey string `json:"object_type_unique_key" example:"ot-page"` // The unique key of the object type
}
type ObjectResponse struct {
- Object Object `json:"object"`
+ Object Object `json:"object"` // The object
}
type Object struct {
- Type string `json:"type" example:"Page"`
- Id string `json:"id" example:"bafyreie6n5l5nkbjal37su54cha4coy7qzuhrnajluzv5qd5jvtsrxkequ"`
- Name string `json:"name" example:"Object Name"`
- Icon string `json:"icon" example:"📄"`
- Snippet string `json:"snippet" example:"The beginning of the object body..."`
- Layout string `json:"layout" example:"basic"`
- SpaceId string `json:"space_id" example:"bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1"`
- RootId string `json:"root_id" example:"bafyreicypzj6uvu54664ucv3hmbsd5cmdy2dv4fwua26sciq74khzpyn4u"`
- Blocks []Block `json:"blocks"`
- Details []Detail `json:"details"`
+ Type string `json:"type" example:"Page"` // The type of the object
+ Id string `json:"id" example:"bafyreie6n5l5nkbjal37su54cha4coy7qzuhrnajluzv5qd5jvtsrxkequ"` // The id of the object
+ Name string `json:"name" example:"My object"` // The name of the object
+ Icon string `json:"icon" example:"📄"` // The icon of the object
+ Snippet string `json:"snippet" example:"The beginning of the object body..."` // The snippet of the object, especially important for notes as they don't have a name
+ Layout string `json:"layout" example:"basic"` // The layout of the object
+ SpaceId string `json:"space_id" example:"bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1"` // The id of the space the object is in
+ RootId string `json:"root_id" example:"bafyreicypzj6uvu54664ucv3hmbsd5cmdy2dv4fwua26sciq74khzpyn4u"` // The id of the object's root
+ Blocks []Block `json:"blocks"` // The blocks of the object
+ Details []Detail `json:"details"` // The details of the object
}
type Block struct {
- Id string `json:"id" example:"64394517de52ad5acb89c66c"`
- ChildrenIds []string `json:"children_ids" example:"['6797ce8ecda913cde14b02dc']"`
- BackgroundColor string `json:"background_color" example:"red"`
- Align string `json:"align" enums:"AlignLeft,AlignCenter,AlignRight,AlignJustify" example:"AlignLeft"`
- VerticalAlign string `json:"vertical_align" enums:"VerticalAlignTop,VerticalAlignMiddle,VerticalAlignBottom" example:"VerticalAlignTop"`
- Text *Text `json:"text,omitempty"`
- File *File `json:"file,omitempty"`
+ Id string `json:"id" example:"64394517de52ad5acb89c66c"` // The id of the block
+ ChildrenIds []string `json:"children_ids" example:"['6797ce8ecda913cde14b02dc']"` // The ids of the block's children
+ BackgroundColor string `json:"background_color" example:"red"` // The background color of the block
+ Align string `json:"align" enums:"AlignLeft,AlignCenter,AlignRight,AlignJustify" example:"AlignLeft"` // The alignment of the block
+ VerticalAlign string `json:"vertical_align" enums:"VerticalAlignTop,VerticalAlignMiddle,VerticalAlignBottom" example:"VerticalAlignTop"` // The vertical alignment of the block
+ Text *Text `json:"text,omitempty"` // The text of the block, if applicable
+ File *File `json:"file,omitempty"` // The file of the block, if applicable
}
type Text struct {
- Text string `json:"text" example:"Some text"`
- Style string `json:"style" enums:"Paragraph,Header1,Header2,Header3,Header4,Quote,Code,Title,Checkbox,Marked,Numbered,Toggle,Description,Callout" example:"Paragraph"`
- Checked bool `json:"checked" example:"true"`
- Color string `json:"color" example:"red"`
- Icon string `json:"icon" example:"📄"`
+ Text string `json:"text" example:"Some text..."` // The text
+ Style string `json:"style" enums:"Paragraph,Header1,Header2,Header3,Header4,Quote,Code,Title,Checkbox,Marked,Numbered,Toggle,Description,Callout" example:"Paragraph"` // The style of the text
+ Checked bool `json:"checked" example:"true"` // Whether the text is checked
+ Color string `json:"color" example:"red"` // The color of the text
+ Icon string `json:"icon" example:"📄"` // The icon of the text
}
type File struct {
- Hash string `json:"hash"`
- Name string `json:"name"`
- Type string `json:"type"`
- Mime string `json:"mime"`
- Size int `json:"size"`
- AddedAt int `json:"added_at"`
- TargetObjectId string `json:"target_object_id"`
- State string `json:"state"`
- Style string `json:"style"`
+ Hash string `json:"hash"` // The hash of the file
+ Name string `json:"name"` // The name of the file
+ Type string `json:"type"` // The type of the file
+ Mime string `json:"mime"` // The mime of the file
+ Size int `json:"size"` // The size of the file
+ AddedAt int `json:"added_at"` // The added at of the file
+ TargetObjectId string `json:"target_object_id"` // The target object id of the file
+ State string `json:"state"` // The state of the file
+ Style string `json:"style"` // The style of the file
}
type Detail struct {
- Id string `json:"id" enums:"last_modified_date,last_modified_by,created_date,created_by,last_opened_date,tags" example:"last_modified_date"`
- Details map[string]interface{} `json:"details"`
+ Id string `json:"id" enums:"last_modified_date,last_modified_by,created_date,created_by,last_opened_date,tags" example:"last_modified_date"` // The id of the detail
+ Details map[string]interface{} `json:"details"` // The details
}
type Tag struct {
- Id string `json:"id" example:"bafyreiaixlnaefu3ci22zdenjhsdlyaeeoyjrsid5qhfeejzlccijbj7sq"`
- Name string `json:"name" example:"Tag Name"`
- Color string `json:"color" example:"yellow"`
+ Id string `json:"id" example:"bafyreiaixlnaefu3ci22zdenjhsdlyaeeoyjrsid5qhfeejzlccijbj7sq"` // The id of the tag
+ Name string `json:"name" example:"in-progress"` // The name of the tag
+ Color string `json:"color" example:"yellow"` // The color of the tag
}
type TypeResponse struct {
- Type Type `json:"type"`
+ Type Type `json:"type"` // The type
}
type Type struct {
- Type string `json:"type" example:"type"`
- Id string `json:"id" example:"bafyreigyb6l5szohs32ts26ku2j42yd65e6hqy2u3gtzgdwqv6hzftsetu"`
- UniqueKey string `json:"unique_key" example:"ot-page"`
- Name string `json:"name" example:"Page"`
- Icon string `json:"icon" example:"📄"`
- RecommendedLayout string `json:"recommended_layout" example:"todo"`
+ Type string `json:"type" example:"type"` // The type of the object
+ Id string `json:"id" example:"bafyreigyb6l5szohs32ts26ku2j42yd65e6hqy2u3gtzgdwqv6hzftsetu"` // The id of the type
+ UniqueKey string `json:"unique_key" example:"ot-page"` // The unique key of the type
+ Name string `json:"name" example:"Page"` // The name of the type
+ Icon string `json:"icon" example:"📄"` // The icon of the type
+ RecommendedLayout string `json:"recommended_layout" example:"todo"` // The recommended layout of the type
}
type TemplateResponse struct {
- Template Template `json:"template"`
+ Template Template `json:"template"` // The template
}
type Template struct {
- Type string `json:"type" example:"template"`
- Id string `json:"id" example:"bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge"`
- Name string `json:"name" example:"Template Name"`
- Icon string `json:"icon" example:"📄"`
+ Type string `json:"type" example:"template"` // The type of the object
+ Id string `json:"id" example:"bafyreictrp3obmnf6dwejy5o4p7bderaaia4bdg2psxbfzf44yya5uutge"` // The id of the template
+ Name string `json:"name" example:"My template"` // The name of the template
+ Icon string `json:"icon" example:"📄"` // The icon of the template
}
diff --git a/core/api/internal/object/service.go b/core/api/internal/object/service.go
index 91efda7b20..284a588ad3 100644
--- a/core/api/internal/object/service.go
+++ b/core/api/internal/object/service.go
@@ -447,6 +447,16 @@ func (s *ObjectService) GetDetails(resp *pb.RpcObjectShowResponse) []Detail {
}
}
+ memberLastModifiedBy, err := s.spaceService.GetMember(context.Background(), resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeySpaceId.String()].GetStringValue(), lastModifiedById)
+ if err != nil {
+ memberLastModifiedBy = space.Member{}
+ }
+
+ memberCreator, err := s.spaceService.GetMember(context.Background(), resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeySpaceId.String()].GetStringValue(), creatorId)
+ if err != nil {
+ memberCreator = space.Member{}
+ }
+
return []Detail{
{
Id: "last_modified_date",
@@ -457,7 +467,7 @@ func (s *ObjectService) GetDetails(resp *pb.RpcObjectShowResponse) []Detail {
{
Id: "last_modified_by",
Details: map[string]interface{}{
- "details": s.spaceService.GetParticipantDetails(s.mw, resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeySpaceId.String()].GetStringValue(), lastModifiedById),
+ "details": memberLastModifiedBy,
},
},
{
@@ -469,7 +479,7 @@ func (s *ObjectService) GetDetails(resp *pb.RpcObjectShowResponse) []Detail {
{
Id: "created_by",
Details: map[string]interface{}{
- "details": s.spaceService.GetParticipantDetails(s.mw, resp.ObjectView.Details[0].Details.Fields[bundle.RelationKeySpaceId.String()].GetStringValue(), creatorId),
+ "details": memberCreator,
},
},
{
diff --git a/core/api/internal/object/service_test.go b/core/api/internal/object/service_test.go
index 10ba7e1c4d..5ae1f6ba25 100644
--- a/core/api/internal/object/service_test.go
+++ b/core/api/internal/object/service_test.go
@@ -390,7 +390,7 @@ func TestObjectService_CreateObject(t *testing.T) {
bundle.RelationKeyOrigin.String(): pbtypes.Int64(int64(model.ObjectOrigin_api)),
},
},
- TemplateId: "",
+ TemplateId: mockedTemplateId,
SpaceId: mockedSpaceId,
ObjectTypeUniqueKey: mockedObjectTypeUniqueKey,
WithChat: false,
@@ -483,10 +483,9 @@ func TestObjectService_CreateObject(t *testing.T) {
// when
object, err := fx.CreateObject(ctx, mockedSpaceId, CreateObjectRequest{
- Name: mockedObjectName,
- Icon: mockedObjectIcon,
- // TODO: use actual values
- TemplateId: "",
+ Name: mockedObjectName,
+ Icon: mockedObjectIcon,
+ TemplateId: mockedTemplateId,
ObjectTypeUniqueKey: mockedObjectTypeUniqueKey,
})
diff --git a/core/api/internal/search/model.go b/core/api/internal/search/model.go
index f52cf59e42..1709338418 100644
--- a/core/api/internal/search/model.go
+++ b/core/api/internal/search/model.go
@@ -1,12 +1,12 @@
package search
type SearchRequest struct {
- Query string `json:"query"`
- Types []string `json:"types"`
- Sort SortOptions `json:"sort"`
+ Query string `json:"query" example:"test"` // The search term to look for in object names and snippets
+ Types []string `json:"types" example:"ot-note,ot-page,ot-678043f0cda9133be777049f,bafyreightzrdts2ymxyaeyzspwdfo2juspyam76ewq6qq7ixnw3523gs7q"` // The types of objects to search for, specified by unique key or ID
+ Sort SortOptions `json:"sort"` // The sorting criteria and direction for the search results
}
type SortOptions struct {
- Direction string `json:"direction" enums:"asc,desc" default:"desc"`
- Timestamp string `json:"timestamp" enums:"created_date,last_modified_date,last_opened_date" default:"last_modified_date"`
+ Direction string `json:"direction" enums:"asc,desc" default:"desc"` // The direction to sort the search results
+ Timestamp string `json:"timestamp" enums:"created_date,last_modified_date,last_opened_date" default:"last_modified_date"` // The timestamp to sort the search results by
}
diff --git a/core/api/internal/search/service.go b/core/api/internal/search/service.go
index 58c783ef38..ecd2408718 100644
--- a/core/api/internal/search/service.go
+++ b/core/api/internal/search/service.go
@@ -48,7 +48,7 @@ func (s *SearchService) GlobalSearch(ctx context.Context, request SearchRequest,
baseFilters := s.prepareBaseFilters()
queryFilters := s.prepareQueryFilter(request.Query)
sorts := s.prepareSorts(request.Sort)
- dateToSortAfter := sorts.RelationKey
+ dateToSortAfter := sorts[0].RelationKey
allResponses := make([]*pb.RpcObjectSearchResponse, 0, len(spaces))
for _, space := range spaces {
@@ -59,7 +59,7 @@ func (s *SearchService) GlobalSearch(ctx context.Context, request SearchRequest,
objResp := s.mw.ObjectSearch(ctx, &pb.RpcObjectSearchRequest{
SpaceId: space.Id,
Filters: filters,
- Sorts: []*model.BlockContentDataviewSort{sorts},
+ Sorts: sorts,
Keys: []string{bundle.RelationKeyId.String(), bundle.RelationKeySpaceId.String(), dateToSortAfter},
Limit: int32(offset + limit), // nolint: gosec
})
@@ -91,7 +91,7 @@ func (s *SearchService) GlobalSearch(ctx context.Context, request SearchRequest,
}
// sort after posix last_modified_date to achieve descending sort order across all spaces
- sort.Slice(combinedRecords, func(i, j int) bool {
+ sort.SliceStable(combinedRecords, func(i, j int) bool {
return combinedRecords[i].DateToSortAfter > combinedRecords[j].DateToSortAfter
})
@@ -118,12 +118,12 @@ func (s *SearchService) Search(ctx context.Context, spaceId string, request Sear
filters := s.combineFilters(model.BlockContentDataviewFilter_And, baseFilters, queryFilters, typeFilters)
sorts := s.prepareSorts(request.Sort)
- dateToSortAfter := sorts.RelationKey
+ dateToSortAfter := sorts[0].RelationKey
resp := s.mw.ObjectSearch(ctx, &pb.RpcObjectSearchRequest{
SpaceId: spaceId,
Filters: filters,
- Sorts: []*model.BlockContentDataviewSort{sorts},
+ Sorts: sorts,
Keys: []string{bundle.RelationKeyId.String(), bundle.RelationKeySpaceId.String(), dateToSortAfter},
})
@@ -262,14 +262,28 @@ func (s *SearchService) prepareObjectTypeFilters(spaceId string, objectTypes []s
}
// prepareSorts returns a sort filter based on the given sort parameters
-func (s *SearchService) prepareSorts(sort SortOptions) *model.BlockContentDataviewSort {
- return &model.BlockContentDataviewSort{
+func (s *SearchService) prepareSorts(sort SortOptions) []*model.BlockContentDataviewSort {
+ primarySort := &model.BlockContentDataviewSort{
RelationKey: s.getSortRelationKey(sort.Timestamp),
Type: s.getSortDirection(sort.Direction),
Format: model.RelationFormat_date,
IncludeTime: true,
EmptyPlacement: model.BlockContentDataviewSort_NotSpecified,
}
+
+ // last_opened_date possibly is empty, wherefore we sort by last_modified_date as secondary criterion
+ if primarySort.RelationKey == bundle.RelationKeyLastOpenedDate.String() {
+ secondarySort := &model.BlockContentDataviewSort{
+ RelationKey: bundle.RelationKeyLastModifiedDate.String(),
+ Type: s.getSortDirection(sort.Direction),
+ Format: model.RelationFormat_date,
+ IncludeTime: true,
+ EmptyPlacement: model.BlockContentDataviewSort_NotSpecified,
+ }
+ return []*model.BlockContentDataviewSort{primarySort, secondarySort}
+ }
+
+ return []*model.BlockContentDataviewSort{primarySort}
}
// getSortRelationKey returns the relation key for the given sort timestamp
diff --git a/core/api/internal/space/handler.go b/core/api/internal/space/handler.go
index 2a6ca043de..5dbbd2cd83 100644
--- a/core/api/internal/space/handler.go
+++ b/core/api/internal/space/handler.go
@@ -42,6 +42,38 @@ func GetSpacesHandler(s *SpaceService) gin.HandlerFunc {
}
}
+// GetSpaceHandler retrieves a space
+//
+// @Summary Get space
+// @Tags spaces
+// @Accept json
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Success 200 {object} SpaceResponse "Space"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 404 {object} util.NotFoundError "Space not found"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Router /spaces/{space_id} [get]
+func GetSpaceHandler(s *SpaceService) gin.HandlerFunc {
+ return func(c *gin.Context) {
+ spaceId := c.Param("space_id")
+
+ space, err := s.GetSpace(c.Request.Context(), spaceId)
+ code := util.MapErrorCode(err,
+ util.ErrToCode(ErrWorkspaceNotFound, http.StatusNotFound),
+ util.ErrToCode(ErrFailedOpenWorkspace, http.StatusInternalServerError),
+ )
+
+ if code != http.StatusOK {
+ apiErr := util.CodeToAPIError(code, err.Error())
+ c.JSON(code, apiErr)
+ return
+ }
+
+ c.JSON(http.StatusOK, SpaceResponse{Space: space})
+ }
+}
+
// CreateSpaceHandler creates a new space
//
// @Summary Create space
@@ -49,9 +81,10 @@ func GetSpacesHandler(s *SpaceService) gin.HandlerFunc {
// @Accept json
// @Produce json
// @Param name body CreateSpaceRequest true "Space to create"
-// @Success 200 {object} CreateSpaceResponse "Space created successfully"
+// @Success 200 {object} SpaceResponse "Space created successfully"
// @Failure 400 {object} util.ValidationError "Bad request"
// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 423 {object} util.RateLimitError "Rate limit exceeded"
// @Failure 500 {object} util.ServerError "Internal server error"
// @Router /spaces [post]
func CreateSpaceHandler(s *SpaceService) gin.HandlerFunc {
@@ -74,7 +107,7 @@ func CreateSpaceHandler(s *SpaceService) gin.HandlerFunc {
return
}
- c.JSON(http.StatusOK, CreateSpaceResponse{Space: space})
+ c.JSON(http.StatusOK, SpaceResponse{Space: space})
}
}
@@ -111,3 +144,37 @@ func GetMembersHandler(s *SpaceService) gin.HandlerFunc {
pagination.RespondWithPagination(c, http.StatusOK, members, total, offset, limit, hasMore)
}
}
+
+// GetMemberHandler retrieves a member in a space
+//
+// @Summary Get member
+// @Tags spaces
+// @Accept json
+// @Produce json
+// @Param space_id path string true "Space ID"
+// @Param member_id path string true "Member ID"
+// @Success 200 {object} MemberResponse "Member"
+// @Failure 401 {object} util.UnauthorizedError "Unauthorized"
+// @Failure 404 {object} util.NotFoundError "Member not found"
+// @Failure 500 {object} util.ServerError "Internal server error"
+// @Router /spaces/{space_id}/members/{member_id} [get]
+func GetMemberHandler(s *SpaceService) gin.HandlerFunc {
+ return func(c *gin.Context) {
+ spaceId := c.Param("space_id")
+ memberId := c.Param("member_id")
+
+ member, err := s.GetMember(c.Request.Context(), spaceId, memberId)
+ code := util.MapErrorCode(err,
+ util.ErrToCode(ErrMemberNotFound, http.StatusNotFound),
+ util.ErrToCode(ErrFailedGetMember, http.StatusInternalServerError),
+ )
+
+ if code != http.StatusOK {
+ apiErr := util.CodeToAPIError(code, err.Error())
+ c.JSON(code, apiErr)
+ return
+ }
+
+ c.JSON(http.StatusOK, MemberResponse{Member: member})
+ }
+}
diff --git a/core/api/internal/space/model.go b/core/api/internal/space/model.go
index d13951c3f5..6805de3ccb 100644
--- a/core/api/internal/space/model.go
+++ b/core/api/internal/space/model.go
@@ -1,41 +1,45 @@
package space
-type CreateSpaceRequest struct {
- Name string `json:"name" example:"New Space"`
+type SpaceResponse struct {
+ Space Space `json:"space"` // The space
}
-type CreateSpaceResponse struct {
- Space Space `json:"space"`
+type CreateSpaceRequest struct {
+ Name string `json:"name" example:"New Space"` // The name of the space
}
type Space struct {
- Type string `json:"type" example:"space"`
- Id string `json:"id" example:"bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1"`
- Name string `json:"name" example:"Space Name"`
- Icon string `json:"icon" example:"http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay"`
- HomeObjectId string `json:"home_object_id" example:"bafyreie4qcl3wczb4cw5hrfyycikhjyh6oljdis3ewqrk5boaav3sbwqya"`
- ArchiveObjectId string `json:"archive_object_id" example:"bafyreialsgoyflf3etjm3parzurivyaukzivwortf32b4twnlwpwocsrri"`
- ProfileObjectId string `json:"profile_object_id" example:"bafyreiaxhwreshjqwndpwtdsu4mtihaqhhmlygqnyqpfyfwlqfq3rm3gw4"`
- MarketplaceWorkspaceId string `json:"marketplace_workspace_id" example:"_anytype_marketplace"`
- WorkspaceObjectId string `json:"workspace_object_id" example:"bafyreiapey2g6e6za4zfxvlgwdy4hbbfu676gmwrhnqvjbxvrchr7elr3y"`
- DeviceId string `json:"device_id" example:"12D3KooWGZMJ4kQVyQVXaj7gJPZr3RZ2nvd9M2Eq2pprEoPih9WF"`
- AccountSpaceId string `json:"account_space_id" example:"bafyreihpd2knon5wbljhtfeg3fcqtg3i2pomhhnigui6lrjmzcjzep7gcy.23me69r569oi1"`
- WidgetsId string `json:"widgets_id" example:"bafyreialj7pceh53mifm5dixlho47ke4qjmsn2uh4wsjf7xq2pnlo5xfva"`
- SpaceViewId string `json:"space_view_id" example:"bafyreigzv3vq7qwlrsin6njoduq727ssnhwd6bgyfj6nm4hv3pxoc2rxhy"`
- TechSpaceId string `json:"tech_space_id" example:"bafyreif4xuwncrjl6jajt4zrrfnylpki476nv2w64yf42ovt7gia7oypii.23me69r569oi1"`
- GatewayUrl string `json:"gateway_url" example:"http://127.0.0.1:31006"`
- LocalStoragePath string `json:"local_storage_path" example:"/Users/johndoe/Library/Application Support/Anytype/data/AAHTtt1wuQEnaYBNZ2Cyfcvs6DqPqxgn8VXDVk4avsUkMuha"`
- Timezone string `json:"timezone" example:""`
- AnalyticsId string `json:"analytics_id" example:"624aecdd-4797-4611-9d61-a2ae5f53cf1c"`
- NetworkId string `json:"network_id" example:"N83gJpVd9MuNRZAuJLZ7LiMntTThhPc6DtzWWVjb1M3PouVU"`
+ Type string `json:"type" example:"space"` // The type of the object
+ Id string `json:"id" example:"bafyreigyfkt6rbv24sbv5aq2hko3bhmv5xxlf22b4bypdu6j7hnphm3psq.23me69r569oi1"` // The id of the space
+ Name string `json:"name" example:"My Space"` // The name of the space
+ Icon string `json:"icon" example:"http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay"` // The icon of the space
+ HomeObjectId string `json:"home_object_id" example:"bafyreie4qcl3wczb4cw5hrfyycikhjyh6oljdis3ewqrk5boaav3sbwqya"` // The id of the home object
+ ArchiveObjectId string `json:"archive_object_id" example:"bafyreialsgoyflf3etjm3parzurivyaukzivwortf32b4twnlwpwocsrri"` // The id of the archive object
+ ProfileObjectId string `json:"profile_object_id" example:"bafyreiaxhwreshjqwndpwtdsu4mtihaqhhmlygqnyqpfyfwlqfq3rm3gw4"` // The id of the profile object
+ MarketplaceWorkspaceId string `json:"marketplace_workspace_id" example:"_anytype_marketplace"` // The id of the marketplace workspace
+ WorkspaceObjectId string `json:"workspace_object_id" example:"bafyreiapey2g6e6za4zfxvlgwdy4hbbfu676gmwrhnqvjbxvrchr7elr3y"` // The id of the workspace object
+ DeviceId string `json:"device_id" example:"12D3KooWGZMJ4kQVyQVXaj7gJPZr3RZ2nvd9M2Eq2pprEoPih9WF"` // The id of the device
+ AccountSpaceId string `json:"account_space_id" example:"bafyreihpd2knon5wbljhtfeg3fcqtg3i2pomhhnigui6lrjmzcjzep7gcy.23me69r569oi1"` // The id of the account space
+ WidgetsId string `json:"widgets_id" example:"bafyreialj7pceh53mifm5dixlho47ke4qjmsn2uh4wsjf7xq2pnlo5xfva"` // The id of the widgets
+ SpaceViewId string `json:"space_view_id" example:"bafyreigzv3vq7qwlrsin6njoduq727ssnhwd6bgyfj6nm4hv3pxoc2rxhy"` // The id of the space view
+ TechSpaceId string `json:"tech_space_id" example:"bafyreif4xuwncrjl6jajt4zrrfnylpki476nv2w64yf42ovt7gia7oypii.23me69r569oi1"` // The id of tech space, where objects outside of user's actual spaces are stored, e.g. spaces itself
+ GatewayUrl string `json:"gateway_url" example:"http://127.0.0.1:31006"` // The gateway url to serve files and media
+ LocalStoragePath string `json:"local_storage_path" example:"/Users/johndoe/Library/Application Support/Anytype/data/AAHTtt1wuQEnaYBNZ2Cyfcvs6DqPqxgn8VXDVk4avsUkMuha"` // The local storage path of the account
+ Timezone string `json:"timezone" example:""` // The timezone of the account
+ AnalyticsId string `json:"analytics_id" example:"624aecdd-4797-4611-9d61-a2ae5f53cf1c"` // The analytics id of the account
+ NetworkId string `json:"network_id" example:"N83gJpVd9MuNRZAuJLZ7LiMntTThhPc6DtzWWVjb1M3PouVU"` // The network id of the space
+}
+
+type MemberResponse struct {
+ Member Member `json:"member"` // The member
}
type Member struct {
- Type string `json:"type" example:"member"`
- Id string `json:"id" example:"_participant_bafyreigyfkt6rbv24sbv5aq2hko1bhmv5xxlf22b4bypdu6j7hnphm3psq_23me69r569oi1_AAjEaEwPF4nkEh9AWkqEnzcQ8HziBB4ETjiTpvRCQvWnSMDZ"`
- Name string `json:"name" example:"John Doe"`
- Icon string `json:"icon" example:"http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay?width=100"`
- Identity string `json:"identity" example:"AAjEaEwPF4nkEh7AWkqEnzcQ8HziGB4ETjiTpvRCQvWnSMDZ"`
- GlobalName string `json:"global_name" example:"john.any"`
- Role string `json:"role" enums:"Reader,Writer,Owner,NoPermission" example:"Owner"`
+ Type string `json:"type" example:"member"` // The type of the object
+ Id string `json:"id" example:"_participant_bafyreigyfkt6rbv24sbv5aq2hko1bhmv5xxlf22b4bypdu6j7hnphm3psq_23me69r569oi1_AAjEaEwPF4nkEh9AWkqEnzcQ8HziBB4ETjiTpvRCQvWnSMDZ"` // The profile object id of the member
+ Name string `json:"name" example:"John Doe"` // The name of the member
+ Icon string `json:"icon" example:"http://127.0.0.1:31006/image/bafybeieptz5hvcy6txplcvphjbbh5yjc2zqhmihs3owkh5oab4ezauzqay?width=100"` // The icon of the member
+ Identity string `json:"identity" example:"AAjEaEwPF4nkEh7AWkqEnzcQ8HziGB4ETjiTpvRCQvWnSMDZ"` // The identity of the member in the network
+ GlobalName string `json:"global_name" example:"john.any"` // The global name of the member in the network
+ Role string `json:"role" enums:"Reader,Writer,Owner,NoPermission" example:"Owner"` // The role of the member
}
diff --git a/core/api/internal/space/service.go b/core/api/internal/space/service.go
index 9a617b8472..eb83f636c7 100644
--- a/core/api/internal/space/service.go
+++ b/core/api/internal/space/service.go
@@ -20,15 +20,20 @@ import (
var (
ErrFailedListSpaces = errors.New("failed to retrieve list of spaces")
ErrFailedOpenWorkspace = errors.New("failed to open workspace")
+ ErrWorkspaceNotFound = errors.New("workspace not found")
ErrFailedGenerateRandomIcon = errors.New("failed to generate random icon")
ErrFailedCreateSpace = errors.New("failed to create space")
ErrFailedListMembers = errors.New("failed to retrieve list of members")
+ ErrFailedGetMember = errors.New("failed to retrieve member")
+ ErrMemberNotFound = errors.New("member not found")
)
type Service interface {
ListSpaces(ctx context.Context, offset int, limit int) ([]Space, int, bool, error)
+ GetSpace(ctx context.Context, spaceId string) (Space, error)
CreateSpace(ctx context.Context, name string) (Space, error)
ListMembers(ctx context.Context, spaceId string, offset int, limit int) ([]Member, int, bool, error)
+ GetMember(ctx context.Context, spaceId string, memberId string) (Member, error)
}
type SpaceService struct {
@@ -78,21 +83,55 @@ func (s *SpaceService) ListSpaces(ctx context.Context, offset int, limit int) (s
spaces = make([]Space, 0, len(paginatedRecords))
for _, record := range paginatedRecords {
- workspace, err := s.getWorkspaceInfo(record.Fields[bundle.RelationKeyTargetSpaceId.String()].GetStringValue())
+ name := record.Fields[bundle.RelationKeyName.String()].GetStringValue()
+ icon := util.GetIconFromEmojiOrImage(s.AccountInfo, record.Fields[bundle.RelationKeyIconEmoji.String()].GetStringValue(), record.Fields[bundle.RelationKeyIconImage.String()].GetStringValue())
+
+ workspace, err := s.getWorkspaceInfo(record.Fields[bundle.RelationKeyTargetSpaceId.String()].GetStringValue(), name, icon)
if err != nil {
return nil, 0, false, err
}
- // TODO: name and icon are only returned here; fix that
- workspace.Name = record.Fields[bundle.RelationKeyName.String()].GetStringValue()
- workspace.Icon = util.GetIconFromEmojiOrImage(s.AccountInfo, record.Fields[bundle.RelationKeyIconEmoji.String()].GetStringValue(), record.Fields[bundle.RelationKeyIconImage.String()].GetStringValue())
-
spaces = append(spaces, workspace)
}
return spaces, total, hasMore, nil
}
+// GetSpace returns the space info for the space with the given ID.
+func (s *SpaceService) GetSpace(ctx context.Context, spaceId string) (Space, error) {
+ // Check if the workspace exists and is active
+ resp := s.mw.ObjectSearch(ctx, &pb.RpcObjectSearchRequest{
+ SpaceId: s.AccountInfo.TechSpaceId,
+ Filters: []*model.BlockContentDataviewFilter{
+ {
+ Operator: model.BlockContentDataviewFilter_No,
+ RelationKey: bundle.RelationKeyTargetSpaceId.String(),
+ Condition: model.BlockContentDataviewFilter_Equal,
+ Value: pbtypes.String(spaceId),
+ },
+ {
+ Operator: model.BlockContentDataviewFilter_No,
+ RelationKey: bundle.RelationKeySpaceLocalStatus.String(),
+ Condition: model.BlockContentDataviewFilter_Equal,
+ Value: pbtypes.Int64(int64(model.SpaceStatus_Ok)),
+ },
+ },
+ Keys: []string{bundle.RelationKeyTargetSpaceId.String(), bundle.RelationKeyName.String(), bundle.RelationKeyIconEmoji.String(), bundle.RelationKeyIconImage.String()},
+ })
+
+ if resp.Error.Code != pb.RpcObjectSearchResponseError_NULL {
+ return Space{}, ErrFailedOpenWorkspace
+ }
+
+ if len(resp.Records) == 0 {
+ return Space{}, ErrWorkspaceNotFound
+ }
+
+ name := resp.Records[0].Fields[bundle.RelationKeyName.String()].GetStringValue()
+ icon := util.GetIconFromEmojiOrImage(s.AccountInfo, resp.Records[0].Fields[bundle.RelationKeyIconEmoji.String()].GetStringValue(), resp.Records[0].Fields[bundle.RelationKeyIconImage.String()].GetStringValue())
+ return s.getWorkspaceInfo(spaceId, name, icon)
+}
+
// CreateSpace creates a new space with the given name and returns the space info.
func (s *SpaceService) CreateSpace(ctx context.Context, name string) (Space, error) {
iconOption, err := rand.Int(rand.Reader, big.NewInt(13))
@@ -117,7 +156,7 @@ func (s *SpaceService) CreateSpace(ctx context.Context, name string) (Space, err
return Space{}, ErrFailedCreateSpace
}
- return s.getWorkspaceInfo(resp.SpaceId)
+ return s.getWorkspaceInfo(resp.SpaceId, name, "")
}
// ListMembers returns a paginated list of members in the space with the given ID.
@@ -174,26 +213,27 @@ func (s *SpaceService) ListMembers(ctx context.Context, spaceId string, offset i
return members, total, hasMore, nil
}
-func (s *SpaceService) GetParticipantDetails(mw service.ClientCommandsServer, spaceId string, participantId string) Member {
- resp := mw.ObjectSearch(context.Background(), &pb.RpcObjectSearchRequest{
+// GetMember returns the member with the given ID in the space with the given ID.
+func (s *SpaceService) GetMember(ctx context.Context, spaceId string, memberId string) (Member, error) {
+ resp := s.mw.ObjectSearch(context.Background(), &pb.RpcObjectSearchRequest{
SpaceId: spaceId,
Filters: []*model.BlockContentDataviewFilter{
{
Operator: model.BlockContentDataviewFilter_No,
RelationKey: bundle.RelationKeyId.String(),
Condition: model.BlockContentDataviewFilter_Equal,
- Value: pbtypes.String(participantId),
+ Value: pbtypes.String(memberId),
},
},
Keys: []string{bundle.RelationKeyId.String(), bundle.RelationKeyName.String(), bundle.RelationKeyIconEmoji.String(), bundle.RelationKeyIconImage.String(), bundle.RelationKeyIdentity.String(), bundle.RelationKeyGlobalName.String(), bundle.RelationKeyParticipantPermissions.String()},
})
if resp.Error.Code != pb.RpcObjectSearchResponseError_NULL {
- return Member{}
+ return Member{}, ErrFailedGetMember
}
if len(resp.Records) == 0 {
- return Member{}
+ return Member{}, ErrMemberNotFound
}
icon := util.GetIconFromEmojiOrImage(s.AccountInfo, "", resp.Records[0].Fields[bundle.RelationKeyIconImage.String()].GetStringValue())
@@ -206,11 +246,11 @@ func (s *SpaceService) GetParticipantDetails(mw service.ClientCommandsServer, sp
Identity: resp.Records[0].Fields[bundle.RelationKeyIdentity.String()].GetStringValue(),
GlobalName: resp.Records[0].Fields[bundle.RelationKeyGlobalName.String()].GetStringValue(),
Role: model.ParticipantPermissions_name[int32(resp.Records[0].Fields[bundle.RelationKeyParticipantPermissions.String()].GetNumberValue())],
- }
+ }, nil
}
// getWorkspaceInfo returns the workspace info for the space with the given ID.
-func (s *SpaceService) getWorkspaceInfo(spaceId string) (space Space, err error) {
+func (s *SpaceService) getWorkspaceInfo(spaceId string, name string, icon string) (space Space, err error) {
workspaceResponse := s.mw.WorkspaceOpen(context.Background(), &pb.RpcWorkspaceOpenRequest{
SpaceId: spaceId,
WithChat: true,
@@ -223,6 +263,8 @@ func (s *SpaceService) getWorkspaceInfo(spaceId string) (space Space, err error)
return Space{
Type: "space",
Id: spaceId,
+ Name: name,
+ Icon: icon,
HomeObjectId: workspaceResponse.Info.HomeObjectId,
ArchiveObjectId: workspaceResponse.Info.ArchiveObjectId,
ProfileObjectId: workspaceResponse.Info.ProfileObjectId,
diff --git a/core/api/pagination/model.go b/core/api/pagination/model.go
index 06539ce635..3d679fec48 100644
--- a/core/api/pagination/model.go
+++ b/core/api/pagination/model.go
@@ -1,13 +1,13 @@
package pagination
type PaginationMeta struct {
- Total int `json:"total" example:"1024"` // the total number of items available on that endpoint
- Offset int `json:"offset" example:"0"` // the current offset
- Limit int `json:"limit" example:"100"` // the current limit
- HasMore bool `json:"has_more" example:"true"` // whether there are more items available
+ Total int `json:"total" example:"1024"` // The total number of items available for the endpoint
+ Offset int `json:"offset" example:"0"` // The number of items skipped before starting to collect the result set
+ Limit int `json:"limit" example:"100"` // The maximum number of items returned in the result set
+ HasMore bool `json:"has_more" example:"true"` // Indicates if there are more items available beyond the current result set
}
type PaginatedResponse[T any] struct {
- Data []T `json:"data"`
- Pagination PaginationMeta `json:"pagination"`
+ Data []T `json:"data"` // The list of items in the current result set
+ Pagination PaginationMeta `json:"pagination"` // The pagination metadata for the response
}
diff --git a/core/api/server/middleware.go b/core/api/server/middleware.go
index da05740b8c..d2a2d23c94 100644
--- a/core/api/server/middleware.go
+++ b/core/api/server/middleware.go
@@ -11,6 +11,7 @@ import (
"github.com/gin-gonic/gin"
"github.com/anyproto/anytype-heart/core/anytype/account"
+ "github.com/anyproto/anytype-heart/core/api/util"
"github.com/anyproto/anytype-heart/pb"
"github.com/anyproto/anytype-heart/pb/service"
)
@@ -26,7 +27,8 @@ func (s *Server) rateLimit(max float64) gin.HandlerFunc {
return func(c *gin.Context) {
httpError := tollbooth.LimitByRequest(lmt, c.Writer, c.Request)
if httpError != nil {
- c.AbortWithStatusJSON(httpError.StatusCode, gin.H{"error": httpError.Message})
+ apiErr := util.CodeToAPIError(httpError.StatusCode, httpError.Message)
+ c.AbortWithStatusJSON(httpError.StatusCode, apiErr)
return
}
c.Next()
@@ -38,12 +40,14 @@ func (s *Server) ensureAuthenticated(mw service.ClientCommandsServer) gin.Handle
return func(c *gin.Context) {
authHeader := c.GetHeader("Authorization")
if authHeader == "" {
- c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Missing Authorization header"})
+ apiErr := util.CodeToAPIError(http.StatusUnauthorized, "Missing Authorization header")
+ c.AbortWithStatusJSON(http.StatusUnauthorized, apiErr)
return
}
if !strings.HasPrefix(authHeader, "Bearer ") {
- c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid Authorization header format"})
+ apiErr := util.CodeToAPIError(http.StatusUnauthorized, "Invalid Authorization header format")
+ c.AbortWithStatusJSON(http.StatusUnauthorized, apiErr)
return
}
key := strings.TrimPrefix(authHeader, "Bearer ")
@@ -57,7 +61,8 @@ func (s *Server) ensureAuthenticated(mw service.ClientCommandsServer) gin.Handle
if !exists {
response := mw.WalletCreateSession(context.Background(), &pb.RpcWalletCreateSessionRequest{Auth: &pb.RpcWalletCreateSessionRequestAuthOfAppKey{AppKey: key}})
if response.Error.Code != pb.RpcWalletCreateSessionResponseError_NULL {
- c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
+ apiErr := util.CodeToAPIError(http.StatusUnauthorized, "Invalid token")
+ c.AbortWithStatusJSON(http.StatusUnauthorized, apiErr)
return
}
token = response.Token
@@ -78,7 +83,8 @@ func (s *Server) ensureAccountInfo(accountService account.Service) gin.HandlerFu
return func(c *gin.Context) {
accInfo, err := accountService.GetInfo(context.Background())
if err != nil {
- c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("failed to get account info: %v", err)})
+ apiErr := util.CodeToAPIError(http.StatusInternalServerError, fmt.Sprintf("failed to get account info: %v", err))
+ c.AbortWithStatusJSON(http.StatusInternalServerError, apiErr)
return
}
diff --git a/core/api/server/router.go b/core/api/server/router.go
index e33206a325..ed1b00a990 100644
--- a/core/api/server/router.go
+++ b/core/api/server/router.go
@@ -78,7 +78,9 @@ func (s *Server) NewRouter(accountService account.Service, mw service.ClientComm
// Space
v1.GET("/spaces", space.GetSpacesHandler(s.spaceService))
+ v1.GET("/spaces/:space_id", space.GetSpaceHandler(s.spaceService))
v1.GET("/spaces/:space_id/members", space.GetMembersHandler(s.spaceService))
+ v1.GET("/spaces/:space_id/members/:member_id", space.GetMemberHandler(s.spaceService))
v1.POST("/spaces", s.rateLimit(maxWriteRequestsPerSecond), space.CreateSpaceHandler(s.spaceService))
// Type
diff --git a/core/api/util/error.go b/core/api/util/error.go
index b7553f3fd2..77aeff751e 100644
--- a/core/api/util/error.go
+++ b/core/api/util/error.go
@@ -5,38 +5,45 @@ import (
"net/http"
)
-// 400
+// ValidationError is a struct for 400 errors
type ValidationError struct {
Error struct {
- Message string `json:"message"`
+ Message string `json:"message" example:"Bad request"`
} `json:"error"`
}
-// 401
+// UnauthorizedError is a struct for 401 errors
type UnauthorizedError struct {
Error struct {
- Message string `json:"message"`
+ Message string `json:"message" example:"Unauthorized"`
} `json:"error"`
}
-// 403
+// ForbiddenError is a struct for 403 errors
type ForbiddenError struct {
Error struct {
- Message string `json:"message"`
+ Message string `json:"message" example:"Forbidden"`
} `json:"error"`
}
-// 404
+// NotFoundError is a struct for 404 errors
type NotFoundError struct {
Error struct {
- Message string `json:"message"`
+ Message string `json:"message" example:"Resource not found"`
} `json:"error"`
}
-// 500
+// RateLimitError is a struct for 423 errors
+type RateLimitError struct {
+ Error struct {
+ Message string `json:"message" example:"Rate limit exceeded"`
+ } `json:"error"`
+}
+
+// ServerError is a struct for 500 errors
type ServerError struct {
Error struct {
- Message string `json:"message"`
+ Message string `json:"message" example:"Internal server error"`
} `json:"error"`
}
@@ -72,10 +79,11 @@ func MapErrorCode(err error, mappings ...errCodeMapping) int {
// for the given HTTP code, embedding the supplied message.
func CodeToAPIError(code int, message string) any {
switch code {
- case http.StatusNotFound:
- return NotFoundError{
+
+ case http.StatusBadRequest:
+ return ValidationError{
Error: struct {
- Message string `json:"message"`
+ Message string `json:"message" example:"Bad request"`
}{
Message: message,
},
@@ -84,16 +92,34 @@ func CodeToAPIError(code int, message string) any {
case http.StatusUnauthorized:
return UnauthorizedError{
Error: struct {
- Message string `json:"message"`
+ Message string `json:"message" example:"Unauthorized"`
}{
Message: message,
},
}
- case http.StatusBadRequest:
- return ValidationError{
+ case http.StatusForbidden:
+ return ForbiddenError{
+ Error: struct {
+ Message string `json:"message" example:"Forbidden"`
+ }{
+ Message: message,
+ },
+ }
+
+ case http.StatusNotFound:
+ return NotFoundError{
+ Error: struct {
+ Message string `json:"message" example:"Resource not found"`
+ }{
+ Message: message,
+ },
+ }
+
+ case http.StatusTooManyRequests:
+ return RateLimitError{
Error: struct {
- Message string `json:"message"`
+ Message string `json:"message" example:"Rate limit exceeded"`
}{
Message: message,
},
@@ -102,7 +128,7 @@ func CodeToAPIError(code int, message string) any {
default:
return ServerError{
Error: struct {
- Message string `json:"message"`
+ Message string `json:"message" example:"Internal server error"`
}{
Message: message,
},