mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
chore: tweak resource definition
This commit is contained in:
@ -146,19 +146,19 @@ UpdateInbox updates an inbox.
|
||||
#### GET
|
||||
##### Summary
|
||||
|
||||
GetMemo gets a memo.
|
||||
GetResource returns a resource by name.
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ------ |
|
||||
| name_1 | path | The name of the memo. Format: memos/{id} | Yes | string |
|
||||
| name_1 | path | | Yes | string |
|
||||
|
||||
##### Responses
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | A successful response. | [v2GetMemoResponse](#v2getmemoresponse) |
|
||||
| 200 | A successful response. | [v2GetResourceResponse](#v2getresourceresponse) |
|
||||
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
|
||||
|
||||
#### DELETE
|
||||
@ -288,7 +288,7 @@ ExportMemos exports memos.
|
||||
#### GET
|
||||
##### Summary
|
||||
|
||||
SearchMemosRequest searches memos.
|
||||
SearchMemos searches memos.
|
||||
|
||||
##### Parameters
|
||||
|
||||
@ -324,7 +324,7 @@ UpdateMemo updates a memo.
|
||||
| 200 | A successful response. | [v2UpdateMemoResponse](#v2updatememoresponse) |
|
||||
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
|
||||
|
||||
### /api/v2/{name_1}
|
||||
### /api/v2/{name_2}
|
||||
|
||||
#### GET
|
||||
##### Summary
|
||||
@ -335,7 +335,7 @@ GetMemo gets a memo.
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ------ |
|
||||
| name_1 | path | The name of the memo. Format: memos/{id} | Yes | string |
|
||||
| name_2 | path | The name of the memo. Format: memos/{id} | Yes | string |
|
||||
|
||||
##### Responses
|
||||
|
||||
@ -347,22 +347,22 @@ GetMemo gets a memo.
|
||||
#### DELETE
|
||||
##### Summary
|
||||
|
||||
DeleteInbox deletes an inbox.
|
||||
DeleteResource deletes a resource by name.
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ------ |
|
||||
| name_1 | path | The name of the inbox to delete. Format: inboxes/{uid} | Yes | string |
|
||||
| name_2 | path | | Yes | string |
|
||||
|
||||
##### Responses
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | A successful response. | [v2DeleteInboxResponse](#v2deleteinboxresponse) |
|
||||
| 200 | A successful response. | [v2DeleteResourceResponse](#v2deleteresourceresponse) |
|
||||
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
|
||||
|
||||
### /api/v2/{name_2}
|
||||
### /api/v2/{name_3}
|
||||
|
||||
#### DELETE
|
||||
##### Summary
|
||||
@ -373,7 +373,7 @@ DeleteMemo deletes a memo.
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ------ |
|
||||
| name_2 | path | The name of the memo. Format: memos/{id} | Yes | string |
|
||||
| name_3 | path | The name of the memo. Format: memos/{id} | Yes | string |
|
||||
|
||||
##### Responses
|
||||
|
||||
@ -601,38 +601,38 @@ CreateResource creates a new resource.
|
||||
| 200 | A successful response. | [v2CreateResourceResponse](#v2createresourceresponse) |
|
||||
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
|
||||
|
||||
### /api/v2/resources/name/{name}
|
||||
### /api/v2/resources:search
|
||||
|
||||
#### GET
|
||||
##### Summary
|
||||
|
||||
GetResourceByName returns a resource by name.
|
||||
SearchResources searches memos.
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ------ |
|
||||
| name | path | | Yes | string |
|
||||
| filter | query | | No | string |
|
||||
|
||||
##### Responses
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | A successful response. | [v2GetResourceByNameResponse](#v2getresourcebynameresponse) |
|
||||
| 200 | A successful response. | [v2SearchResourcesResponse](#v2searchresourcesresponse) |
|
||||
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
|
||||
|
||||
### /api/v2/resources/{id}
|
||||
### /api/v2/{name_1}
|
||||
|
||||
#### GET
|
||||
##### Summary
|
||||
|
||||
GetResource returns a resource by id.
|
||||
GetResource returns a resource by name.
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ------ |
|
||||
| id | path | | Yes | integer |
|
||||
| name_1 | path | | Yes | string |
|
||||
|
||||
##### Responses
|
||||
|
||||
@ -644,13 +644,51 @@ GetResource returns a resource by id.
|
||||
#### DELETE
|
||||
##### Summary
|
||||
|
||||
DeleteResource deletes a resource by id.
|
||||
DeleteInbox deletes an inbox.
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ------ |
|
||||
| id | path | | Yes | integer |
|
||||
| name_1 | path | The name of the inbox to delete. Format: inboxes/{uid} | Yes | string |
|
||||
|
||||
##### Responses
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | A successful response. | [v2DeleteInboxResponse](#v2deleteinboxresponse) |
|
||||
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
|
||||
|
||||
### /api/v2/{name_2}
|
||||
|
||||
#### GET
|
||||
##### Summary
|
||||
|
||||
GetMemo gets a memo.
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ------ |
|
||||
| name_2 | path | The name of the memo. Format: memos/{id} | Yes | string |
|
||||
|
||||
##### Responses
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | A successful response. | [v2GetMemoResponse](#v2getmemoresponse) |
|
||||
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
|
||||
|
||||
#### DELETE
|
||||
##### Summary
|
||||
|
||||
DeleteResource deletes a resource by name.
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ------ |
|
||||
| name_2 | path | | Yes | string |
|
||||
|
||||
##### Responses
|
||||
|
||||
@ -659,7 +697,7 @@ DeleteResource deletes a resource by id.
|
||||
| 200 | A successful response. | [v2DeleteResourceResponse](#v2deleteresourceresponse) |
|
||||
| default | An unexpected error response. | [googlerpcStatus](#googlerpcstatus) |
|
||||
|
||||
### /api/v2/resources/{resource.id}
|
||||
### /api/v2/{resource.name}
|
||||
|
||||
#### PATCH
|
||||
##### Summary
|
||||
@ -670,8 +708,8 @@ UpdateResource updates a resource.
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ------ |
|
||||
| resource.id | path | id is the system generated unique identifier. | Yes | integer |
|
||||
| resource | body | | Yes | { **"name"**: string, **"createTime"**: dateTime, **"filename"**: string, **"externalLink"**: string, **"type"**: string, **"size"**: string (int64), **"memoId"**: integer } |
|
||||
| resource.name | path | The name of the resource. Format: resources/{id} id is the system generated unique identifier. | Yes | string |
|
||||
| resource | body | | Yes | { **"uid"**: string, **"createTime"**: dateTime, **"filename"**: string, **"externalLink"**: string, **"type"**: string, **"size"**: string (int64), **"memoId"**: integer } |
|
||||
|
||||
##### Responses
|
||||
|
||||
@ -1463,12 +1501,6 @@ GetActivity returns the activity with the given id.
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| memo | [v2Memo](#v2memo) | | No |
|
||||
|
||||
#### v2GetResourceByNameResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| resource | [v2Resource](#v2resource) | | No |
|
||||
|
||||
#### v2GetResourceResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
@ -1659,8 +1691,8 @@ GetActivity returns the activity with the given id.
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| id | integer | id is the system generated unique identifier. | No |
|
||||
| name | string | name is the user provided name. | No |
|
||||
| name | string | The name of the resource. Format: resources/{id} id is the system generated unique identifier. | No |
|
||||
| uid | string | The user defined id of the resource. | No |
|
||||
| createTime | dateTime | | No |
|
||||
| filename | string | | No |
|
||||
| externalLink | string | | No |
|
||||
@ -1674,6 +1706,12 @@ GetActivity returns the activity with the given id.
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| memos | [ [v2Memo](#v2memo) ] | | No |
|
||||
|
||||
#### v2SearchResourcesResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| resources | [ [v2Resource](#v2resource) ] | | No |
|
||||
|
||||
#### v2SearchUsersResponse
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|
@ -285,7 +285,7 @@ paths:
|
||||
- MemoService
|
||||
/api/v2/memos:search:
|
||||
get:
|
||||
summary: SearchMemosRequest searches memos.
|
||||
summary: SearchMemos searches memos.
|
||||
operationId: MemoService_SearchMemos
|
||||
responses:
|
||||
"200":
|
||||
@ -353,113 +353,26 @@ paths:
|
||||
format: int32
|
||||
tags:
|
||||
- ResourceService
|
||||
/api/v2/resources/name/{name}:
|
||||
/api/v2/resources:search:
|
||||
get:
|
||||
summary: GetResourceByName returns a resource by name.
|
||||
operationId: ResourceService_GetResourceByName
|
||||
summary: SearchResources searches memos.
|
||||
operationId: ResourceService_SearchResources
|
||||
responses:
|
||||
"200":
|
||||
description: A successful response.
|
||||
schema:
|
||||
$ref: '#/definitions/v2GetResourceByNameResponse'
|
||||
$ref: '#/definitions/v2SearchResourcesResponse'
|
||||
default:
|
||||
description: An unexpected error response.
|
||||
schema:
|
||||
$ref: '#/definitions/googlerpcStatus'
|
||||
parameters:
|
||||
- name: name
|
||||
in: path
|
||||
required: true
|
||||
- name: filter
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
tags:
|
||||
- ResourceService
|
||||
/api/v2/resources/{id}:
|
||||
get:
|
||||
summary: GetResource returns a resource by id.
|
||||
operationId: ResourceService_GetResource
|
||||
responses:
|
||||
"200":
|
||||
description: A successful response.
|
||||
schema:
|
||||
$ref: '#/definitions/v2GetResourceResponse'
|
||||
default:
|
||||
description: An unexpected error response.
|
||||
schema:
|
||||
$ref: '#/definitions/googlerpcStatus'
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
type: integer
|
||||
format: int32
|
||||
tags:
|
||||
- ResourceService
|
||||
delete:
|
||||
summary: DeleteResource deletes a resource by id.
|
||||
operationId: ResourceService_DeleteResource
|
||||
responses:
|
||||
"200":
|
||||
description: A successful response.
|
||||
schema:
|
||||
$ref: '#/definitions/v2DeleteResourceResponse'
|
||||
default:
|
||||
description: An unexpected error response.
|
||||
schema:
|
||||
$ref: '#/definitions/googlerpcStatus'
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
type: integer
|
||||
format: int32
|
||||
tags:
|
||||
- ResourceService
|
||||
/api/v2/resources/{resource.id}:
|
||||
patch:
|
||||
summary: UpdateResource updates a resource.
|
||||
operationId: ResourceService_UpdateResource
|
||||
responses:
|
||||
"200":
|
||||
description: A successful response.
|
||||
schema:
|
||||
$ref: '#/definitions/v2UpdateResourceResponse'
|
||||
default:
|
||||
description: An unexpected error response.
|
||||
schema:
|
||||
$ref: '#/definitions/googlerpcStatus'
|
||||
parameters:
|
||||
- name: resource.id
|
||||
description: id is the system generated unique identifier.
|
||||
in: path
|
||||
required: true
|
||||
type: integer
|
||||
format: int32
|
||||
- name: resource
|
||||
in: body
|
||||
required: true
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: name is the user provided name.
|
||||
createTime:
|
||||
type: string
|
||||
format: date-time
|
||||
filename:
|
||||
type: string
|
||||
externalLink:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
size:
|
||||
type: string
|
||||
format: int64
|
||||
memoId:
|
||||
type: integer
|
||||
format: int32
|
||||
tags:
|
||||
- ResourceService
|
||||
/api/v2/tags:
|
||||
get:
|
||||
summary: ListTags lists tags.
|
||||
@ -978,28 +891,25 @@ paths:
|
||||
- MemoService
|
||||
/api/v2/{name_1}:
|
||||
get:
|
||||
summary: GetMemo gets a memo.
|
||||
operationId: MemoService_GetMemo
|
||||
summary: GetResource returns a resource by name.
|
||||
operationId: ResourceService_GetResource
|
||||
responses:
|
||||
"200":
|
||||
description: A successful response.
|
||||
schema:
|
||||
$ref: '#/definitions/v2GetMemoResponse'
|
||||
$ref: '#/definitions/v2GetResourceResponse'
|
||||
default:
|
||||
description: An unexpected error response.
|
||||
schema:
|
||||
$ref: '#/definitions/googlerpcStatus'
|
||||
parameters:
|
||||
- name: name_1
|
||||
description: |-
|
||||
The name of the memo.
|
||||
Format: memos/{id}
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
pattern: memos/[^/]+
|
||||
pattern: resources/[^/]+
|
||||
tags:
|
||||
- MemoService
|
||||
- ResourceService
|
||||
delete:
|
||||
summary: DeleteInbox deletes an inbox.
|
||||
operationId: InboxService_DeleteInbox
|
||||
@ -1024,6 +934,50 @@ paths:
|
||||
tags:
|
||||
- InboxService
|
||||
/api/v2/{name_2}:
|
||||
get:
|
||||
summary: GetMemo gets a memo.
|
||||
operationId: MemoService_GetMemo
|
||||
responses:
|
||||
"200":
|
||||
description: A successful response.
|
||||
schema:
|
||||
$ref: '#/definitions/v2GetMemoResponse'
|
||||
default:
|
||||
description: An unexpected error response.
|
||||
schema:
|
||||
$ref: '#/definitions/googlerpcStatus'
|
||||
parameters:
|
||||
- name: name_2
|
||||
description: |-
|
||||
The name of the memo.
|
||||
Format: memos/{id}
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
pattern: memos/[^/]+
|
||||
tags:
|
||||
- MemoService
|
||||
delete:
|
||||
summary: DeleteResource deletes a resource by name.
|
||||
operationId: ResourceService_DeleteResource
|
||||
responses:
|
||||
"200":
|
||||
description: A successful response.
|
||||
schema:
|
||||
$ref: '#/definitions/v2DeleteResourceResponse'
|
||||
default:
|
||||
description: An unexpected error response.
|
||||
schema:
|
||||
$ref: '#/definitions/googlerpcStatus'
|
||||
parameters:
|
||||
- name: name_2
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
pattern: resources/[^/]+
|
||||
tags:
|
||||
- ResourceService
|
||||
/api/v2/{name_3}:
|
||||
delete:
|
||||
summary: DeleteMemo deletes a memo.
|
||||
operationId: MemoService_DeleteMemo
|
||||
@ -1037,7 +991,7 @@ paths:
|
||||
schema:
|
||||
$ref: '#/definitions/googlerpcStatus'
|
||||
parameters:
|
||||
- name: name_2
|
||||
- name: name_3
|
||||
description: |-
|
||||
The name of the memo.
|
||||
Format: memos/{id}
|
||||
@ -1475,6 +1429,55 @@ paths:
|
||||
pattern: users/[^/]+
|
||||
tags:
|
||||
- UserService
|
||||
/api/v2/{resource.name}:
|
||||
patch:
|
||||
summary: UpdateResource updates a resource.
|
||||
operationId: ResourceService_UpdateResource
|
||||
responses:
|
||||
"200":
|
||||
description: A successful response.
|
||||
schema:
|
||||
$ref: '#/definitions/v2UpdateResourceResponse'
|
||||
default:
|
||||
description: An unexpected error response.
|
||||
schema:
|
||||
$ref: '#/definitions/googlerpcStatus'
|
||||
parameters:
|
||||
- name: resource.name
|
||||
description: |-
|
||||
The name of the resource.
|
||||
Format: resources/{id}
|
||||
id is the system generated unique identifier.
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
pattern: resources/[^/]+
|
||||
- name: resource
|
||||
in: body
|
||||
required: true
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
uid:
|
||||
type: string
|
||||
description: The user defined id of the resource.
|
||||
createTime:
|
||||
type: string
|
||||
format: date-time
|
||||
filename:
|
||||
type: string
|
||||
externalLink:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
size:
|
||||
type: string
|
||||
format: int64
|
||||
memoId:
|
||||
type: integer
|
||||
format: int32
|
||||
tags:
|
||||
- ResourceService
|
||||
/api/v2/{setting.name}:
|
||||
patch:
|
||||
summary: UpdateUserSetting updates the setting of a user.
|
||||
@ -1882,11 +1885,6 @@ definitions:
|
||||
properties:
|
||||
memo:
|
||||
$ref: '#/definitions/v2Memo'
|
||||
v2GetResourceByNameResponse:
|
||||
type: object
|
||||
properties:
|
||||
resource:
|
||||
$ref: '#/definitions/v2Resource'
|
||||
v2GetResourceResponse:
|
||||
type: object
|
||||
properties:
|
||||
@ -2161,13 +2159,15 @@ definitions:
|
||||
v2Resource:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int32
|
||||
description: id is the system generated unique identifier.
|
||||
name:
|
||||
type: string
|
||||
description: name is the user provided name.
|
||||
description: |-
|
||||
The name of the resource.
|
||||
Format: resources/{id}
|
||||
id is the system generated unique identifier.
|
||||
uid:
|
||||
type: string
|
||||
description: The user defined id of the resource.
|
||||
createTime:
|
||||
type: string
|
||||
format: date-time
|
||||
@ -2191,6 +2191,14 @@ definitions:
|
||||
items:
|
||||
type: object
|
||||
$ref: '#/definitions/v2Memo'
|
||||
v2SearchResourcesResponse:
|
||||
type: object
|
||||
properties:
|
||||
resources:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
$ref: '#/definitions/v2Resource'
|
||||
v2SearchUsersResponse:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -13,12 +13,12 @@ import (
|
||||
)
|
||||
|
||||
func (s *APIV2Service) SetMemoResources(ctx context.Context, request *apiv2pb.SetMemoResourcesRequest) (*apiv2pb.SetMemoResourcesResponse, error) {
|
||||
id, err := ExtractMemoIDFromName(request.Name)
|
||||
memoID, err := ExtractMemoIDFromName(request.Name)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "invalid memo name: %v", err)
|
||||
}
|
||||
resources, err := s.Store.ListResources(ctx, &store.FindResource{
|
||||
MemoID: &id,
|
||||
MemoID: &memoID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed to list resources")
|
||||
@ -28,7 +28,7 @@ func (s *APIV2Service) SetMemoResources(ctx context.Context, request *apiv2pb.Se
|
||||
for _, resource := range resources {
|
||||
found := false
|
||||
for _, requestResource := range request.Resources {
|
||||
if resource.ID == int32(requestResource.Id) {
|
||||
if resource.UID == requestResource.Uid {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
@ -36,7 +36,7 @@ func (s *APIV2Service) SetMemoResources(ctx context.Context, request *apiv2pb.Se
|
||||
if !found {
|
||||
if err = s.Store.DeleteResource(ctx, &store.DeleteResource{
|
||||
ID: int32(resource.ID),
|
||||
MemoID: &id,
|
||||
MemoID: &memoID,
|
||||
}); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed to delete resource")
|
||||
}
|
||||
@ -46,10 +46,14 @@ func (s *APIV2Service) SetMemoResources(ctx context.Context, request *apiv2pb.Se
|
||||
slices.Reverse(request.Resources)
|
||||
// Update resources' memo_id in the request.
|
||||
for index, resource := range request.Resources {
|
||||
id, err := ExtractMemoIDFromName(resource.Name)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "invalid resource name: %v", err)
|
||||
}
|
||||
updatedTs := time.Now().Unix() + int64(index)
|
||||
if _, err := s.Store.UpdateResource(ctx, &store.UpdateResource{
|
||||
ID: resource.Id,
|
||||
MemoID: &id,
|
||||
ID: id,
|
||||
MemoID: &memoID,
|
||||
UpdatedTs: &updatedTs,
|
||||
}); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed to update resource: %v", err)
|
||||
|
@ -874,7 +874,7 @@ func convertMemoToWebhookPayload(memo *apiv2pb.Memo) (*webhook.WebhookPayload, e
|
||||
resources := []*webhook.Resource{}
|
||||
for _, resource := range memo.Resources {
|
||||
resources = append(resources, &webhook.Resource{
|
||||
ID: resource.Id,
|
||||
UID: resource.Uid,
|
||||
Filename: resource.Filename,
|
||||
ExternalLink: resource.ExternalLink,
|
||||
Type: resource.Type,
|
||||
|
@ -13,6 +13,7 @@ const (
|
||||
WorkspaceSettingNamePrefix = "settings/"
|
||||
UserNamePrefix = "users/"
|
||||
MemoNamePrefix = "memos/"
|
||||
ResourceNamePrefix = "resources/"
|
||||
InboxNamePrefix = "inboxes/"
|
||||
)
|
||||
|
||||
@ -70,6 +71,19 @@ func ExtractMemoIDFromName(name string) (int32, error) {
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// ExtractResourceIDFromName returns the resource ID from a resource name.
|
||||
func ExtractResourceIDFromName(name string) (int32, error) {
|
||||
tokens, err := GetNameParentTokens(name, ResourceNamePrefix)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
id, err := util.ConvertStringToInt32(tokens[0])
|
||||
if err != nil {
|
||||
return 0, errors.Errorf("invalid resource ID %q", tokens[0])
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// ExtractInboxIDFromName returns the inbox ID from a resource name.
|
||||
func ExtractInboxIDFromName(name string) (int32, error) {
|
||||
tokens, err := GetNameParentTokens(name, InboxNamePrefix)
|
||||
|
@ -2,10 +2,14 @@ package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/google/cel-go/cel"
|
||||
"github.com/lithammer/shortuuid/v4"
|
||||
"github.com/pkg/errors"
|
||||
expr "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
@ -69,9 +73,42 @@ func (s *APIV2Service) ListResources(ctx context.Context, _ *apiv2pb.ListResourc
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (s *APIV2Service) SearchResources(ctx context.Context, request *apiv2pb.SearchResourcesRequest) (*apiv2pb.SearchResourcesResponse, error) {
|
||||
if request.Filter == "" {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "filter is empty")
|
||||
}
|
||||
filter, err := parseSearchResourcesFilter(request.Filter)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "failed to parse filter: %v", err)
|
||||
}
|
||||
resourceFind := &store.FindResource{}
|
||||
if filter.UID != nil {
|
||||
resourceFind.UID = filter.UID
|
||||
}
|
||||
user, err := getCurrentUser(ctx, s.Store)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed to get current user: %v", err)
|
||||
}
|
||||
resourceFind.CreatorID = &user.ID
|
||||
resources, err := s.Store.ListResources(ctx, resourceFind)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed to search resources: %v", err)
|
||||
}
|
||||
|
||||
response := &apiv2pb.SearchResourcesResponse{}
|
||||
for _, resource := range resources {
|
||||
response.Resources = append(response.Resources, s.convertResourceFromStore(ctx, resource))
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (s *APIV2Service) GetResource(ctx context.Context, request *apiv2pb.GetResourceRequest) (*apiv2pb.GetResourceResponse, error) {
|
||||
id, err := ExtractResourceIDFromName(request.Name)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "invalid resource name: %v", err)
|
||||
}
|
||||
resource, err := s.Store.GetResource(ctx, &store.FindResource{
|
||||
ID: &request.Id,
|
||||
ID: &id,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed to get resource: %v", err)
|
||||
@ -85,30 +122,18 @@ func (s *APIV2Service) GetResource(ctx context.Context, request *apiv2pb.GetReso
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *APIV2Service) GetResourceByName(ctx context.Context, request *apiv2pb.GetResourceByNameRequest) (*apiv2pb.GetResourceByNameResponse, error) {
|
||||
resource, err := s.Store.GetResource(ctx, &store.FindResource{
|
||||
UID: &request.Name,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed to get resource: %v", err)
|
||||
}
|
||||
if resource == nil {
|
||||
return nil, status.Errorf(codes.NotFound, "resource not found")
|
||||
}
|
||||
|
||||
return &apiv2pb.GetResourceByNameResponse{
|
||||
Resource: s.convertResourceFromStore(ctx, resource),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *APIV2Service) UpdateResource(ctx context.Context, request *apiv2pb.UpdateResourceRequest) (*apiv2pb.UpdateResourceResponse, error) {
|
||||
id, err := ExtractResourceIDFromName(request.Resource.Name)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "invalid resource name: %v", err)
|
||||
}
|
||||
if request.UpdateMask == nil || len(request.UpdateMask.Paths) == 0 {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "update mask is required")
|
||||
}
|
||||
|
||||
currentTs := time.Now().Unix()
|
||||
update := &store.UpdateResource{
|
||||
ID: request.Resource.Id,
|
||||
ID: id,
|
||||
UpdatedTs: ¤tTs,
|
||||
}
|
||||
for _, field := range request.UpdateMask.Paths {
|
||||
@ -129,12 +154,16 @@ func (s *APIV2Service) UpdateResource(ctx context.Context, request *apiv2pb.Upda
|
||||
}
|
||||
|
||||
func (s *APIV2Service) DeleteResource(ctx context.Context, request *apiv2pb.DeleteResourceRequest) (*apiv2pb.DeleteResourceResponse, error) {
|
||||
id, err := ExtractResourceIDFromName(request.Name)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "invalid resource name: %v", err)
|
||||
}
|
||||
user, err := getCurrentUser(ctx, s.Store)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed to get current user: %v", err)
|
||||
}
|
||||
resource, err := s.Store.GetResource(ctx, &store.FindResource{
|
||||
ID: &request.Id,
|
||||
ID: &id,
|
||||
CreatorID: &user.ID,
|
||||
})
|
||||
if err != nil {
|
||||
@ -164,8 +193,8 @@ func (s *APIV2Service) convertResourceFromStore(ctx context.Context, resource *s
|
||||
}
|
||||
|
||||
return &apiv2pb.Resource{
|
||||
Id: resource.ID,
|
||||
Name: resource.UID,
|
||||
Name: fmt.Sprintf("%s%d", ResourceNamePrefix, resource.ID),
|
||||
Uid: resource.UID,
|
||||
CreateTime: timestamppb.New(time.Unix(resource.CreatedTs, 0)),
|
||||
Filename: resource.Filename,
|
||||
ExternalLink: resource.ExternalLink,
|
||||
@ -174,3 +203,50 @@ func (s *APIV2Service) convertResourceFromStore(ctx context.Context, resource *s
|
||||
MemoId: memoID,
|
||||
}
|
||||
}
|
||||
|
||||
// SearchResourcesFilterCELAttributes are the CEL attributes for SearchResourcesFilter.
|
||||
var SearchResourcesFilterCELAttributes = []cel.EnvOption{
|
||||
cel.Variable("uid", cel.StringType),
|
||||
}
|
||||
|
||||
type SearchResourcesFilter struct {
|
||||
UID *string
|
||||
}
|
||||
|
||||
func parseSearchResourcesFilter(expression string) (*SearchResourcesFilter, error) {
|
||||
e, err := cel.NewEnv(SearchResourcesFilterCELAttributes...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ast, issues := e.Compile(expression)
|
||||
if issues != nil {
|
||||
return nil, errors.Errorf("found issue %v", issues)
|
||||
}
|
||||
filter := &SearchResourcesFilter{}
|
||||
expr, err := cel.AstToParsedExpr(ast)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
callExpr := expr.GetExpr().GetCallExpr()
|
||||
findSearchResourcesField(callExpr, filter)
|
||||
return filter, nil
|
||||
}
|
||||
|
||||
func findSearchResourcesField(callExpr *expr.Expr_Call, filter *SearchResourcesFilter) {
|
||||
if len(callExpr.Args) == 2 {
|
||||
idExpr := callExpr.Args[0].GetIdentExpr()
|
||||
if idExpr != nil {
|
||||
if idExpr.Name == "uid" {
|
||||
uid := callExpr.Args[1].GetConstExpr().GetStringValue()
|
||||
filter.UID = &uid
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
for _, arg := range callExpr.Args {
|
||||
callExpr := arg.GetCallExpr()
|
||||
if callExpr != nil {
|
||||
findSearchResourcesField(callExpr, filter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user