Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
canifa_note
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Vũ Hoàng Anh
canifa_note
Commits
d7284fe8
Commit
d7284fe8
authored
Dec 30, 2025
by
Johnny
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactor: nest reaction resource names under memos
parent
c2aea5a4
Changes
8
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
63 additions
and
53 deletions
+63
-53
memo_service.proto
proto/api/v1/memo_service.proto
+4
-4
memo_service.pb.go
proto/gen/api/v1/memo_service.pb.go
+8
-8
memo_service.pb.gw.go
proto/gen/api/v1/memo_service.pb.gw.go
+3
-3
openapi.yaml
proto/gen/openapi.yaml
+30
-24
reaction_service.go
server/router/api/v1/reaction_service.go
+4
-2
resource_name.go
server/router/api/v1/resource_name.go
+9
-8
reaction_service_test.go
server/router/api/v1/test/reaction_service_test.go
+2
-1
memo_service_pb.ts
web/src/types/proto/api/v1/memo_service_pb.ts
+3
-3
No files found.
proto/api/v1/memo_service.proto
View file @
d7284fe8
...
@@ -100,7 +100,7 @@ service MemoService {
...
@@ -100,7 +100,7 @@ service MemoService {
}
}
// DeleteMemoReaction deletes a reaction for a memo.
// DeleteMemoReaction deletes a reaction for a memo.
rpc
DeleteMemoReaction
(
DeleteMemoReactionRequest
)
returns
(
google.protobuf.Empty
)
{
rpc
DeleteMemoReaction
(
DeleteMemoReactionRequest
)
returns
(
google.protobuf.Empty
)
{
option
(
google.api.http
)
=
{
delete
:
"/api/v1/{name=reactions/*}"
};
option
(
google.api.http
)
=
{
delete
:
"/api/v1/{name=
memos/*/
reactions/*}"
};
option
(
google.api.method_signature
)
=
"name"
;
option
(
google.api.method_signature
)
=
"name"
;
}
}
}
}
...
@@ -115,14 +115,14 @@ enum Visibility {
...
@@ -115,14 +115,14 @@ enum Visibility {
message
Reaction
{
message
Reaction
{
option
(
google.api.resource
)
=
{
option
(
google.api.resource
)
=
{
type
:
"memos.api.v1/Reaction"
type
:
"memos.api.v1/Reaction"
pattern
:
"reactions/{reaction}"
pattern
:
"
memos/{memo}/
reactions/{reaction}"
name_field
:
"name"
name_field
:
"name"
singular
:
"reaction"
singular
:
"reaction"
plural
:
"reactions"
plural
:
"reactions"
};
};
// The resource name of the reaction.
// The resource name of the reaction.
// Format: reactions/{reaction}
// Format:
memos/{memo}/
reactions/{reaction}
string
name
=
1
[
string
name
=
1
[
(
google.api.field_behavior
)
=
OUTPUT_ONLY
,
(
google.api.field_behavior
)
=
OUTPUT_ONLY
,
(
google.api.field_behavior
)
=
IDENTIFIER
(
google.api.field_behavior
)
=
IDENTIFIER
...
@@ -501,7 +501,7 @@ message UpsertMemoReactionRequest {
...
@@ -501,7 +501,7 @@ message UpsertMemoReactionRequest {
message
DeleteMemoReactionRequest
{
message
DeleteMemoReactionRequest
{
// Required. The resource name of the reaction to delete.
// Required. The resource name of the reaction to delete.
// Format: reactions/{reaction}
// Format:
memos/{memo}/
reactions/{reaction}
string
name
=
1
[
string
name
=
1
[
(
google.api.field_behavior
)
=
REQUIRED
,
(
google.api.field_behavior
)
=
REQUIRED
,
(
google.api.resource_reference
)
=
{
type
:
"memos.api.v1/Reaction"
}
(
google.api.resource_reference
)
=
{
type
:
"memos.api.v1/Reaction"
}
...
...
proto/gen/api/v1/memo_service.pb.go
View file @
d7284fe8
...
@@ -130,7 +130,7 @@ func (MemoRelation_Type) EnumDescriptor() ([]byte, []int) {
...
@@ -130,7 +130,7 @@ func (MemoRelation_Type) EnumDescriptor() ([]byte, []int) {
type
Reaction
struct
{
type
Reaction
struct
{
state
protoimpl
.
MessageState
`protogen:"open.v1"`
state
protoimpl
.
MessageState
`protogen:"open.v1"`
// The resource name of the reaction.
// The resource name of the reaction.
// Format: reactions/{reaction}
// Format:
memos/{memo}/
reactions/{reaction}
Name
string
`protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Name
string
`protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
// The resource name of the creator.
// The resource name of the creator.
// Format: users/{user}
// Format: users/{user}
...
@@ -1627,7 +1627,7 @@ func (x *UpsertMemoReactionRequest) GetReaction() *Reaction {
...
@@ -1627,7 +1627,7 @@ func (x *UpsertMemoReactionRequest) GetReaction() *Reaction {
type
DeleteMemoReactionRequest
struct
{
type
DeleteMemoReactionRequest
struct
{
state
protoimpl
.
MessageState
`protogen:"open.v1"`
state
protoimpl
.
MessageState
`protogen:"open.v1"`
// Required. The resource name of the reaction to delete.
// Required. The resource name of the reaction to delete.
// Format: reactions/{reaction}
// Format:
memos/{memo}/
reactions/{reaction}
Name
string
`protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Name
string
`protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
unknownFields
protoimpl
.
UnknownFields
unknownFields
protoimpl
.
UnknownFields
sizeCache
protoimpl
.
SizeCache
sizeCache
protoimpl
.
SizeCache
...
@@ -1799,7 +1799,7 @@ var File_api_v1_memo_service_proto protoreflect.FileDescriptor
...
@@ -1799,7 +1799,7 @@ var File_api_v1_memo_service_proto protoreflect.FileDescriptor
const
file_api_v1_memo_service_proto_rawDesc
=
""
+
const
file_api_v1_memo_service_proto_rawDesc
=
""
+
"
\n
"
+
"
\n
"
+
"
\x19
api/v1/memo_service.proto
\x12\f
memos.api.v1
\x1a\x1f
api/v1/attachment_service.proto
\x1a\x13
api/v1/common.proto
\x1a\x1c
google/api/annotations.proto
\x1a\x17
google/api/client.proto
\x1a\x1f
google/api/field_behavior.proto
\x1a\x19
google/api/resource.proto
\x1a\x1b
google/protobuf/empty.proto
\x1a
google/protobuf/field_mask.proto
\x1a\x1f
google/protobuf/timestamp.proto
\"\x
ce
\x02\n
"
+
"
\x19
api/v1/memo_service.proto
\x12\f
memos.api.v1
\x1a\x1f
api/v1/attachment_service.proto
\x1a\x13
api/v1/common.proto
\x1a\x1c
google/api/annotations.proto
\x1a\x17
google/api/client.proto
\x1a\x1f
google/api/field_behavior.proto
\x1a\x19
google/api/resource.proto
\x1a\x1b
google/protobuf/empty.proto
\x1a
google/protobuf/field_mask.proto
\x1a\x1f
google/protobuf/timestamp.proto
\"\x
db
\x02\n
"
+
"
\b
Reaction
\x12\x1a\n
"
+
"
\b
Reaction
\x12\x1a\n
"
+
"
\x04
name
\x18\x01
\x01
(
\t
B
\x06\xe0
A
\x03\xe0
A
\b
R
\x04
name
\x12
3
\n
"
+
"
\x04
name
\x18\x01
\x01
(
\t
B
\x06\xe0
A
\x03\xe0
A
\b
R
\x04
name
\x12
3
\n
"
+
"
\a
creator
\x18\x02
\x01
(
\t
B
\x19\xe0
A
\x03\xfa
A
\x13\n
"
+
"
\a
creator
\x18\x02
\x01
(
\t
B
\x19\xe0
A
\x03\xfa
A
\x13\n
"
+
...
@@ -1809,8 +1809,8 @@ const file_api_v1_memo_service_proto_rawDesc = "" +
...
@@ -1809,8 +1809,8 @@ const file_api_v1_memo_service_proto_rawDesc = "" +
"
\x11
memos.api.v1/MemoR
\t
contentId
\x12
(
\n
"
+
"
\x11
memos.api.v1/MemoR
\t
contentId
\x12
(
\n
"
+
"
\r
reaction_type
\x18\x04
\x01
(
\t
B
\x03\xe0
A
\x02
R
\f
reactionType
\x12
@
\n
"
+
"
\r
reaction_type
\x18\x04
\x01
(
\t
B
\x03\xe0
A
\x02
R
\f
reactionType
\x12
@
\n
"
+
"
\v
create_time
\x18\x05
\x01
(
\v
2
\x1a
.google.protobuf.TimestampB
\x03\xe0
A
\x03
R
\n
"
+
"
\v
create_time
\x18\x05
\x01
(
\v
2
\x1a
.google.protobuf.TimestampB
\x03\xe0
A
\x03
R
\n
"
+
"createTime:
K
\xea
AH
\n
"
+
"createTime:
X
\xea
AU
\n
"
+
"
\x15
memos.api.v1/Reaction
\x12
\x14
reactions/{reaction}
\x1a\x04
name*
\t
reactions2
\b
reaction
\"\xd8\b\n
"
+
"
\x15
memos.api.v1/Reaction
\x12
!memos/{memo}/
reactions/{reaction}
\x1a\x04
name*
\t
reactions2
\b
reaction
\"\xd8\b\n
"
+
"
\x04
Memo
\x12\x17\n
"
+
"
\x04
Memo
\x12\x17\n
"
+
"
\x04
name
\x18\x01
\x01
(
\t
B
\x03\xe0
A
\b
R
\x04
name
\x12
.
\n
"
+
"
\x04
name
\x18\x01
\x01
(
\t
B
\x03\xe0
A
\b
R
\x04
name
\x12
.
\n
"
+
"
\x05
state
\x18\x02
\x01
(
\x0e
2
\x13
.memos.api.v1.StateB
\x03\xe0
A
\x02
R
\x05
state
\x12
3
\n
"
+
"
\x05
state
\x18\x02
\x01
(
\x0e
2
\x13
.memos.api.v1.StateB
\x03\xe0
A
\x02
R
\x05
state
\x12
3
\n
"
+
...
@@ -1953,7 +1953,7 @@ const file_api_v1_memo_service_proto_rawDesc = "" +
...
@@ -1953,7 +1953,7 @@ const file_api_v1_memo_service_proto_rawDesc = "" +
"
\a
PRIVATE
\x10\x01\x12\r\n
"
+
"
\a
PRIVATE
\x10\x01\x12\r\n
"
+
"
\t
PROTECTED
\x10\x02\x12\n
"
+
"
\t
PROTECTED
\x10\x02\x12\n
"
+
"
\n
"
+
"
\n
"
+
"
\x06
PUBLIC
\x10\x03
2
\x
cb
\x0e\n
"
+
"
\x06
PUBLIC
\x10\x03
2
\x
d3
\x0e\n
"
+
"
\v
MemoService
\x12
e
\n
"
+
"
\v
MemoService
\x12
e
\n
"
+
"
\n
"
+
"
\n
"
+
"CreateMemo
\x12\x1f
.memos.api.v1.CreateMemoRequest
\x1a\x12
.memos.api.v1.Memo
\"\"\xda
A
\x04
memo
\x82\xd3\xe4\x93\x02\x15
:
\x04
memo
\"\r
/api/v1/memos
\x12
f
\n
"
+
"CreateMemo
\x12\x1f
.memos.api.v1.CreateMemoRequest
\x1a\x12
.memos.api.v1.Memo
\"\"\xda
A
\x04
memo
\x82\xd3\xe4\x93\x02\x15
:
\x04
memo
\"\r
/api/v1/memos
\x12
f
\n
"
+
...
@@ -1970,8 +1970,8 @@ const file_api_v1_memo_service_proto_rawDesc = "" +
...
@@ -1970,8 +1970,8 @@ const file_api_v1_memo_service_proto_rawDesc = "" +
"
\x11
CreateMemoComment
\x12
&.memos.api.v1.CreateMemoCommentRequest
\x1a\x12
.memos.api.v1.Memo
\"
?
\xda
A
\f
name,comment
\x82\xd3\xe4\x93\x02
*:
\a
comment
\"\x1f
/api/v1/{name=memos/*}/comments
\x12\x91\x01\n
"
+
"
\x11
CreateMemoComment
\x12
&.memos.api.v1.CreateMemoCommentRequest
\x1a\x12
.memos.api.v1.Memo
\"
?
\xda
A
\f
name,comment
\x82\xd3\xe4\x93\x02
*:
\a
comment
\"\x1f
/api/v1/{name=memos/*}/comments
\x12\x91\x01\n
"
+
"
\x10
ListMemoComments
\x12
%.memos.api.v1.ListMemoCommentsRequest
\x1a
&.memos.api.v1.ListMemoCommentsResponse
\"
.
\xda
A
\x04
name
\x82\xd3\xe4\x93\x02
!
\x12\x1f
/api/v1/{name=memos/*}/comments
\x12\x95\x01\n
"
+
"
\x10
ListMemoComments
\x12
%.memos.api.v1.ListMemoCommentsRequest
\x1a
&.memos.api.v1.ListMemoCommentsResponse
\"
.
\xda
A
\x04
name
\x82\xd3\xe4\x93\x02
!
\x12\x1f
/api/v1/{name=memos/*}/comments
\x12\x95\x01\n
"
+
"
\x11
ListMemoReactions
\x12
&.memos.api.v1.ListMemoReactionsRequest
\x1a
'.memos.api.v1.ListMemoReactionsResponse
\"
/
\xda
A
\x04
name
\x82\xd3\xe4\x93\x02\"\x12
/api/v1/{name=memos/*}/reactions
\x12\x89\x01\n
"
+
"
\x11
ListMemoReactions
\x12
&.memos.api.v1.ListMemoReactionsRequest
\x1a
'.memos.api.v1.ListMemoReactionsResponse
\"
/
\xda
A
\x04
name
\x82\xd3\xe4\x93\x02\"\x12
/api/v1/{name=memos/*}/reactions
\x12\x89\x01\n
"
+
"
\x12
UpsertMemoReaction
\x12
'.memos.api.v1.UpsertMemoReactionRequest
\x1a\x16
.memos.api.v1.Reaction
\"
2
\xda
A
\x04
name
\x82\xd3\xe4\x93\x02
%:
\x01
*
\"
/api/v1/{name=memos/*}/reactions
\x12\x8
0
\x01\n
"
+
"
\x12
UpsertMemoReaction
\x12
'.memos.api.v1.UpsertMemoReactionRequest
\x1a\x16
.memos.api.v1.Reaction
\"
2
\xda
A
\x04
name
\x82\xd3\xe4\x93\x02
%:
\x01
*
\"
/api/v1/{name=memos/*}/reactions
\x12\x8
8
\x01\n
"
+
"
\x12
DeleteMemoReaction
\x12
'.memos.api.v1.DeleteMemoReactionRequest
\x1a\x16
.google.protobuf.Empty
\"
)
\xda
A
\x04
name
\x82\xd3\xe4\x93\x02\x1c
*
\x1a
/api/v1/{name=
reactions/*}B
\xa8\x01\n
"
+
"
\x12
DeleteMemoReaction
\x12
'.memos.api.v1.DeleteMemoReactionRequest
\x1a\x16
.google.protobuf.Empty
\"
1
\xda
A
\x04
name
\x82\xd3\xe4\x93\x02
$*
\"
/api/v1/{name=memos/*/
reactions/*}B
\xa8\x01\n
"
+
"
\x10
com.memos.api.v1B
\x10
MemoServiceProtoP
\x01
Z0github.com/usememos/memos/proto/gen/api/v1;apiv1
\xa2\x02\x03
MAX
\xaa\x02\f
Memos.Api.V1
\xca\x02\f
Memos
\\
Api
\\
V1
\xe2\x02\x18
Memos
\\
Api
\\
V1
\\
GPBMetadata
\xea\x02\x0e
Memos::Api::V1b
\x06
proto3"
"
\x10
com.memos.api.v1B
\x10
MemoServiceProtoP
\x01
Z0github.com/usememos/memos/proto/gen/api/v1;apiv1
\xa2\x02\x03
MAX
\xaa\x02\f
Memos.Api.V1
\xca\x02\f
Memos
\\
Api
\\
V1
\xe2\x02\x18
Memos
\\
Api
\\
V1
\\
GPBMetadata
\xea\x02\x0e
Memos::Api::V1b
\x06
proto3"
var
(
var
(
...
...
proto/gen/api/v1/memo_service.pb.gw.go
View file @
d7284fe8
...
@@ -1001,7 +1001,7 @@ func RegisterMemoServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
...
@@ -1001,7 +1001,7 @@ func RegisterMemoServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
var
stream
runtime
.
ServerTransportStream
var
stream
runtime
.
ServerTransportStream
ctx
=
grpc
.
NewContextWithServerTransportStream
(
ctx
,
&
stream
)
ctx
=
grpc
.
NewContextWithServerTransportStream
(
ctx
,
&
stream
)
inboundMarshaler
,
outboundMarshaler
:=
runtime
.
MarshalerForRequest
(
mux
,
req
)
inboundMarshaler
,
outboundMarshaler
:=
runtime
.
MarshalerForRequest
(
mux
,
req
)
annotatedContext
,
err
:=
runtime
.
AnnotateIncomingContext
(
ctx
,
mux
,
req
,
"/memos.api.v1.MemoService/DeleteMemoReaction"
,
runtime
.
WithHTTPPathPattern
(
"/api/v1/{name=reactions/*}"
))
annotatedContext
,
err
:=
runtime
.
AnnotateIncomingContext
(
ctx
,
mux
,
req
,
"/memos.api.v1.MemoService/DeleteMemoReaction"
,
runtime
.
WithHTTPPathPattern
(
"/api/v1/{name=
memos/*/
reactions/*}"
))
if
err
!=
nil
{
if
err
!=
nil
{
runtime
.
HTTPError
(
ctx
,
mux
,
outboundMarshaler
,
w
,
req
,
err
)
runtime
.
HTTPError
(
ctx
,
mux
,
outboundMarshaler
,
w
,
req
,
err
)
return
return
...
@@ -1280,7 +1280,7 @@ func RegisterMemoServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
...
@@ -1280,7 +1280,7 @@ func RegisterMemoServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
ctx
,
cancel
:=
context
.
WithCancel
(
req
.
Context
())
ctx
,
cancel
:=
context
.
WithCancel
(
req
.
Context
())
defer
cancel
()
defer
cancel
()
inboundMarshaler
,
outboundMarshaler
:=
runtime
.
MarshalerForRequest
(
mux
,
req
)
inboundMarshaler
,
outboundMarshaler
:=
runtime
.
MarshalerForRequest
(
mux
,
req
)
annotatedContext
,
err
:=
runtime
.
AnnotateContext
(
ctx
,
mux
,
req
,
"/memos.api.v1.MemoService/DeleteMemoReaction"
,
runtime
.
WithHTTPPathPattern
(
"/api/v1/{name=reactions/*}"
))
annotatedContext
,
err
:=
runtime
.
AnnotateContext
(
ctx
,
mux
,
req
,
"/memos.api.v1.MemoService/DeleteMemoReaction"
,
runtime
.
WithHTTPPathPattern
(
"/api/v1/{name=
memos/*/
reactions/*}"
))
if
err
!=
nil
{
if
err
!=
nil
{
runtime
.
HTTPError
(
ctx
,
mux
,
outboundMarshaler
,
w
,
req
,
err
)
runtime
.
HTTPError
(
ctx
,
mux
,
outboundMarshaler
,
w
,
req
,
err
)
return
return
...
@@ -1310,7 +1310,7 @@ var (
...
@@ -1310,7 +1310,7 @@ var (
pattern_MemoService_ListMemoComments_0
=
runtime
.
MustPattern
(
runtime
.
NewPattern
(
1
,
[]
int
{
2
,
0
,
2
,
1
,
2
,
2
,
1
,
0
,
4
,
2
,
5
,
3
,
2
,
4
},
[]
string
{
"api"
,
"v1"
,
"memos"
,
"name"
,
"comments"
},
""
))
pattern_MemoService_ListMemoComments_0
=
runtime
.
MustPattern
(
runtime
.
NewPattern
(
1
,
[]
int
{
2
,
0
,
2
,
1
,
2
,
2
,
1
,
0
,
4
,
2
,
5
,
3
,
2
,
4
},
[]
string
{
"api"
,
"v1"
,
"memos"
,
"name"
,
"comments"
},
""
))
pattern_MemoService_ListMemoReactions_0
=
runtime
.
MustPattern
(
runtime
.
NewPattern
(
1
,
[]
int
{
2
,
0
,
2
,
1
,
2
,
2
,
1
,
0
,
4
,
2
,
5
,
3
,
2
,
4
},
[]
string
{
"api"
,
"v1"
,
"memos"
,
"name"
,
"reactions"
},
""
))
pattern_MemoService_ListMemoReactions_0
=
runtime
.
MustPattern
(
runtime
.
NewPattern
(
1
,
[]
int
{
2
,
0
,
2
,
1
,
2
,
2
,
1
,
0
,
4
,
2
,
5
,
3
,
2
,
4
},
[]
string
{
"api"
,
"v1"
,
"memos"
,
"name"
,
"reactions"
},
""
))
pattern_MemoService_UpsertMemoReaction_0
=
runtime
.
MustPattern
(
runtime
.
NewPattern
(
1
,
[]
int
{
2
,
0
,
2
,
1
,
2
,
2
,
1
,
0
,
4
,
2
,
5
,
3
,
2
,
4
},
[]
string
{
"api"
,
"v1"
,
"memos"
,
"name"
,
"reactions"
},
""
))
pattern_MemoService_UpsertMemoReaction_0
=
runtime
.
MustPattern
(
runtime
.
NewPattern
(
1
,
[]
int
{
2
,
0
,
2
,
1
,
2
,
2
,
1
,
0
,
4
,
2
,
5
,
3
,
2
,
4
},
[]
string
{
"api"
,
"v1"
,
"memos"
,
"name"
,
"reactions"
},
""
))
pattern_MemoService_DeleteMemoReaction_0
=
runtime
.
MustPattern
(
runtime
.
NewPattern
(
1
,
[]
int
{
2
,
0
,
2
,
1
,
2
,
2
,
1
,
0
,
4
,
2
,
5
,
3
},
[]
string
{
"api"
,
"v1
"
,
"reactions"
,
"name"
},
""
))
pattern_MemoService_DeleteMemoReaction_0
=
runtime
.
MustPattern
(
runtime
.
NewPattern
(
1
,
[]
int
{
2
,
0
,
2
,
1
,
2
,
2
,
1
,
0
,
2
,
3
,
1
,
0
,
4
,
4
,
5
,
4
},
[]
string
{
"api"
,
"v1"
,
"memos
"
,
"reactions"
,
"name"
},
""
))
)
)
var
(
var
(
...
...
proto/gen/openapi.yaml
View file @
d7284fe8
...
@@ -960,6 +960,35 @@ paths:
...
@@ -960,6 +960,35 @@ paths:
application/json
:
application/json
:
schema
:
schema
:
$ref
:
'
#/components/schemas/Status'
$ref
:
'
#/components/schemas/Status'
/api/v1/memos/{memo}/reactions/{reaction}
:
delete
:
tags
:
-
MemoService
description
:
DeleteMemoReaction deletes a reaction for a memo.
operationId
:
MemoService_DeleteMemoReaction
parameters
:
-
name
:
memo
in
:
path
description
:
The memo id.
required
:
true
schema
:
type
:
string
-
name
:
reaction
in
:
path
description
:
The reaction id.
required
:
true
schema
:
type
:
string
responses
:
"
200"
:
description
:
OK
content
:
{}
default
:
description
:
Default error response
content
:
application/json
:
schema
:
$ref
:
'
#/components/schemas/Status'
/api/v1/memos/{memo}/relations
:
/api/v1/memos/{memo}/relations
:
get
:
get
:
tags
:
tags
:
...
@@ -1025,29 +1054,6 @@ paths:
...
@@ -1025,29 +1054,6 @@ paths:
application/json
:
application/json
:
schema
:
schema
:
$ref
:
'
#/components/schemas/Status'
$ref
:
'
#/components/schemas/Status'
/api/v1/reactions/{reaction}
:
delete
:
tags
:
-
MemoService
description
:
DeleteMemoReaction deletes a reaction for a memo.
operationId
:
MemoService_DeleteMemoReaction
parameters
:
-
name
:
reaction
in
:
path
description
:
The reaction id.
required
:
true
schema
:
type
:
string
responses
:
"
200"
:
description
:
OK
content
:
{}
default
:
description
:
Default error response
content
:
application/json
:
schema
:
$ref
:
'
#/components/schemas/Status'
/api/v1/users
:
/api/v1/users
:
get
:
get
:
tags
:
tags
:
...
@@ -2640,7 +2646,7 @@ components:
...
@@ -2640,7 +2646,7 @@ components:
type
:
string
type
:
string
description
:
|-
description
:
|-
The resource name of the reaction.
The resource name of the reaction.
Format: reactions/{reaction}
Format:
memos/{memo}/
reactions/{reaction}
creator
:
creator
:
readOnly
:
true
readOnly
:
true
type
:
string
type
:
string
...
...
server/router/api/v1/reaction_service.go
View file @
d7284fe8
...
@@ -63,7 +63,7 @@ func (s *APIV1Service) DeleteMemoReaction(ctx context.Context, request *v1pb.Del
...
@@ -63,7 +63,7 @@ func (s *APIV1Service) DeleteMemoReaction(ctx context.Context, request *v1pb.Del
return
nil
,
status
.
Errorf
(
codes
.
Unauthenticated
,
"user not authenticated"
)
return
nil
,
status
.
Errorf
(
codes
.
Unauthenticated
,
"user not authenticated"
)
}
}
reactionID
,
err
:=
Extract
ReactionIDFromName
(
request
.
Name
)
_
,
reactionID
,
err
:=
ExtractMemo
ReactionIDFromName
(
request
.
Name
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
status
.
Errorf
(
codes
.
InvalidArgument
,
"invalid reaction name: %v"
,
err
)
return
nil
,
status
.
Errorf
(
codes
.
InvalidArgument
,
"invalid reaction name: %v"
,
err
)
}
}
...
@@ -95,8 +95,10 @@ func (s *APIV1Service) DeleteMemoReaction(ctx context.Context, request *v1pb.Del
...
@@ -95,8 +95,10 @@ func (s *APIV1Service) DeleteMemoReaction(ctx context.Context, request *v1pb.Del
func
convertReactionFromStore
(
reaction
*
store
.
Reaction
)
*
v1pb
.
Reaction
{
func
convertReactionFromStore
(
reaction
*
store
.
Reaction
)
*
v1pb
.
Reaction
{
reactionUID
:=
fmt
.
Sprintf
(
"%d"
,
reaction
.
ID
)
reactionUID
:=
fmt
.
Sprintf
(
"%d"
,
reaction
.
ID
)
// Generate nested resource name: memos/{memo}/reactions/{reaction}
// reaction.ContentID already contains "memos/{memo}"
return
&
v1pb
.
Reaction
{
return
&
v1pb
.
Reaction
{
Name
:
fmt
.
Sprintf
(
"%s
%s"
,
ReactionNamePrefix
,
reactionUID
),
Name
:
fmt
.
Sprintf
(
"%s
/%s%s"
,
reaction
.
ContentID
,
ReactionNamePrefix
,
reactionUID
),
Creator
:
fmt
.
Sprintf
(
"%s%d"
,
UserNamePrefix
,
reaction
.
CreatorID
),
Creator
:
fmt
.
Sprintf
(
"%s%d"
,
UserNamePrefix
,
reaction
.
CreatorID
),
ContentId
:
reaction
.
ContentID
,
ContentId
:
reaction
.
ContentID
,
ReactionType
:
reaction
.
ReactionType
,
ReactionType
:
reaction
.
ReactionType
,
...
...
server/router/api/v1/resource_name.go
View file @
d7284fe8
...
@@ -105,18 +105,19 @@ func ExtractAttachmentUIDFromName(name string) (string, error) {
...
@@ -105,18 +105,19 @@ func ExtractAttachmentUIDFromName(name string) (string, error) {
return
id
,
nil
return
id
,
nil
}
}
// Extract
ReactionIDFromName returns the
reaction ID from a resource name.
// Extract
MemoReactionIDFromName returns the memo UID and
reaction ID from a resource name.
// e.g., "
reactions/123" -> 123
.
// e.g., "
memos/abc/reactions/123" -> ("abc", 123)
.
func
Extract
ReactionIDFromName
(
name
string
)
(
int32
,
error
)
{
func
Extract
MemoReactionIDFromName
(
name
string
)
(
string
,
int32
,
error
)
{
tokens
,
err
:=
GetNameParentTokens
(
name
,
ReactionNamePrefix
)
tokens
,
err
:=
GetNameParentTokens
(
name
,
MemoNamePrefix
,
ReactionNamePrefix
)
if
err
!=
nil
{
if
err
!=
nil
{
return
0
,
err
return
""
,
0
,
err
}
}
id
,
err
:=
util
.
ConvertStringToInt32
(
tokens
[
0
])
memoUID
:=
tokens
[
0
]
reactionID
,
err
:=
util
.
ConvertStringToInt32
(
tokens
[
1
])
if
err
!=
nil
{
if
err
!=
nil
{
return
0
,
errors
.
Errorf
(
"invalid reaction ID %q"
,
tokens
[
0
])
return
""
,
0
,
errors
.
Errorf
(
"invalid reaction ID %q"
,
tokens
[
1
])
}
}
return
id
,
nil
return
memoUID
,
reactionID
,
nil
}
}
// ExtractInboxIDFromName returns the inbox ID from a resource name.
// ExtractInboxIDFromName returns the inbox ID from a resource name.
...
...
server/router/api/v1/test/reaction_service_test.go
View file @
d7284fe8
...
@@ -183,8 +183,9 @@ func TestDeleteMemoReaction(t *testing.T) {
...
@@ -183,8 +183,9 @@ func TestDeleteMemoReaction(t *testing.T) {
// Try to delete non-existent reaction - should fail with permission denied
// Try to delete non-existent reaction - should fail with permission denied
// (not "not found" to avoid information disclosure)
// (not "not found" to avoid information disclosure)
// Use new nested resource format: memos/{memo}/reactions/{reaction}
_
,
err
=
ts
.
Service
.
DeleteMemoReaction
(
userCtx
,
&
apiv1
.
DeleteMemoReactionRequest
{
_
,
err
=
ts
.
Service
.
DeleteMemoReaction
(
userCtx
,
&
apiv1
.
DeleteMemoReactionRequest
{
Name
:
"reactions/99999"
,
Name
:
"
memos/nonexistent/
reactions/99999"
,
})
})
require
.
Error
(
t
,
err
)
require
.
Error
(
t
,
err
)
require
.
Contains
(
t
,
err
.
Error
(),
"permission denied"
)
require
.
Contains
(
t
,
err
.
Error
(),
"permission denied"
)
...
...
web/src/types/proto/api/v1/memo_service_pb.ts
View file @
d7284fe8
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment