mirror of https://github.com/usememos/memos.git
feat: implement user session
This commit is contained in:
parent
741fe35c2a
commit
77b7fc4441
|
|
@ -108,6 +108,18 @@ service UserService {
|
|||
option (google.api.http) = {delete: "/api/v1/{name=users/*/accessTokens/*}"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
|
||||
// ListUserSessions returns a list of active sessions for a user.
|
||||
rpc ListUserSessions(ListUserSessionsRequest) returns (ListUserSessionsResponse) {
|
||||
option (google.api.http) = {get: "/api/v1/{parent=users/*}/sessions"};
|
||||
option (google.api.method_signature) = "parent";
|
||||
}
|
||||
|
||||
// RevokeUserSession revokes a specific session for a user.
|
||||
rpc RevokeUserSession(RevokeUserSessionRequest) returns (google.protobuf.Empty) {
|
||||
option (google.api.http) = {delete: "/api/v1/{name=users/*/sessions/*}"};
|
||||
option (google.api.method_signature) = "name";
|
||||
}
|
||||
}
|
||||
|
||||
message User {
|
||||
|
|
@ -458,6 +470,76 @@ message DeleteUserAccessTokenRequest {
|
|||
];
|
||||
}
|
||||
|
||||
message UserSession {
|
||||
option (google.api.resource) = {
|
||||
type: "memos.api.v1/UserSession"
|
||||
pattern: "users/{user}/sessions/{session}"
|
||||
name_field: "name"
|
||||
};
|
||||
|
||||
// The resource name of the session.
|
||||
// Format: users/{user}/sessions/{session}
|
||||
string name = 1 [(google.api.field_behavior) = IDENTIFIER];
|
||||
|
||||
// The session ID.
|
||||
string session_id = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
|
||||
// The timestamp when the session was created.
|
||||
google.protobuf.Timestamp create_time = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
|
||||
// The timestamp when the session expires.
|
||||
google.protobuf.Timestamp expire_time = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
|
||||
// The timestamp when the session was last accessed.
|
||||
google.protobuf.Timestamp last_accessed_time = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
|
||||
// Client information associated with this session.
|
||||
ClientInfo client_info = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
|
||||
message ClientInfo {
|
||||
// User agent string of the client.
|
||||
string user_agent = 1;
|
||||
|
||||
// IP address of the client.
|
||||
string ip_address = 2;
|
||||
|
||||
// Optional. Device type (e.g., "mobile", "desktop", "tablet").
|
||||
string device_type = 3 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. Operating system (e.g., "iOS 17.0", "Windows 11").
|
||||
string os = 4 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. Browser name and version (e.g., "Chrome 119.0").
|
||||
string browser = 5 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
||||
// Optional. Geographic location (country code, e.g., "US").
|
||||
string country = 6 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
}
|
||||
|
||||
message ListUserSessionsRequest {
|
||||
// Required. The resource name of the parent.
|
||||
// Format: users/{user}
|
||||
string parent = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/User"}
|
||||
];
|
||||
}
|
||||
|
||||
message ListUserSessionsResponse {
|
||||
// The list of user sessions.
|
||||
repeated UserSession sessions = 1;
|
||||
}
|
||||
|
||||
message RevokeUserSessionRequest {
|
||||
// Required. The resource name of the session to revoke.
|
||||
// Format: users/{user}/sessions/{session}
|
||||
string name = 1 [
|
||||
(google.api.field_behavior) = REQUIRED,
|
||||
(google.api.resource_reference) = {type: "memos.api.v1/UserSession"}
|
||||
];
|
||||
}
|
||||
|
||||
message ListAllUserStatsRequest {
|
||||
// Optional. The maximum number of user stats to return.
|
||||
int32 page_size = 1 [(google.api.field_behavior) = OPTIONAL];
|
||||
|
|
|
|||
|
|
@ -1443,6 +1443,234 @@ func (x *DeleteUserAccessTokenRequest) GetName() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
type UserSession struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// The resource name of the session.
|
||||
// Format: users/{user}/sessions/{session}
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
// The session ID.
|
||||
SessionId string `protobuf:"bytes,2,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"`
|
||||
// The timestamp when the session was created.
|
||||
CreateTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=create_time,json=createTime,proto3" json:"create_time,omitempty"`
|
||||
// The timestamp when the session expires.
|
||||
ExpireTime *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=expire_time,json=expireTime,proto3" json:"expire_time,omitempty"`
|
||||
// The timestamp when the session was last accessed.
|
||||
LastAccessedTime *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=last_accessed_time,json=lastAccessedTime,proto3" json:"last_accessed_time,omitempty"`
|
||||
// Client information associated with this session.
|
||||
ClientInfo *UserSession_ClientInfo `protobuf:"bytes,6,opt,name=client_info,json=clientInfo,proto3" json:"client_info,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *UserSession) Reset() {
|
||||
*x = UserSession{}
|
||||
mi := &file_api_v1_user_service_proto_msgTypes[20]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *UserSession) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*UserSession) ProtoMessage() {}
|
||||
|
||||
func (x *UserSession) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_v1_user_service_proto_msgTypes[20]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use UserSession.ProtoReflect.Descriptor instead.
|
||||
func (*UserSession) Descriptor() ([]byte, []int) {
|
||||
return file_api_v1_user_service_proto_rawDescGZIP(), []int{20}
|
||||
}
|
||||
|
||||
func (x *UserSession) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *UserSession) GetSessionId() string {
|
||||
if x != nil {
|
||||
return x.SessionId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *UserSession) GetCreateTime() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.CreateTime
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *UserSession) GetExpireTime() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.ExpireTime
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *UserSession) GetLastAccessedTime() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.LastAccessedTime
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *UserSession) GetClientInfo() *UserSession_ClientInfo {
|
||||
if x != nil {
|
||||
return x.ClientInfo
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ListUserSessionsRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Required. The resource name of the parent.
|
||||
// Format: users/{user}
|
||||
Parent string `protobuf:"bytes,1,opt,name=parent,proto3" json:"parent,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ListUserSessionsRequest) Reset() {
|
||||
*x = ListUserSessionsRequest{}
|
||||
mi := &file_api_v1_user_service_proto_msgTypes[21]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ListUserSessionsRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ListUserSessionsRequest) ProtoMessage() {}
|
||||
|
||||
func (x *ListUserSessionsRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_v1_user_service_proto_msgTypes[21]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ListUserSessionsRequest.ProtoReflect.Descriptor instead.
|
||||
func (*ListUserSessionsRequest) Descriptor() ([]byte, []int) {
|
||||
return file_api_v1_user_service_proto_rawDescGZIP(), []int{21}
|
||||
}
|
||||
|
||||
func (x *ListUserSessionsRequest) GetParent() string {
|
||||
if x != nil {
|
||||
return x.Parent
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ListUserSessionsResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// The list of user sessions.
|
||||
Sessions []*UserSession `protobuf:"bytes,1,rep,name=sessions,proto3" json:"sessions,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ListUserSessionsResponse) Reset() {
|
||||
*x = ListUserSessionsResponse{}
|
||||
mi := &file_api_v1_user_service_proto_msgTypes[22]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ListUserSessionsResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ListUserSessionsResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ListUserSessionsResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_v1_user_service_proto_msgTypes[22]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ListUserSessionsResponse.ProtoReflect.Descriptor instead.
|
||||
func (*ListUserSessionsResponse) Descriptor() ([]byte, []int) {
|
||||
return file_api_v1_user_service_proto_rawDescGZIP(), []int{22}
|
||||
}
|
||||
|
||||
func (x *ListUserSessionsResponse) GetSessions() []*UserSession {
|
||||
if x != nil {
|
||||
return x.Sessions
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type RevokeUserSessionRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Required. The resource name of the session to revoke.
|
||||
// Format: users/{user}/sessions/{session}
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *RevokeUserSessionRequest) Reset() {
|
||||
*x = RevokeUserSessionRequest{}
|
||||
mi := &file_api_v1_user_service_proto_msgTypes[23]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *RevokeUserSessionRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*RevokeUserSessionRequest) ProtoMessage() {}
|
||||
|
||||
func (x *RevokeUserSessionRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_v1_user_service_proto_msgTypes[23]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use RevokeUserSessionRequest.ProtoReflect.Descriptor instead.
|
||||
func (*RevokeUserSessionRequest) Descriptor() ([]byte, []int) {
|
||||
return file_api_v1_user_service_proto_rawDescGZIP(), []int{23}
|
||||
}
|
||||
|
||||
func (x *RevokeUserSessionRequest) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ListAllUserStatsRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Optional. The maximum number of user stats to return.
|
||||
|
|
@ -1455,7 +1683,7 @@ type ListAllUserStatsRequest struct {
|
|||
|
||||
func (x *ListAllUserStatsRequest) Reset() {
|
||||
*x = ListAllUserStatsRequest{}
|
||||
mi := &file_api_v1_user_service_proto_msgTypes[20]
|
||||
mi := &file_api_v1_user_service_proto_msgTypes[24]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
|
@ -1467,7 +1695,7 @@ func (x *ListAllUserStatsRequest) String() string {
|
|||
func (*ListAllUserStatsRequest) ProtoMessage() {}
|
||||
|
||||
func (x *ListAllUserStatsRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_v1_user_service_proto_msgTypes[20]
|
||||
mi := &file_api_v1_user_service_proto_msgTypes[24]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
|
|
@ -1480,7 +1708,7 @@ func (x *ListAllUserStatsRequest) ProtoReflect() protoreflect.Message {
|
|||
|
||||
// Deprecated: Use ListAllUserStatsRequest.ProtoReflect.Descriptor instead.
|
||||
func (*ListAllUserStatsRequest) Descriptor() ([]byte, []int) {
|
||||
return file_api_v1_user_service_proto_rawDescGZIP(), []int{20}
|
||||
return file_api_v1_user_service_proto_rawDescGZIP(), []int{24}
|
||||
}
|
||||
|
||||
func (x *ListAllUserStatsRequest) GetPageSize() int32 {
|
||||
|
|
@ -1511,7 +1739,7 @@ type ListAllUserStatsResponse struct {
|
|||
|
||||
func (x *ListAllUserStatsResponse) Reset() {
|
||||
*x = ListAllUserStatsResponse{}
|
||||
mi := &file_api_v1_user_service_proto_msgTypes[21]
|
||||
mi := &file_api_v1_user_service_proto_msgTypes[25]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
|
@ -1523,7 +1751,7 @@ func (x *ListAllUserStatsResponse) String() string {
|
|||
func (*ListAllUserStatsResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ListAllUserStatsResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_v1_user_service_proto_msgTypes[21]
|
||||
mi := &file_api_v1_user_service_proto_msgTypes[25]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
|
|
@ -1536,7 +1764,7 @@ func (x *ListAllUserStatsResponse) ProtoReflect() protoreflect.Message {
|
|||
|
||||
// Deprecated: Use ListAllUserStatsResponse.ProtoReflect.Descriptor instead.
|
||||
func (*ListAllUserStatsResponse) Descriptor() ([]byte, []int) {
|
||||
return file_api_v1_user_service_proto_rawDescGZIP(), []int{21}
|
||||
return file_api_v1_user_service_proto_rawDescGZIP(), []int{25}
|
||||
}
|
||||
|
||||
func (x *ListAllUserStatsResponse) GetUserStats() []*UserStats {
|
||||
|
|
@ -1573,7 +1801,7 @@ type UserStats_MemoTypeStats struct {
|
|||
|
||||
func (x *UserStats_MemoTypeStats) Reset() {
|
||||
*x = UserStats_MemoTypeStats{}
|
||||
mi := &file_api_v1_user_service_proto_msgTypes[23]
|
||||
mi := &file_api_v1_user_service_proto_msgTypes[27]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
|
@ -1585,7 +1813,7 @@ func (x *UserStats_MemoTypeStats) String() string {
|
|||
func (*UserStats_MemoTypeStats) ProtoMessage() {}
|
||||
|
||||
func (x *UserStats_MemoTypeStats) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_v1_user_service_proto_msgTypes[23]
|
||||
mi := &file_api_v1_user_service_proto_msgTypes[27]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
|
|
@ -1629,6 +1857,96 @@ func (x *UserStats_MemoTypeStats) GetUndoCount() int32 {
|
|||
return 0
|
||||
}
|
||||
|
||||
type UserSession_ClientInfo struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// User agent string of the client.
|
||||
UserAgent string `protobuf:"bytes,1,opt,name=user_agent,json=userAgent,proto3" json:"user_agent,omitempty"`
|
||||
// IP address of the client.
|
||||
IpAddress string `protobuf:"bytes,2,opt,name=ip_address,json=ipAddress,proto3" json:"ip_address,omitempty"`
|
||||
// Optional. Device type (e.g., "mobile", "desktop", "tablet").
|
||||
DeviceType string `protobuf:"bytes,3,opt,name=device_type,json=deviceType,proto3" json:"device_type,omitempty"`
|
||||
// Optional. Operating system (e.g., "iOS 17.0", "Windows 11").
|
||||
Os string `protobuf:"bytes,4,opt,name=os,proto3" json:"os,omitempty"`
|
||||
// Optional. Browser name and version (e.g., "Chrome 119.0").
|
||||
Browser string `protobuf:"bytes,5,opt,name=browser,proto3" json:"browser,omitempty"`
|
||||
// Optional. Geographic location (country code, e.g., "US").
|
||||
Country string `protobuf:"bytes,6,opt,name=country,proto3" json:"country,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *UserSession_ClientInfo) Reset() {
|
||||
*x = UserSession_ClientInfo{}
|
||||
mi := &file_api_v1_user_service_proto_msgTypes[28]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *UserSession_ClientInfo) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*UserSession_ClientInfo) ProtoMessage() {}
|
||||
|
||||
func (x *UserSession_ClientInfo) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_api_v1_user_service_proto_msgTypes[28]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use UserSession_ClientInfo.ProtoReflect.Descriptor instead.
|
||||
func (*UserSession_ClientInfo) Descriptor() ([]byte, []int) {
|
||||
return file_api_v1_user_service_proto_rawDescGZIP(), []int{20, 0}
|
||||
}
|
||||
|
||||
func (x *UserSession_ClientInfo) GetUserAgent() string {
|
||||
if x != nil {
|
||||
return x.UserAgent
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *UserSession_ClientInfo) GetIpAddress() string {
|
||||
if x != nil {
|
||||
return x.IpAddress
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *UserSession_ClientInfo) GetDeviceType() string {
|
||||
if x != nil {
|
||||
return x.DeviceType
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *UserSession_ClientInfo) GetOs() string {
|
||||
if x != nil {
|
||||
return x.Os
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *UserSession_ClientInfo) GetBrowser() string {
|
||||
if x != nil {
|
||||
return x.Browser
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *UserSession_ClientInfo) GetCountry() string {
|
||||
if x != nil {
|
||||
return x.Country
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_api_v1_user_service_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_api_v1_user_service_proto_rawDesc = "" +
|
||||
|
|
@ -1766,7 +2084,38 @@ const file_api_v1_user_service_proto_rawDesc = "" +
|
|||
"\x0faccess_token_id\x18\x03 \x01(\tB\x03\xe0A\x01R\raccessTokenId\"X\n" +
|
||||
"\x1cDeleteUserAccessTokenRequest\x128\n" +
|
||||
"\x04name\x18\x01 \x01(\tB$\xe0A\x02\xfaA\x1e\n" +
|
||||
"\x1cmemos.api.v1/UserAccessTokenR\x04name\"_\n" +
|
||||
"\x1cmemos.api.v1/UserAccessTokenR\x04name\"\xf5\x04\n" +
|
||||
"\vUserSession\x12\x17\n" +
|
||||
"\x04name\x18\x01 \x01(\tB\x03\xe0A\bR\x04name\x12\"\n" +
|
||||
"\n" +
|
||||
"session_id\x18\x02 \x01(\tB\x03\xe0A\x03R\tsessionId\x12@\n" +
|
||||
"\vcreate_time\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampB\x03\xe0A\x03R\n" +
|
||||
"createTime\x12@\n" +
|
||||
"\vexpire_time\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampB\x03\xe0A\x03R\n" +
|
||||
"expireTime\x12M\n" +
|
||||
"\x12last_accessed_time\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampB\x03\xe0A\x03R\x10lastAccessedTime\x12J\n" +
|
||||
"\vclient_info\x18\x06 \x01(\v2$.memos.api.v1.UserSession.ClientInfoB\x03\xe0A\x03R\n" +
|
||||
"clientInfo\x1a\xc3\x01\n" +
|
||||
"\n" +
|
||||
"ClientInfo\x12\x1d\n" +
|
||||
"\n" +
|
||||
"user_agent\x18\x01 \x01(\tR\tuserAgent\x12\x1d\n" +
|
||||
"\n" +
|
||||
"ip_address\x18\x02 \x01(\tR\tipAddress\x12$\n" +
|
||||
"\vdevice_type\x18\x03 \x01(\tB\x03\xe0A\x01R\n" +
|
||||
"deviceType\x12\x13\n" +
|
||||
"\x02os\x18\x04 \x01(\tB\x03\xe0A\x01R\x02os\x12\x1d\n" +
|
||||
"\abrowser\x18\x05 \x01(\tB\x03\xe0A\x01R\abrowser\x12\x1d\n" +
|
||||
"\acountry\x18\x06 \x01(\tB\x03\xe0A\x01R\acountry:D\xeaAA\n" +
|
||||
"\x18memos.api.v1/UserSession\x12\x1fusers/{user}/sessions/{session}\x1a\x04name\"L\n" +
|
||||
"\x17ListUserSessionsRequest\x121\n" +
|
||||
"\x06parent\x18\x01 \x01(\tB\x19\xe0A\x02\xfaA\x13\n" +
|
||||
"\x11memos.api.v1/UserR\x06parent\"Q\n" +
|
||||
"\x18ListUserSessionsResponse\x125\n" +
|
||||
"\bsessions\x18\x01 \x03(\v2\x19.memos.api.v1.UserSessionR\bsessions\"P\n" +
|
||||
"\x18RevokeUserSessionRequest\x124\n" +
|
||||
"\x04name\x18\x01 \x01(\tB \xe0A\x02\xfaA\x1a\n" +
|
||||
"\x18memos.api.v1/UserSessionR\x04name\"_\n" +
|
||||
"\x17ListAllUserStatsRequest\x12 \n" +
|
||||
"\tpage_size\x18\x01 \x01(\x05B\x03\xe0A\x01R\bpageSize\x12\"\n" +
|
||||
"\n" +
|
||||
|
|
@ -1776,7 +2125,7 @@ const file_api_v1_user_service_proto_rawDesc = "" +
|
|||
"user_stats\x18\x01 \x03(\v2\x17.memos.api.v1.UserStatsR\tuserStats\x12&\n" +
|
||||
"\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\x12\x1d\n" +
|
||||
"\n" +
|
||||
"total_size\x18\x03 \x01(\x05R\ttotalSize2\xc2\x0e\n" +
|
||||
"total_size\x18\x03 \x01(\x05R\ttotalSize2\xe2\x10\n" +
|
||||
"\vUserService\x12c\n" +
|
||||
"\tListUsers\x12\x1e.memos.api.v1.ListUsersRequest\x1a\x1f.memos.api.v1.ListUsersResponse\"\x15\x82\xd3\xe4\x93\x02\x0f\x12\r/api/v1/users\x12b\n" +
|
||||
"\aGetUser\x12\x1c.memos.api.v1.GetUserRequest\x1a\x12.memos.api.v1.User\"%\xdaA\x04name\x82\xd3\xe4\x93\x02\x18\x12\x16/api/v1/{name=users/*}\x12e\n" +
|
||||
|
|
@ -1794,7 +2143,9 @@ const file_api_v1_user_service_proto_rawDesc = "" +
|
|||
"\x11UpdateUserSetting\x12&.memos.api.v1.UpdateUserSettingRequest\x1a\x19.memos.api.v1.UserSetting\"S\xdaA\x13setting,update_mask\x82\xd3\xe4\x93\x027:\asetting2,/api/v1/{setting.name=users/*}:updateSetting\x12\xa5\x01\n" +
|
||||
"\x14ListUserAccessTokens\x12).memos.api.v1.ListUserAccessTokensRequest\x1a*.memos.api.v1.ListUserAccessTokensResponse\"6\xdaA\x06parent\x82\xd3\xe4\x93\x02'\x12%/api/v1/{parent=users/*}/accessTokens\x12\xb5\x01\n" +
|
||||
"\x15CreateUserAccessToken\x12*.memos.api.v1.CreateUserAccessTokenRequest\x1a\x1d.memos.api.v1.UserAccessToken\"Q\xdaA\x13parent,access_token\x82\xd3\xe4\x93\x025:\faccess_token\"%/api/v1/{parent=users/*}/accessTokens\x12\x91\x01\n" +
|
||||
"\x15DeleteUserAccessToken\x12*.memos.api.v1.DeleteUserAccessTokenRequest\x1a\x16.google.protobuf.Empty\"4\xdaA\x04name\x82\xd3\xe4\x93\x02'*%/api/v1/{name=users/*/accessTokens/*}B\xa8\x01\n" +
|
||||
"\x15DeleteUserAccessToken\x12*.memos.api.v1.DeleteUserAccessTokenRequest\x1a\x16.google.protobuf.Empty\"4\xdaA\x04name\x82\xd3\xe4\x93\x02'*%/api/v1/{name=users/*/accessTokens/*}\x12\x95\x01\n" +
|
||||
"\x10ListUserSessions\x12%.memos.api.v1.ListUserSessionsRequest\x1a&.memos.api.v1.ListUserSessionsResponse\"2\xdaA\x06parent\x82\xd3\xe4\x93\x02#\x12!/api/v1/{parent=users/*}/sessions\x12\x85\x01\n" +
|
||||
"\x11RevokeUserSession\x12&.memos.api.v1.RevokeUserSessionRequest\x1a\x16.google.protobuf.Empty\"0\xdaA\x04name\x82\xd3\xe4\x93\x02#*!/api/v1/{name=users/*/sessions/*}B\xa8\x01\n" +
|
||||
"\x10com.memos.api.v1B\x10UserServiceProtoP\x01Z0github.com/usememos/memos/proto/gen/api/v1;apiv1\xa2\x02\x03MAX\xaa\x02\fMemos.Api.V1\xca\x02\fMemos\\Api\\V1\xe2\x02\x18Memos\\Api\\V1\\GPBMetadata\xea\x02\x0eMemos::Api::V1b\x06proto3"
|
||||
|
||||
var (
|
||||
|
|
@ -1810,7 +2161,7 @@ func file_api_v1_user_service_proto_rawDescGZIP() []byte {
|
|||
}
|
||||
|
||||
var file_api_v1_user_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_api_v1_user_service_proto_msgTypes = make([]protoimpl.MessageInfo, 24)
|
||||
var file_api_v1_user_service_proto_msgTypes = make([]protoimpl.MessageInfo, 29)
|
||||
var file_api_v1_user_service_proto_goTypes = []any{
|
||||
(User_Role)(0), // 0: memos.api.v1.User.Role
|
||||
(*User)(nil), // 1: memos.api.v1.User
|
||||
|
|
@ -1833,70 +2184,84 @@ var file_api_v1_user_service_proto_goTypes = []any{
|
|||
(*ListUserAccessTokensResponse)(nil), // 18: memos.api.v1.ListUserAccessTokensResponse
|
||||
(*CreateUserAccessTokenRequest)(nil), // 19: memos.api.v1.CreateUserAccessTokenRequest
|
||||
(*DeleteUserAccessTokenRequest)(nil), // 20: memos.api.v1.DeleteUserAccessTokenRequest
|
||||
(*ListAllUserStatsRequest)(nil), // 21: memos.api.v1.ListAllUserStatsRequest
|
||||
(*ListAllUserStatsResponse)(nil), // 22: memos.api.v1.ListAllUserStatsResponse
|
||||
nil, // 23: memos.api.v1.UserStats.TagCountEntry
|
||||
(*UserStats_MemoTypeStats)(nil), // 24: memos.api.v1.UserStats.MemoTypeStats
|
||||
(State)(0), // 25: memos.api.v1.State
|
||||
(*timestamppb.Timestamp)(nil), // 26: google.protobuf.Timestamp
|
||||
(*fieldmaskpb.FieldMask)(nil), // 27: google.protobuf.FieldMask
|
||||
(*emptypb.Empty)(nil), // 28: google.protobuf.Empty
|
||||
(*httpbody.HttpBody)(nil), // 29: google.api.HttpBody
|
||||
(*UserSession)(nil), // 21: memos.api.v1.UserSession
|
||||
(*ListUserSessionsRequest)(nil), // 22: memos.api.v1.ListUserSessionsRequest
|
||||
(*ListUserSessionsResponse)(nil), // 23: memos.api.v1.ListUserSessionsResponse
|
||||
(*RevokeUserSessionRequest)(nil), // 24: memos.api.v1.RevokeUserSessionRequest
|
||||
(*ListAllUserStatsRequest)(nil), // 25: memos.api.v1.ListAllUserStatsRequest
|
||||
(*ListAllUserStatsResponse)(nil), // 26: memos.api.v1.ListAllUserStatsResponse
|
||||
nil, // 27: memos.api.v1.UserStats.TagCountEntry
|
||||
(*UserStats_MemoTypeStats)(nil), // 28: memos.api.v1.UserStats.MemoTypeStats
|
||||
(*UserSession_ClientInfo)(nil), // 29: memos.api.v1.UserSession.ClientInfo
|
||||
(State)(0), // 30: memos.api.v1.State
|
||||
(*timestamppb.Timestamp)(nil), // 31: google.protobuf.Timestamp
|
||||
(*fieldmaskpb.FieldMask)(nil), // 32: google.protobuf.FieldMask
|
||||
(*emptypb.Empty)(nil), // 33: google.protobuf.Empty
|
||||
(*httpbody.HttpBody)(nil), // 34: google.api.HttpBody
|
||||
}
|
||||
var file_api_v1_user_service_proto_depIdxs = []int32{
|
||||
0, // 0: memos.api.v1.User.role:type_name -> memos.api.v1.User.Role
|
||||
25, // 1: memos.api.v1.User.state:type_name -> memos.api.v1.State
|
||||
26, // 2: memos.api.v1.User.create_time:type_name -> google.protobuf.Timestamp
|
||||
26, // 3: memos.api.v1.User.update_time:type_name -> google.protobuf.Timestamp
|
||||
30, // 1: memos.api.v1.User.state:type_name -> memos.api.v1.State
|
||||
31, // 2: memos.api.v1.User.create_time:type_name -> google.protobuf.Timestamp
|
||||
31, // 3: memos.api.v1.User.update_time:type_name -> google.protobuf.Timestamp
|
||||
1, // 4: memos.api.v1.ListUsersResponse.users:type_name -> memos.api.v1.User
|
||||
27, // 5: memos.api.v1.GetUserRequest.read_mask:type_name -> google.protobuf.FieldMask
|
||||
32, // 5: memos.api.v1.GetUserRequest.read_mask:type_name -> google.protobuf.FieldMask
|
||||
1, // 6: memos.api.v1.CreateUserRequest.user:type_name -> memos.api.v1.User
|
||||
1, // 7: memos.api.v1.UpdateUserRequest.user:type_name -> memos.api.v1.User
|
||||
27, // 8: memos.api.v1.UpdateUserRequest.update_mask:type_name -> google.protobuf.FieldMask
|
||||
32, // 8: memos.api.v1.UpdateUserRequest.update_mask:type_name -> google.protobuf.FieldMask
|
||||
1, // 9: memos.api.v1.SearchUsersResponse.users:type_name -> memos.api.v1.User
|
||||
26, // 10: memos.api.v1.UserStats.memo_display_timestamps:type_name -> google.protobuf.Timestamp
|
||||
24, // 11: memos.api.v1.UserStats.memo_type_stats:type_name -> memos.api.v1.UserStats.MemoTypeStats
|
||||
23, // 12: memos.api.v1.UserStats.tag_count:type_name -> memos.api.v1.UserStats.TagCountEntry
|
||||
31, // 10: memos.api.v1.UserStats.memo_display_timestamps:type_name -> google.protobuf.Timestamp
|
||||
28, // 11: memos.api.v1.UserStats.memo_type_stats:type_name -> memos.api.v1.UserStats.MemoTypeStats
|
||||
27, // 12: memos.api.v1.UserStats.tag_count:type_name -> memos.api.v1.UserStats.TagCountEntry
|
||||
13, // 13: memos.api.v1.UpdateUserSettingRequest.setting:type_name -> memos.api.v1.UserSetting
|
||||
27, // 14: memos.api.v1.UpdateUserSettingRequest.update_mask:type_name -> google.protobuf.FieldMask
|
||||
26, // 15: memos.api.v1.UserAccessToken.issued_at:type_name -> google.protobuf.Timestamp
|
||||
26, // 16: memos.api.v1.UserAccessToken.expires_at:type_name -> google.protobuf.Timestamp
|
||||
32, // 14: memos.api.v1.UpdateUserSettingRequest.update_mask:type_name -> google.protobuf.FieldMask
|
||||
31, // 15: memos.api.v1.UserAccessToken.issued_at:type_name -> google.protobuf.Timestamp
|
||||
31, // 16: memos.api.v1.UserAccessToken.expires_at:type_name -> google.protobuf.Timestamp
|
||||
16, // 17: memos.api.v1.ListUserAccessTokensResponse.access_tokens:type_name -> memos.api.v1.UserAccessToken
|
||||
16, // 18: memos.api.v1.CreateUserAccessTokenRequest.access_token:type_name -> memos.api.v1.UserAccessToken
|
||||
11, // 19: memos.api.v1.ListAllUserStatsResponse.user_stats:type_name -> memos.api.v1.UserStats
|
||||
2, // 20: memos.api.v1.UserService.ListUsers:input_type -> memos.api.v1.ListUsersRequest
|
||||
4, // 21: memos.api.v1.UserService.GetUser:input_type -> memos.api.v1.GetUserRequest
|
||||
5, // 22: memos.api.v1.UserService.CreateUser:input_type -> memos.api.v1.CreateUserRequest
|
||||
6, // 23: memos.api.v1.UserService.UpdateUser:input_type -> memos.api.v1.UpdateUserRequest
|
||||
7, // 24: memos.api.v1.UserService.DeleteUser:input_type -> memos.api.v1.DeleteUserRequest
|
||||
8, // 25: memos.api.v1.UserService.SearchUsers:input_type -> memos.api.v1.SearchUsersRequest
|
||||
10, // 26: memos.api.v1.UserService.GetUserAvatar:input_type -> memos.api.v1.GetUserAvatarRequest
|
||||
21, // 27: memos.api.v1.UserService.ListAllUserStats:input_type -> memos.api.v1.ListAllUserStatsRequest
|
||||
12, // 28: memos.api.v1.UserService.GetUserStats:input_type -> memos.api.v1.GetUserStatsRequest
|
||||
14, // 29: memos.api.v1.UserService.GetUserSetting:input_type -> memos.api.v1.GetUserSettingRequest
|
||||
15, // 30: memos.api.v1.UserService.UpdateUserSetting:input_type -> memos.api.v1.UpdateUserSettingRequest
|
||||
17, // 31: memos.api.v1.UserService.ListUserAccessTokens:input_type -> memos.api.v1.ListUserAccessTokensRequest
|
||||
19, // 32: memos.api.v1.UserService.CreateUserAccessToken:input_type -> memos.api.v1.CreateUserAccessTokenRequest
|
||||
20, // 33: memos.api.v1.UserService.DeleteUserAccessToken:input_type -> memos.api.v1.DeleteUserAccessTokenRequest
|
||||
3, // 34: memos.api.v1.UserService.ListUsers:output_type -> memos.api.v1.ListUsersResponse
|
||||
1, // 35: memos.api.v1.UserService.GetUser:output_type -> memos.api.v1.User
|
||||
1, // 36: memos.api.v1.UserService.CreateUser:output_type -> memos.api.v1.User
|
||||
1, // 37: memos.api.v1.UserService.UpdateUser:output_type -> memos.api.v1.User
|
||||
28, // 38: memos.api.v1.UserService.DeleteUser:output_type -> google.protobuf.Empty
|
||||
9, // 39: memos.api.v1.UserService.SearchUsers:output_type -> memos.api.v1.SearchUsersResponse
|
||||
29, // 40: memos.api.v1.UserService.GetUserAvatar:output_type -> google.api.HttpBody
|
||||
22, // 41: memos.api.v1.UserService.ListAllUserStats:output_type -> memos.api.v1.ListAllUserStatsResponse
|
||||
11, // 42: memos.api.v1.UserService.GetUserStats:output_type -> memos.api.v1.UserStats
|
||||
13, // 43: memos.api.v1.UserService.GetUserSetting:output_type -> memos.api.v1.UserSetting
|
||||
13, // 44: memos.api.v1.UserService.UpdateUserSetting:output_type -> memos.api.v1.UserSetting
|
||||
18, // 45: memos.api.v1.UserService.ListUserAccessTokens:output_type -> memos.api.v1.ListUserAccessTokensResponse
|
||||
16, // 46: memos.api.v1.UserService.CreateUserAccessToken:output_type -> memos.api.v1.UserAccessToken
|
||||
28, // 47: memos.api.v1.UserService.DeleteUserAccessToken:output_type -> google.protobuf.Empty
|
||||
34, // [34:48] is the sub-list for method output_type
|
||||
20, // [20:34] is the sub-list for method input_type
|
||||
20, // [20:20] is the sub-list for extension type_name
|
||||
20, // [20:20] is the sub-list for extension extendee
|
||||
0, // [0:20] is the sub-list for field type_name
|
||||
31, // 19: memos.api.v1.UserSession.create_time:type_name -> google.protobuf.Timestamp
|
||||
31, // 20: memos.api.v1.UserSession.expire_time:type_name -> google.protobuf.Timestamp
|
||||
31, // 21: memos.api.v1.UserSession.last_accessed_time:type_name -> google.protobuf.Timestamp
|
||||
29, // 22: memos.api.v1.UserSession.client_info:type_name -> memos.api.v1.UserSession.ClientInfo
|
||||
21, // 23: memos.api.v1.ListUserSessionsResponse.sessions:type_name -> memos.api.v1.UserSession
|
||||
11, // 24: memos.api.v1.ListAllUserStatsResponse.user_stats:type_name -> memos.api.v1.UserStats
|
||||
2, // 25: memos.api.v1.UserService.ListUsers:input_type -> memos.api.v1.ListUsersRequest
|
||||
4, // 26: memos.api.v1.UserService.GetUser:input_type -> memos.api.v1.GetUserRequest
|
||||
5, // 27: memos.api.v1.UserService.CreateUser:input_type -> memos.api.v1.CreateUserRequest
|
||||
6, // 28: memos.api.v1.UserService.UpdateUser:input_type -> memos.api.v1.UpdateUserRequest
|
||||
7, // 29: memos.api.v1.UserService.DeleteUser:input_type -> memos.api.v1.DeleteUserRequest
|
||||
8, // 30: memos.api.v1.UserService.SearchUsers:input_type -> memos.api.v1.SearchUsersRequest
|
||||
10, // 31: memos.api.v1.UserService.GetUserAvatar:input_type -> memos.api.v1.GetUserAvatarRequest
|
||||
25, // 32: memos.api.v1.UserService.ListAllUserStats:input_type -> memos.api.v1.ListAllUserStatsRequest
|
||||
12, // 33: memos.api.v1.UserService.GetUserStats:input_type -> memos.api.v1.GetUserStatsRequest
|
||||
14, // 34: memos.api.v1.UserService.GetUserSetting:input_type -> memos.api.v1.GetUserSettingRequest
|
||||
15, // 35: memos.api.v1.UserService.UpdateUserSetting:input_type -> memos.api.v1.UpdateUserSettingRequest
|
||||
17, // 36: memos.api.v1.UserService.ListUserAccessTokens:input_type -> memos.api.v1.ListUserAccessTokensRequest
|
||||
19, // 37: memos.api.v1.UserService.CreateUserAccessToken:input_type -> memos.api.v1.CreateUserAccessTokenRequest
|
||||
20, // 38: memos.api.v1.UserService.DeleteUserAccessToken:input_type -> memos.api.v1.DeleteUserAccessTokenRequest
|
||||
22, // 39: memos.api.v1.UserService.ListUserSessions:input_type -> memos.api.v1.ListUserSessionsRequest
|
||||
24, // 40: memos.api.v1.UserService.RevokeUserSession:input_type -> memos.api.v1.RevokeUserSessionRequest
|
||||
3, // 41: memos.api.v1.UserService.ListUsers:output_type -> memos.api.v1.ListUsersResponse
|
||||
1, // 42: memos.api.v1.UserService.GetUser:output_type -> memos.api.v1.User
|
||||
1, // 43: memos.api.v1.UserService.CreateUser:output_type -> memos.api.v1.User
|
||||
1, // 44: memos.api.v1.UserService.UpdateUser:output_type -> memos.api.v1.User
|
||||
33, // 45: memos.api.v1.UserService.DeleteUser:output_type -> google.protobuf.Empty
|
||||
9, // 46: memos.api.v1.UserService.SearchUsers:output_type -> memos.api.v1.SearchUsersResponse
|
||||
34, // 47: memos.api.v1.UserService.GetUserAvatar:output_type -> google.api.HttpBody
|
||||
26, // 48: memos.api.v1.UserService.ListAllUserStats:output_type -> memos.api.v1.ListAllUserStatsResponse
|
||||
11, // 49: memos.api.v1.UserService.GetUserStats:output_type -> memos.api.v1.UserStats
|
||||
13, // 50: memos.api.v1.UserService.GetUserSetting:output_type -> memos.api.v1.UserSetting
|
||||
13, // 51: memos.api.v1.UserService.UpdateUserSetting:output_type -> memos.api.v1.UserSetting
|
||||
18, // 52: memos.api.v1.UserService.ListUserAccessTokens:output_type -> memos.api.v1.ListUserAccessTokensResponse
|
||||
16, // 53: memos.api.v1.UserService.CreateUserAccessToken:output_type -> memos.api.v1.UserAccessToken
|
||||
33, // 54: memos.api.v1.UserService.DeleteUserAccessToken:output_type -> google.protobuf.Empty
|
||||
23, // 55: memos.api.v1.UserService.ListUserSessions:output_type -> memos.api.v1.ListUserSessionsResponse
|
||||
33, // 56: memos.api.v1.UserService.RevokeUserSession:output_type -> google.protobuf.Empty
|
||||
41, // [41:57] is the sub-list for method output_type
|
||||
25, // [25:41] is the sub-list for method input_type
|
||||
25, // [25:25] is the sub-list for extension type_name
|
||||
25, // [25:25] is the sub-list for extension extendee
|
||||
0, // [0:25] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_api_v1_user_service_proto_init() }
|
||||
|
|
@ -1911,7 +2276,7 @@ func file_api_v1_user_service_proto_init() {
|
|||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_v1_user_service_proto_rawDesc), len(file_api_v1_user_service_proto_rawDesc)),
|
||||
NumEnums: 1,
|
||||
NumMessages: 24,
|
||||
NumMessages: 29,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -717,6 +717,84 @@ func local_request_UserService_DeleteUserAccessToken_0(ctx context.Context, mars
|
|||
return msg, metadata, err
|
||||
}
|
||||
|
||||
func request_UserService_ListUserSessions_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var (
|
||||
protoReq ListUserSessionsRequest
|
||||
metadata runtime.ServerMetadata
|
||||
err error
|
||||
)
|
||||
if req.Body != nil {
|
||||
_, _ = io.Copy(io.Discard, req.Body)
|
||||
}
|
||||
val, ok := pathParams["parent"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "parent")
|
||||
}
|
||||
protoReq.Parent, err = runtime.String(val)
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "parent", err)
|
||||
}
|
||||
msg, err := client.ListUserSessions(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
}
|
||||
|
||||
func local_request_UserService_ListUserSessions_0(ctx context.Context, marshaler runtime.Marshaler, server UserServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var (
|
||||
protoReq ListUserSessionsRequest
|
||||
metadata runtime.ServerMetadata
|
||||
err error
|
||||
)
|
||||
val, ok := pathParams["parent"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "parent")
|
||||
}
|
||||
protoReq.Parent, err = runtime.String(val)
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "parent", err)
|
||||
}
|
||||
msg, err := server.ListUserSessions(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
}
|
||||
|
||||
func request_UserService_RevokeUserSession_0(ctx context.Context, marshaler runtime.Marshaler, client UserServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var (
|
||||
protoReq RevokeUserSessionRequest
|
||||
metadata runtime.ServerMetadata
|
||||
err error
|
||||
)
|
||||
if req.Body != nil {
|
||||
_, _ = io.Copy(io.Discard, req.Body)
|
||||
}
|
||||
val, ok := pathParams["name"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name")
|
||||
}
|
||||
protoReq.Name, err = runtime.String(val)
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err)
|
||||
}
|
||||
msg, err := client.RevokeUserSession(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
}
|
||||
|
||||
func local_request_UserService_RevokeUserSession_0(ctx context.Context, marshaler runtime.Marshaler, server UserServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var (
|
||||
protoReq RevokeUserSessionRequest
|
||||
metadata runtime.ServerMetadata
|
||||
err error
|
||||
)
|
||||
val, ok := pathParams["name"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name")
|
||||
}
|
||||
protoReq.Name, err = runtime.String(val)
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err)
|
||||
}
|
||||
msg, err := server.RevokeUserSession(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
}
|
||||
|
||||
// RegisterUserServiceHandlerServer registers the http handlers for service UserService to "mux".
|
||||
// UnaryRPC :call UserServiceServer directly.
|
||||
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
||||
|
|
@ -1003,6 +1081,46 @@ func RegisterUserServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux
|
|||
}
|
||||
forward_UserService_DeleteUserAccessToken_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
})
|
||||
mux.Handle(http.MethodGet, pattern_UserService_ListUserSessions_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.UserService/ListUserSessions", runtime.WithHTTPPathPattern("/api/v1/{parent=users/*}/sessions"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_UserService_ListUserSessions_0(annotatedContext, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
forward_UserService_ListUserSessions_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
})
|
||||
mux.Handle(http.MethodDelete, pattern_UserService_RevokeUserSession_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
var stream runtime.ServerTransportStream
|
||||
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.UserService/RevokeUserSession", runtime.WithHTTPPathPattern("/api/v1/{name=users/*/sessions/*}"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_UserService_RevokeUserSession_0(annotatedContext, inboundMarshaler, server, req, pathParams)
|
||||
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
forward_UserService_RevokeUserSession_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1281,6 +1399,40 @@ func RegisterUserServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux
|
|||
}
|
||||
forward_UserService_DeleteUserAccessToken_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
})
|
||||
mux.Handle(http.MethodGet, pattern_UserService_ListUserSessions_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.UserService/ListUserSessions", runtime.WithHTTPPathPattern("/api/v1/{parent=users/*}/sessions"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_UserService_ListUserSessions_0(annotatedContext, inboundMarshaler, client, req, pathParams)
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
forward_UserService_ListUserSessions_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
})
|
||||
mux.Handle(http.MethodDelete, pattern_UserService_RevokeUserSession_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.UserService/RevokeUserSession", runtime.WithHTTPPathPattern("/api/v1/{name=users/*/sessions/*}"))
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_UserService_RevokeUserSession_0(annotatedContext, inboundMarshaler, client, req, pathParams)
|
||||
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
forward_UserService_RevokeUserSession_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -1299,6 +1451,8 @@ var (
|
|||
pattern_UserService_ListUserAccessTokens_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "parent", "accessTokens"}, ""))
|
||||
pattern_UserService_CreateUserAccessToken_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "parent", "accessTokens"}, ""))
|
||||
pattern_UserService_DeleteUserAccessToken_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", "users", "accessTokens", "name"}, ""))
|
||||
pattern_UserService_ListUserSessions_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3, 2, 4}, []string{"api", "v1", "users", "parent", "sessions"}, ""))
|
||||
pattern_UserService_RevokeUserSession_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", "users", "sessions", "name"}, ""))
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -1316,4 +1470,6 @@ var (
|
|||
forward_UserService_ListUserAccessTokens_0 = runtime.ForwardResponseMessage
|
||||
forward_UserService_CreateUserAccessToken_0 = runtime.ForwardResponseMessage
|
||||
forward_UserService_DeleteUserAccessToken_0 = runtime.ForwardResponseMessage
|
||||
forward_UserService_ListUserSessions_0 = runtime.ForwardResponseMessage
|
||||
forward_UserService_RevokeUserSession_0 = runtime.ForwardResponseMessage
|
||||
)
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ const (
|
|||
UserService_ListUserAccessTokens_FullMethodName = "/memos.api.v1.UserService/ListUserAccessTokens"
|
||||
UserService_CreateUserAccessToken_FullMethodName = "/memos.api.v1.UserService/CreateUserAccessToken"
|
||||
UserService_DeleteUserAccessToken_FullMethodName = "/memos.api.v1.UserService/DeleteUserAccessToken"
|
||||
UserService_ListUserSessions_FullMethodName = "/memos.api.v1.UserService/ListUserSessions"
|
||||
UserService_RevokeUserSession_FullMethodName = "/memos.api.v1.UserService/RevokeUserSession"
|
||||
)
|
||||
|
||||
// UserServiceClient is the client API for UserService service.
|
||||
|
|
@ -69,6 +71,10 @@ type UserServiceClient interface {
|
|||
CreateUserAccessToken(ctx context.Context, in *CreateUserAccessTokenRequest, opts ...grpc.CallOption) (*UserAccessToken, error)
|
||||
// DeleteUserAccessToken deletes an access token.
|
||||
DeleteUserAccessToken(ctx context.Context, in *DeleteUserAccessTokenRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||
// ListUserSessions returns a list of active sessions for a user.
|
||||
ListUserSessions(ctx context.Context, in *ListUserSessionsRequest, opts ...grpc.CallOption) (*ListUserSessionsResponse, error)
|
||||
// RevokeUserSession revokes a specific session for a user.
|
||||
RevokeUserSession(ctx context.Context, in *RevokeUserSessionRequest, opts ...grpc.CallOption) (*emptypb.Empty, error)
|
||||
}
|
||||
|
||||
type userServiceClient struct {
|
||||
|
|
@ -219,6 +225,26 @@ func (c *userServiceClient) DeleteUserAccessToken(ctx context.Context, in *Delet
|
|||
return out, nil
|
||||
}
|
||||
|
||||
func (c *userServiceClient) ListUserSessions(ctx context.Context, in *ListUserSessionsRequest, opts ...grpc.CallOption) (*ListUserSessionsResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(ListUserSessionsResponse)
|
||||
err := c.cc.Invoke(ctx, UserService_ListUserSessions_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *userServiceClient) RevokeUserSession(ctx context.Context, in *RevokeUserSessionRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(emptypb.Empty)
|
||||
err := c.cc.Invoke(ctx, UserService_RevokeUserSession_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// UserServiceServer is the server API for UserService service.
|
||||
// All implementations must embed UnimplementedUserServiceServer
|
||||
// for forward compatibility.
|
||||
|
|
@ -251,6 +277,10 @@ type UserServiceServer interface {
|
|||
CreateUserAccessToken(context.Context, *CreateUserAccessTokenRequest) (*UserAccessToken, error)
|
||||
// DeleteUserAccessToken deletes an access token.
|
||||
DeleteUserAccessToken(context.Context, *DeleteUserAccessTokenRequest) (*emptypb.Empty, error)
|
||||
// ListUserSessions returns a list of active sessions for a user.
|
||||
ListUserSessions(context.Context, *ListUserSessionsRequest) (*ListUserSessionsResponse, error)
|
||||
// RevokeUserSession revokes a specific session for a user.
|
||||
RevokeUserSession(context.Context, *RevokeUserSessionRequest) (*emptypb.Empty, error)
|
||||
mustEmbedUnimplementedUserServiceServer()
|
||||
}
|
||||
|
||||
|
|
@ -303,6 +333,12 @@ func (UnimplementedUserServiceServer) CreateUserAccessToken(context.Context, *Cr
|
|||
func (UnimplementedUserServiceServer) DeleteUserAccessToken(context.Context, *DeleteUserAccessTokenRequest) (*emptypb.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method DeleteUserAccessToken not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) ListUserSessions(context.Context, *ListUserSessionsRequest) (*ListUserSessionsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ListUserSessions not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) RevokeUserSession(context.Context, *RevokeUserSessionRequest) (*emptypb.Empty, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RevokeUserSession not implemented")
|
||||
}
|
||||
func (UnimplementedUserServiceServer) mustEmbedUnimplementedUserServiceServer() {}
|
||||
func (UnimplementedUserServiceServer) testEmbeddedByValue() {}
|
||||
|
||||
|
|
@ -576,6 +612,42 @@ func _UserService_DeleteUserAccessToken_Handler(srv interface{}, ctx context.Con
|
|||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _UserService_ListUserSessions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(ListUserSessionsRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(UserServiceServer).ListUserSessions(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: UserService_ListUserSessions_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(UserServiceServer).ListUserSessions(ctx, req.(*ListUserSessionsRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _UserService_RevokeUserSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(RevokeUserSessionRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(UserServiceServer).RevokeUserSession(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: UserService_RevokeUserSession_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(UserServiceServer).RevokeUserSession(ctx, req.(*RevokeUserSessionRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// UserService_ServiceDesc is the grpc.ServiceDesc for UserService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
|
|
@ -639,6 +711,14 @@ var UserService_ServiceDesc = grpc.ServiceDesc{
|
|||
MethodName: "DeleteUserAccessToken",
|
||||
Handler: _UserService_DeleteUserAccessToken_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ListUserSessions",
|
||||
Handler: _UserService_ListUserSessions_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "RevokeUserSession",
|
||||
Handler: _UserService_RevokeUserSession_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{},
|
||||
Metadata: "api/v1/user_service.proto",
|
||||
|
|
|
|||
|
|
@ -1193,8 +1193,8 @@ paths:
|
|||
tags:
|
||||
- IdentityProviderService
|
||||
delete:
|
||||
summary: DeleteIdentityProvider deletes an identity provider.
|
||||
operationId: IdentityProviderService_DeleteIdentityProvider
|
||||
summary: RevokeUserSession revokes a specific session for a user.
|
||||
operationId: UserService_RevokeUserSession
|
||||
responses:
|
||||
"200":
|
||||
description: A successful response.
|
||||
|
|
@ -1208,14 +1208,14 @@ paths:
|
|||
parameters:
|
||||
- name: name_3
|
||||
description: |-
|
||||
Required. The resource name of the identity provider to delete.
|
||||
Format: identityProviders/{idp}
|
||||
Required. The resource name of the session to revoke.
|
||||
Format: users/{user}/sessions/{session}
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
pattern: identityProviders/[^/]+
|
||||
pattern: users/[^/]+/sessions/[^/]+
|
||||
tags:
|
||||
- IdentityProviderService
|
||||
- UserService
|
||||
/api/v1/{name_4}:
|
||||
get:
|
||||
summary: GetMemo gets a memo.
|
||||
|
|
@ -1248,8 +1248,8 @@ paths:
|
|||
tags:
|
||||
- MemoService
|
||||
delete:
|
||||
summary: DeleteInbox deletes an inbox.
|
||||
operationId: InboxService_DeleteInbox
|
||||
summary: DeleteIdentityProvider deletes an identity provider.
|
||||
operationId: IdentityProviderService_DeleteIdentityProvider
|
||||
responses:
|
||||
"200":
|
||||
description: A successful response.
|
||||
|
|
@ -1263,14 +1263,14 @@ paths:
|
|||
parameters:
|
||||
- name: name_4
|
||||
description: |-
|
||||
Required. The resource name of the inbox to delete.
|
||||
Format: inboxes/{inbox}
|
||||
Required. The resource name of the identity provider to delete.
|
||||
Format: identityProviders/{idp}
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
pattern: inboxes/[^/]+
|
||||
pattern: identityProviders/[^/]+
|
||||
tags:
|
||||
- InboxService
|
||||
- IdentityProviderService
|
||||
/api/v1/{name_5}:
|
||||
get:
|
||||
summary: GetShortcut gets a shortcut by name.
|
||||
|
|
@ -1296,8 +1296,8 @@ paths:
|
|||
tags:
|
||||
- ShortcutService
|
||||
delete:
|
||||
summary: DeleteMemo deletes a memo.
|
||||
operationId: MemoService_DeleteMemo
|
||||
summary: DeleteInbox deletes an inbox.
|
||||
operationId: InboxService_DeleteInbox
|
||||
responses:
|
||||
"200":
|
||||
description: A successful response.
|
||||
|
|
@ -1311,19 +1311,14 @@ paths:
|
|||
parameters:
|
||||
- name: name_5
|
||||
description: |-
|
||||
Required. The resource name of the memo to delete.
|
||||
Format: memos/{memo}
|
||||
Required. The resource name of the inbox to delete.
|
||||
Format: inboxes/{inbox}
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
pattern: memos/[^/]+
|
||||
- name: force
|
||||
description: Optional. If set to true, the memo will be deleted even if it has associated data.
|
||||
in: query
|
||||
required: false
|
||||
type: boolean
|
||||
pattern: inboxes/[^/]+
|
||||
tags:
|
||||
- MemoService
|
||||
- InboxService
|
||||
/api/v1/{name_6}:
|
||||
get:
|
||||
summary: GetWebhook gets a webhook by name.
|
||||
|
|
@ -1356,8 +1351,8 @@ paths:
|
|||
tags:
|
||||
- WebhookService
|
||||
delete:
|
||||
summary: DeleteMemoReaction deletes a reaction for a memo.
|
||||
operationId: MemoService_DeleteMemoReaction
|
||||
summary: DeleteMemo deletes a memo.
|
||||
operationId: MemoService_DeleteMemo
|
||||
responses:
|
||||
"200":
|
||||
description: A successful response.
|
||||
|
|
@ -1371,12 +1366,17 @@ paths:
|
|||
parameters:
|
||||
- name: name_6
|
||||
description: |-
|
||||
Required. The resource name of the reaction to delete.
|
||||
Format: reactions/{reaction}
|
||||
Required. The resource name of the memo to delete.
|
||||
Format: memos/{memo}
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
pattern: reactions/[^/]+
|
||||
pattern: memos/[^/]+
|
||||
- name: force
|
||||
description: Optional. If set to true, the memo will be deleted even if it has associated data.
|
||||
in: query
|
||||
required: false
|
||||
type: boolean
|
||||
tags:
|
||||
- MemoService
|
||||
/api/v1/{name_7}:
|
||||
|
|
@ -1404,8 +1404,8 @@ paths:
|
|||
tags:
|
||||
- WorkspaceService
|
||||
delete:
|
||||
summary: DeleteShortcut deletes a shortcut for a user.
|
||||
operationId: ShortcutService_DeleteShortcut
|
||||
summary: DeleteMemoReaction deletes a reaction for a memo.
|
||||
operationId: MemoService_DeleteMemoReaction
|
||||
responses:
|
||||
"200":
|
||||
description: A successful response.
|
||||
|
|
@ -1418,6 +1418,31 @@ paths:
|
|||
$ref: '#/definitions/googlerpcStatus'
|
||||
parameters:
|
||||
- name: name_7
|
||||
description: |-
|
||||
Required. The resource name of the reaction to delete.
|
||||
Format: reactions/{reaction}
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
pattern: reactions/[^/]+
|
||||
tags:
|
||||
- MemoService
|
||||
/api/v1/{name_8}:
|
||||
delete:
|
||||
summary: DeleteShortcut deletes a shortcut for a user.
|
||||
operationId: ShortcutService_DeleteShortcut
|
||||
responses:
|
||||
"200":
|
||||
description: A successful response.
|
||||
schema:
|
||||
type: object
|
||||
properties: {}
|
||||
default:
|
||||
description: An unexpected error response.
|
||||
schema:
|
||||
$ref: '#/definitions/googlerpcStatus'
|
||||
parameters:
|
||||
- name: name_8
|
||||
description: |-
|
||||
Required. The resource name of the shortcut to delete.
|
||||
Format: users/{user}/shortcuts/{shortcut}
|
||||
|
|
@ -1427,7 +1452,7 @@ paths:
|
|||
pattern: users/[^/]+/shortcuts/[^/]+
|
||||
tags:
|
||||
- ShortcutService
|
||||
/api/v1/{name_8}:
|
||||
/api/v1/{name_9}:
|
||||
delete:
|
||||
summary: DeleteWebhook deletes a webhook.
|
||||
operationId: WebhookService_DeleteWebhook
|
||||
|
|
@ -1442,7 +1467,7 @@ paths:
|
|||
schema:
|
||||
$ref: '#/definitions/googlerpcStatus'
|
||||
parameters:
|
||||
- name: name_8
|
||||
- name: name_9
|
||||
description: |-
|
||||
Required. The resource name of the webhook to delete.
|
||||
Format: webhooks/{webhook}
|
||||
|
|
@ -2054,6 +2079,30 @@ paths:
|
|||
type: string
|
||||
tags:
|
||||
- MemoService
|
||||
/api/v1/{parent}/sessions:
|
||||
get:
|
||||
summary: ListUserSessions returns a list of active sessions for a user.
|
||||
operationId: UserService_ListUserSessions
|
||||
responses:
|
||||
"200":
|
||||
description: A successful response.
|
||||
schema:
|
||||
$ref: '#/definitions/v1ListUserSessionsResponse'
|
||||
default:
|
||||
description: An unexpected error response.
|
||||
schema:
|
||||
$ref: '#/definitions/googlerpcStatus'
|
||||
parameters:
|
||||
- name: parent
|
||||
description: |-
|
||||
Required. The resource name of the parent.
|
||||
Format: users/{user}
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
pattern: users/[^/]+
|
||||
tags:
|
||||
- UserService
|
||||
/api/v1/{parent}/shortcuts:
|
||||
get:
|
||||
summary: ListShortcuts returns a list of shortcuts for a user.
|
||||
|
|
@ -3676,6 +3725,15 @@ definitions:
|
|||
type: integer
|
||||
format: int32
|
||||
description: The total count of access tokens.
|
||||
v1ListUserSessionsResponse:
|
||||
type: object
|
||||
properties:
|
||||
sessions:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
$ref: '#/definitions/v1UserSession'
|
||||
description: The list of user sessions.
|
||||
v1ListUsersResponse:
|
||||
type: object
|
||||
properties:
|
||||
|
|
@ -4233,6 +4291,58 @@ definitions:
|
|||
format: date-time
|
||||
description: Optional. The expiration timestamp.
|
||||
title: User access token message
|
||||
v1UserSession:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
title: |-
|
||||
The resource name of the session.
|
||||
Format: users/{user}/sessions/{session}
|
||||
sessionId:
|
||||
type: string
|
||||
description: The session ID.
|
||||
readOnly: true
|
||||
createTime:
|
||||
type: string
|
||||
format: date-time
|
||||
description: The timestamp when the session was created.
|
||||
readOnly: true
|
||||
expireTime:
|
||||
type: string
|
||||
format: date-time
|
||||
description: The timestamp when the session expires.
|
||||
readOnly: true
|
||||
lastAccessedTime:
|
||||
type: string
|
||||
format: date-time
|
||||
description: The timestamp when the session was last accessed.
|
||||
readOnly: true
|
||||
clientInfo:
|
||||
$ref: '#/definitions/v1UserSessionClientInfo'
|
||||
description: Client information associated with this session.
|
||||
readOnly: true
|
||||
v1UserSessionClientInfo:
|
||||
type: object
|
||||
properties:
|
||||
userAgent:
|
||||
type: string
|
||||
description: User agent string of the client.
|
||||
ipAddress:
|
||||
type: string
|
||||
description: IP address of the client.
|
||||
deviceType:
|
||||
type: string
|
||||
description: Optional. Device type (e.g., "mobile", "desktop", "tablet").
|
||||
os:
|
||||
type: string
|
||||
description: Optional. Operating system (e.g., "iOS 17.0", "Windows 11").
|
||||
browser:
|
||||
type: string
|
||||
description: Optional. Browser name and version (e.g., "Chrome 119.0").
|
||||
country:
|
||||
type: string
|
||||
description: Optional. Geographic location (country code, e.g., "US").
|
||||
v1UserStats:
|
||||
type: object
|
||||
properties:
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import (
|
|||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/status"
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
"github.com/usememos/memos/internal/base"
|
||||
"github.com/usememos/memos/internal/util"
|
||||
|
|
@ -176,6 +177,13 @@ func (s *APIV1Service) doSignIn(ctx context.Context, user *store.User, expireTim
|
|||
return status.Errorf(codes.Internal, "failed to upsert access token to store, error: %v", err)
|
||||
}
|
||||
|
||||
// Track session in user settings
|
||||
if err := s.trackUserSession(ctx, user.ID, accessToken, expireTime); err != nil {
|
||||
// Log the error but don't fail the login if session tracking fails
|
||||
// This ensures backward compatibility
|
||||
// TODO: Add proper logging here
|
||||
}
|
||||
|
||||
cookie, err := s.buildAccessTokenCookie(ctx, accessToken, expireTime)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Internal, "failed to build access token cookie, error: %v", err)
|
||||
|
|
@ -313,3 +321,41 @@ func (s *APIV1Service) GetCurrentUser(ctx context.Context) (*store.User, error)
|
|||
}
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// Helper function to track user session for session management
|
||||
func (s *APIV1Service) trackUserSession(ctx context.Context, userID int32, sessionID string, expireTime time.Time) error {
|
||||
// Extract client information from the context
|
||||
clientInfo := s.extractClientInfo(ctx)
|
||||
|
||||
session := &storepb.SessionsUserSetting_Session{
|
||||
SessionId: sessionID,
|
||||
CreateTime: timestamppb.Now(),
|
||||
ExpireTime: timestamppb.New(expireTime),
|
||||
LastAccessedTime: timestamppb.Now(),
|
||||
ClientInfo: clientInfo,
|
||||
}
|
||||
|
||||
return s.Store.AddUserSession(ctx, userID, session)
|
||||
}
|
||||
|
||||
// Helper function to extract client information from the gRPC context
|
||||
func (s *APIV1Service) extractClientInfo(ctx context.Context) *storepb.SessionsUserSetting_ClientInfo {
|
||||
clientInfo := &storepb.SessionsUserSetting_ClientInfo{}
|
||||
|
||||
// Extract user agent from metadata if available
|
||||
if md, ok := metadata.FromIncomingContext(ctx); ok {
|
||||
if userAgents := md.Get("user-agent"); len(userAgents) > 0 {
|
||||
clientInfo.UserAgent = userAgents[0]
|
||||
}
|
||||
if forwardedFor := md.Get("x-forwarded-for"); len(forwardedFor) > 0 {
|
||||
clientInfo.IpAddress = forwardedFor[0]
|
||||
} else if realIP := md.Get("x-real-ip"); len(realIP) > 0 {
|
||||
clientInfo.IpAddress = realIP[0]
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Parse user agent to extract device type, OS, browser info
|
||||
// This could be done using a user agent parsing library
|
||||
|
||||
return clientInfo
|
||||
}
|
||||
|
|
|
|||
|
|
@ -588,6 +588,108 @@ func (s *APIV1Service) DeleteUserAccessToken(ctx context.Context, request *v1pb.
|
|||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (s *APIV1Service) ListUserSessions(ctx context.Context, request *v1pb.ListUserSessionsRequest) (*v1pb.ListUserSessionsResponse, error) {
|
||||
userID, err := ExtractUserIDFromName(request.Parent)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "invalid user name: %v", err)
|
||||
}
|
||||
|
||||
currentUser, err := s.GetCurrentUser(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed to get current user: %v", err)
|
||||
}
|
||||
if currentUser == nil {
|
||||
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
|
||||
}
|
||||
if currentUser.ID != userID {
|
||||
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
|
||||
}
|
||||
|
||||
userSessions, err := s.Store.GetUserSessions(ctx, userID)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed to list sessions: %v", err)
|
||||
}
|
||||
|
||||
sessions := []*v1pb.UserSession{}
|
||||
for _, userSession := range userSessions {
|
||||
sessionResponse := &v1pb.UserSession{
|
||||
Name: fmt.Sprintf("users/%d/sessions/%s", userID, userSession.SessionId),
|
||||
SessionId: userSession.SessionId,
|
||||
CreateTime: userSession.CreateTime,
|
||||
ExpireTime: userSession.ExpireTime,
|
||||
LastAccessedTime: userSession.LastAccessedTime,
|
||||
}
|
||||
|
||||
if userSession.ClientInfo != nil {
|
||||
sessionResponse.ClientInfo = &v1pb.UserSession_ClientInfo{
|
||||
UserAgent: userSession.ClientInfo.UserAgent,
|
||||
IpAddress: userSession.ClientInfo.IpAddress,
|
||||
DeviceType: userSession.ClientInfo.DeviceType,
|
||||
Os: userSession.ClientInfo.Os,
|
||||
Browser: userSession.ClientInfo.Browser,
|
||||
Country: userSession.ClientInfo.Country,
|
||||
}
|
||||
}
|
||||
|
||||
sessions = append(sessions, sessionResponse)
|
||||
}
|
||||
|
||||
// Sort by last accessed time in descending order.
|
||||
slices.SortFunc(sessions, func(i, j *v1pb.UserSession) int {
|
||||
return int(j.LastAccessedTime.Seconds - i.LastAccessedTime.Seconds)
|
||||
})
|
||||
|
||||
response := &v1pb.ListUserSessionsResponse{
|
||||
Sessions: sessions,
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (s *APIV1Service) RevokeUserSession(ctx context.Context, request *v1pb.RevokeUserSessionRequest) (*emptypb.Empty, error) {
|
||||
// Extract user ID and session ID from the session resource name
|
||||
// Format: users/{user}/sessions/{session}
|
||||
parts := strings.Split(request.Name, "/")
|
||||
if len(parts) != 4 || parts[0] != "users" || parts[2] != "sessions" {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "invalid session name format: %s", request.Name)
|
||||
}
|
||||
|
||||
userID, err := ExtractUserIDFromName(fmt.Sprintf("users/%s", parts[1]))
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "invalid user name: %v", err)
|
||||
}
|
||||
sessionIDToRevoke := parts[3]
|
||||
|
||||
currentUser, err := s.GetCurrentUser(ctx)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed to get current user: %v", err)
|
||||
}
|
||||
if currentUser == nil {
|
||||
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
|
||||
}
|
||||
if currentUser.ID != userID {
|
||||
return nil, status.Errorf(codes.PermissionDenied, "permission denied")
|
||||
}
|
||||
|
||||
if err := s.Store.RemoveUserSession(ctx, userID, sessionIDToRevoke); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed to revoke session: %v", err)
|
||||
}
|
||||
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
// Helper function to add or update a user session
|
||||
func (s *APIV1Service) UpsertUserSession(ctx context.Context, userID int32, sessionID string, clientInfo *storepb.SessionsUserSetting_ClientInfo) error {
|
||||
session := &storepb.SessionsUserSetting_Session{
|
||||
SessionId: sessionID,
|
||||
CreateTime: timestamppb.Now(),
|
||||
ExpireTime: timestamppb.New(time.Now().Add(30 * 24 * time.Hour)), // 30 days default
|
||||
LastAccessedTime: timestamppb.Now(),
|
||||
ClientInfo: clientInfo,
|
||||
}
|
||||
|
||||
return s.Store.AddUserSession(ctx, userID, session)
|
||||
}
|
||||
|
||||
func (s *APIV1Service) UpsertAccessTokenToStore(ctx context.Context, user *store.User, accessToken, description string) error {
|
||||
userAccessTokens, err := s.Store.GetUserAccessTokens(ctx, user.ID)
|
||||
if err != nil {
|
||||
|
|
@ -598,6 +700,7 @@ func (s *APIV1Service) UpsertAccessTokenToStore(ctx context.Context, user *store
|
|||
Description: description,
|
||||
}
|
||||
userAccessTokens = append(userAccessTokens, &userAccessToken)
|
||||
|
||||
if _, err := s.Store.UpsertUserSetting(ctx, &storepb.UserSetting{
|
||||
UserId: user.ID,
|
||||
Key: storepb.UserSettingKey_ACCESS_TOKENS,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/pkg/errors"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
|
||||
storepb "github.com/usememos/memos/proto/gen/store"
|
||||
)
|
||||
|
|
@ -132,6 +133,114 @@ func (s *Store) RemoveUserAccessToken(ctx context.Context, userID int32, token s
|
|||
return err
|
||||
}
|
||||
|
||||
// GetUserSessions returns the sessions of the user.
|
||||
func (s *Store) GetUserSessions(ctx context.Context, userID int32) ([]*storepb.SessionsUserSetting_Session, error) {
|
||||
userSetting, err := s.GetUserSetting(ctx, &FindUserSetting{
|
||||
UserID: &userID,
|
||||
Key: storepb.UserSettingKey_SESSIONS,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if userSetting == nil {
|
||||
return []*storepb.SessionsUserSetting_Session{}, nil
|
||||
}
|
||||
|
||||
sessionsUserSetting := userSetting.GetSessions()
|
||||
return sessionsUserSetting.Sessions, nil
|
||||
}
|
||||
|
||||
// RemoveUserSession removes the session of the user.
|
||||
func (s *Store) RemoveUserSession(ctx context.Context, userID int32, sessionID string) error {
|
||||
oldSessions, err := s.GetUserSessions(ctx, userID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newSessions := make([]*storepb.SessionsUserSetting_Session, 0, len(oldSessions))
|
||||
for _, session := range oldSessions {
|
||||
if sessionID != session.SessionId {
|
||||
newSessions = append(newSessions, session)
|
||||
}
|
||||
}
|
||||
|
||||
_, err = s.UpsertUserSetting(ctx, &storepb.UserSetting{
|
||||
UserId: userID,
|
||||
Key: storepb.UserSettingKey_SESSIONS,
|
||||
Value: &storepb.UserSetting_Sessions{
|
||||
Sessions: &storepb.SessionsUserSetting{
|
||||
Sessions: newSessions,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// AddUserSession adds a new session for the user.
|
||||
func (s *Store) AddUserSession(ctx context.Context, userID int32, session *storepb.SessionsUserSetting_Session) error {
|
||||
existingSessions, err := s.GetUserSessions(ctx, userID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check if session already exists, update if it does
|
||||
var updatedSessions []*storepb.SessionsUserSetting_Session
|
||||
sessionExists := false
|
||||
for _, existing := range existingSessions {
|
||||
if existing.SessionId == session.SessionId {
|
||||
updatedSessions = append(updatedSessions, session)
|
||||
sessionExists = true
|
||||
} else {
|
||||
updatedSessions = append(updatedSessions, existing)
|
||||
}
|
||||
}
|
||||
|
||||
// If session doesn't exist, add it
|
||||
if !sessionExists {
|
||||
updatedSessions = append(updatedSessions, session)
|
||||
}
|
||||
|
||||
_, err = s.UpsertUserSetting(ctx, &storepb.UserSetting{
|
||||
UserId: userID,
|
||||
Key: storepb.UserSettingKey_SESSIONS,
|
||||
Value: &storepb.UserSetting_Sessions{
|
||||
Sessions: &storepb.SessionsUserSetting{
|
||||
Sessions: updatedSessions,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateUserSessionLastAccessed updates the last accessed time of a session.
|
||||
func (s *Store) UpdateUserSessionLastAccessed(ctx context.Context, userID int32, sessionID string, lastAccessedTime *timestamppb.Timestamp) error {
|
||||
sessions, err := s.GetUserSessions(ctx, userID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, session := range sessions {
|
||||
if session.SessionId == sessionID {
|
||||
session.LastAccessedTime = lastAccessedTime
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
_, err = s.UpsertUserSetting(ctx, &storepb.UserSetting{
|
||||
UserId: userID,
|
||||
Key: storepb.UserSettingKey_SESSIONS,
|
||||
Value: &storepb.UserSetting_Sessions{
|
||||
Sessions: &storepb.SessionsUserSetting{
|
||||
Sessions: sessions,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func convertUserSettingFromRaw(raw *UserSetting) (*storepb.UserSetting, error) {
|
||||
userSetting := &storepb.UserSetting{
|
||||
UserId: raw.UserID,
|
||||
|
|
@ -145,6 +254,12 @@ func convertUserSettingFromRaw(raw *UserSetting) (*storepb.UserSetting, error) {
|
|||
return nil, err
|
||||
}
|
||||
userSetting.Value = &storepb.UserSetting_AccessTokens{AccessTokens: accessTokensUserSetting}
|
||||
case storepb.UserSettingKey_SESSIONS:
|
||||
sessionsUserSetting := &storepb.SessionsUserSetting{}
|
||||
if err := protojsonUnmarshaler.Unmarshal([]byte(raw.Value), sessionsUserSetting); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
userSetting.Value = &storepb.UserSetting_Sessions{Sessions: sessionsUserSetting}
|
||||
case storepb.UserSettingKey_SHORTCUTS:
|
||||
shortcutsUserSetting := &storepb.ShortcutsUserSetting{}
|
||||
if err := protojsonUnmarshaler.Unmarshal([]byte(raw.Value), shortcutsUserSetting); err != nil {
|
||||
|
|
@ -177,6 +292,13 @@ func convertUserSettingToRaw(userSetting *storepb.UserSetting) (*UserSetting, er
|
|||
return nil, err
|
||||
}
|
||||
raw.Value = string(value)
|
||||
case storepb.UserSettingKey_SESSIONS:
|
||||
sessionsUserSetting := userSetting.GetSessions()
|
||||
value, err := protojson.Marshal(sessionsUserSetting)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
raw.Value = string(value)
|
||||
case storepb.UserSettingKey_SHORTCUTS:
|
||||
shortcutsUserSetting := userSetting.GetShortcuts()
|
||||
value, err := protojson.Marshal(shortcutsUserSetting)
|
||||
|
|
|
|||
|
|
@ -359,6 +359,66 @@ export interface DeleteUserAccessTokenRequest {
|
|||
name: string;
|
||||
}
|
||||
|
||||
export interface UserSession {
|
||||
/**
|
||||
* The resource name of the session.
|
||||
* Format: users/{user}/sessions/{session}
|
||||
*/
|
||||
name: string;
|
||||
/** The session ID. */
|
||||
sessionId: string;
|
||||
/** The timestamp when the session was created. */
|
||||
createTime?:
|
||||
| Date
|
||||
| undefined;
|
||||
/** The timestamp when the session expires. */
|
||||
expireTime?:
|
||||
| Date
|
||||
| undefined;
|
||||
/** The timestamp when the session was last accessed. */
|
||||
lastAccessedTime?:
|
||||
| Date
|
||||
| undefined;
|
||||
/** Client information associated with this session. */
|
||||
clientInfo?: UserSession_ClientInfo | undefined;
|
||||
}
|
||||
|
||||
export interface UserSession_ClientInfo {
|
||||
/** User agent string of the client. */
|
||||
userAgent: string;
|
||||
/** IP address of the client. */
|
||||
ipAddress: string;
|
||||
/** Optional. Device type (e.g., "mobile", "desktop", "tablet"). */
|
||||
deviceType: string;
|
||||
/** Optional. Operating system (e.g., "iOS 17.0", "Windows 11"). */
|
||||
os: string;
|
||||
/** Optional. Browser name and version (e.g., "Chrome 119.0"). */
|
||||
browser: string;
|
||||
/** Optional. Geographic location (country code, e.g., "US"). */
|
||||
country: string;
|
||||
}
|
||||
|
||||
export interface ListUserSessionsRequest {
|
||||
/**
|
||||
* Required. The resource name of the parent.
|
||||
* Format: users/{user}
|
||||
*/
|
||||
parent: string;
|
||||
}
|
||||
|
||||
export interface ListUserSessionsResponse {
|
||||
/** The list of user sessions. */
|
||||
sessions: UserSession[];
|
||||
}
|
||||
|
||||
export interface RevokeUserSessionRequest {
|
||||
/**
|
||||
* Required. The resource name of the session to revoke.
|
||||
* Format: users/{user}/sessions/{session}
|
||||
*/
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface ListAllUserStatsRequest {
|
||||
/** Optional. The maximum number of user stats to return. */
|
||||
pageSize: number;
|
||||
|
|
@ -2046,6 +2106,365 @@ export const DeleteUserAccessTokenRequest: MessageFns<DeleteUserAccessTokenReque
|
|||
},
|
||||
};
|
||||
|
||||
function createBaseUserSession(): UserSession {
|
||||
return {
|
||||
name: "",
|
||||
sessionId: "",
|
||||
createTime: undefined,
|
||||
expireTime: undefined,
|
||||
lastAccessedTime: undefined,
|
||||
clientInfo: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export const UserSession: MessageFns<UserSession> = {
|
||||
encode(message: UserSession, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||
if (message.name !== "") {
|
||||
writer.uint32(10).string(message.name);
|
||||
}
|
||||
if (message.sessionId !== "") {
|
||||
writer.uint32(18).string(message.sessionId);
|
||||
}
|
||||
if (message.createTime !== undefined) {
|
||||
Timestamp.encode(toTimestamp(message.createTime), writer.uint32(26).fork()).join();
|
||||
}
|
||||
if (message.expireTime !== undefined) {
|
||||
Timestamp.encode(toTimestamp(message.expireTime), writer.uint32(34).fork()).join();
|
||||
}
|
||||
if (message.lastAccessedTime !== undefined) {
|
||||
Timestamp.encode(toTimestamp(message.lastAccessedTime), writer.uint32(42).fork()).join();
|
||||
}
|
||||
if (message.clientInfo !== undefined) {
|
||||
UserSession_ClientInfo.encode(message.clientInfo, writer.uint32(50).fork()).join();
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
|
||||
decode(input: BinaryReader | Uint8Array, length?: number): UserSession {
|
||||
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
||||
let end = length === undefined ? reader.len : reader.pos + length;
|
||||
const message = createBaseUserSession();
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32();
|
||||
switch (tag >>> 3) {
|
||||
case 1: {
|
||||
if (tag !== 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.name = reader.string();
|
||||
continue;
|
||||
}
|
||||
case 2: {
|
||||
if (tag !== 18) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.sessionId = reader.string();
|
||||
continue;
|
||||
}
|
||||
case 3: {
|
||||
if (tag !== 26) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.createTime = fromTimestamp(Timestamp.decode(reader, reader.uint32()));
|
||||
continue;
|
||||
}
|
||||
case 4: {
|
||||
if (tag !== 34) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.expireTime = fromTimestamp(Timestamp.decode(reader, reader.uint32()));
|
||||
continue;
|
||||
}
|
||||
case 5: {
|
||||
if (tag !== 42) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.lastAccessedTime = fromTimestamp(Timestamp.decode(reader, reader.uint32()));
|
||||
continue;
|
||||
}
|
||||
case 6: {
|
||||
if (tag !== 50) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.clientInfo = UserSession_ClientInfo.decode(reader, reader.uint32());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
}
|
||||
reader.skip(tag & 7);
|
||||
}
|
||||
return message;
|
||||
},
|
||||
|
||||
create(base?: DeepPartial<UserSession>): UserSession {
|
||||
return UserSession.fromPartial(base ?? {});
|
||||
},
|
||||
fromPartial(object: DeepPartial<UserSession>): UserSession {
|
||||
const message = createBaseUserSession();
|
||||
message.name = object.name ?? "";
|
||||
message.sessionId = object.sessionId ?? "";
|
||||
message.createTime = object.createTime ?? undefined;
|
||||
message.expireTime = object.expireTime ?? undefined;
|
||||
message.lastAccessedTime = object.lastAccessedTime ?? undefined;
|
||||
message.clientInfo = (object.clientInfo !== undefined && object.clientInfo !== null)
|
||||
? UserSession_ClientInfo.fromPartial(object.clientInfo)
|
||||
: undefined;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
function createBaseUserSession_ClientInfo(): UserSession_ClientInfo {
|
||||
return { userAgent: "", ipAddress: "", deviceType: "", os: "", browser: "", country: "" };
|
||||
}
|
||||
|
||||
export const UserSession_ClientInfo: MessageFns<UserSession_ClientInfo> = {
|
||||
encode(message: UserSession_ClientInfo, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||
if (message.userAgent !== "") {
|
||||
writer.uint32(10).string(message.userAgent);
|
||||
}
|
||||
if (message.ipAddress !== "") {
|
||||
writer.uint32(18).string(message.ipAddress);
|
||||
}
|
||||
if (message.deviceType !== "") {
|
||||
writer.uint32(26).string(message.deviceType);
|
||||
}
|
||||
if (message.os !== "") {
|
||||
writer.uint32(34).string(message.os);
|
||||
}
|
||||
if (message.browser !== "") {
|
||||
writer.uint32(42).string(message.browser);
|
||||
}
|
||||
if (message.country !== "") {
|
||||
writer.uint32(50).string(message.country);
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
|
||||
decode(input: BinaryReader | Uint8Array, length?: number): UserSession_ClientInfo {
|
||||
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
||||
let end = length === undefined ? reader.len : reader.pos + length;
|
||||
const message = createBaseUserSession_ClientInfo();
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32();
|
||||
switch (tag >>> 3) {
|
||||
case 1: {
|
||||
if (tag !== 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.userAgent = reader.string();
|
||||
continue;
|
||||
}
|
||||
case 2: {
|
||||
if (tag !== 18) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.ipAddress = reader.string();
|
||||
continue;
|
||||
}
|
||||
case 3: {
|
||||
if (tag !== 26) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.deviceType = reader.string();
|
||||
continue;
|
||||
}
|
||||
case 4: {
|
||||
if (tag !== 34) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.os = reader.string();
|
||||
continue;
|
||||
}
|
||||
case 5: {
|
||||
if (tag !== 42) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.browser = reader.string();
|
||||
continue;
|
||||
}
|
||||
case 6: {
|
||||
if (tag !== 50) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.country = reader.string();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
}
|
||||
reader.skip(tag & 7);
|
||||
}
|
||||
return message;
|
||||
},
|
||||
|
||||
create(base?: DeepPartial<UserSession_ClientInfo>): UserSession_ClientInfo {
|
||||
return UserSession_ClientInfo.fromPartial(base ?? {});
|
||||
},
|
||||
fromPartial(object: DeepPartial<UserSession_ClientInfo>): UserSession_ClientInfo {
|
||||
const message = createBaseUserSession_ClientInfo();
|
||||
message.userAgent = object.userAgent ?? "";
|
||||
message.ipAddress = object.ipAddress ?? "";
|
||||
message.deviceType = object.deviceType ?? "";
|
||||
message.os = object.os ?? "";
|
||||
message.browser = object.browser ?? "";
|
||||
message.country = object.country ?? "";
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
function createBaseListUserSessionsRequest(): ListUserSessionsRequest {
|
||||
return { parent: "" };
|
||||
}
|
||||
|
||||
export const ListUserSessionsRequest: MessageFns<ListUserSessionsRequest> = {
|
||||
encode(message: ListUserSessionsRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||
if (message.parent !== "") {
|
||||
writer.uint32(10).string(message.parent);
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
|
||||
decode(input: BinaryReader | Uint8Array, length?: number): ListUserSessionsRequest {
|
||||
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
||||
let end = length === undefined ? reader.len : reader.pos + length;
|
||||
const message = createBaseListUserSessionsRequest();
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32();
|
||||
switch (tag >>> 3) {
|
||||
case 1: {
|
||||
if (tag !== 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.parent = reader.string();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
}
|
||||
reader.skip(tag & 7);
|
||||
}
|
||||
return message;
|
||||
},
|
||||
|
||||
create(base?: DeepPartial<ListUserSessionsRequest>): ListUserSessionsRequest {
|
||||
return ListUserSessionsRequest.fromPartial(base ?? {});
|
||||
},
|
||||
fromPartial(object: DeepPartial<ListUserSessionsRequest>): ListUserSessionsRequest {
|
||||
const message = createBaseListUserSessionsRequest();
|
||||
message.parent = object.parent ?? "";
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
function createBaseListUserSessionsResponse(): ListUserSessionsResponse {
|
||||
return { sessions: [] };
|
||||
}
|
||||
|
||||
export const ListUserSessionsResponse: MessageFns<ListUserSessionsResponse> = {
|
||||
encode(message: ListUserSessionsResponse, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||
for (const v of message.sessions) {
|
||||
UserSession.encode(v!, writer.uint32(10).fork()).join();
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
|
||||
decode(input: BinaryReader | Uint8Array, length?: number): ListUserSessionsResponse {
|
||||
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
||||
let end = length === undefined ? reader.len : reader.pos + length;
|
||||
const message = createBaseListUserSessionsResponse();
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32();
|
||||
switch (tag >>> 3) {
|
||||
case 1: {
|
||||
if (tag !== 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.sessions.push(UserSession.decode(reader, reader.uint32()));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
}
|
||||
reader.skip(tag & 7);
|
||||
}
|
||||
return message;
|
||||
},
|
||||
|
||||
create(base?: DeepPartial<ListUserSessionsResponse>): ListUserSessionsResponse {
|
||||
return ListUserSessionsResponse.fromPartial(base ?? {});
|
||||
},
|
||||
fromPartial(object: DeepPartial<ListUserSessionsResponse>): ListUserSessionsResponse {
|
||||
const message = createBaseListUserSessionsResponse();
|
||||
message.sessions = object.sessions?.map((e) => UserSession.fromPartial(e)) || [];
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
function createBaseRevokeUserSessionRequest(): RevokeUserSessionRequest {
|
||||
return { name: "" };
|
||||
}
|
||||
|
||||
export const RevokeUserSessionRequest: MessageFns<RevokeUserSessionRequest> = {
|
||||
encode(message: RevokeUserSessionRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||
if (message.name !== "") {
|
||||
writer.uint32(10).string(message.name);
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
|
||||
decode(input: BinaryReader | Uint8Array, length?: number): RevokeUserSessionRequest {
|
||||
const reader = input instanceof BinaryReader ? input : new BinaryReader(input);
|
||||
let end = length === undefined ? reader.len : reader.pos + length;
|
||||
const message = createBaseRevokeUserSessionRequest();
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32();
|
||||
switch (tag >>> 3) {
|
||||
case 1: {
|
||||
if (tag !== 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.name = reader.string();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
}
|
||||
reader.skip(tag & 7);
|
||||
}
|
||||
return message;
|
||||
},
|
||||
|
||||
create(base?: DeepPartial<RevokeUserSessionRequest>): RevokeUserSessionRequest {
|
||||
return RevokeUserSessionRequest.fromPartial(base ?? {});
|
||||
},
|
||||
fromPartial(object: DeepPartial<RevokeUserSessionRequest>): RevokeUserSessionRequest {
|
||||
const message = createBaseRevokeUserSessionRequest();
|
||||
message.name = object.name ?? "";
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
function createBaseListAllUserStatsRequest(): ListAllUserStatsRequest {
|
||||
return { pageSize: 0, pageToken: "" };
|
||||
}
|
||||
|
|
@ -2903,6 +3322,112 @@ export const UserServiceDefinition = {
|
|||
},
|
||||
},
|
||||
},
|
||||
/** ListUserSessions returns a list of active sessions for a user. */
|
||||
listUserSessions: {
|
||||
name: "ListUserSessions",
|
||||
requestType: ListUserSessionsRequest,
|
||||
requestStream: false,
|
||||
responseType: ListUserSessionsResponse,
|
||||
responseStream: false,
|
||||
options: {
|
||||
_unknownFields: {
|
||||
8410: [new Uint8Array([6, 112, 97, 114, 101, 110, 116])],
|
||||
578365826: [
|
||||
new Uint8Array([
|
||||
35,
|
||||
18,
|
||||
33,
|
||||
47,
|
||||
97,
|
||||
112,
|
||||
105,
|
||||
47,
|
||||
118,
|
||||
49,
|
||||
47,
|
||||
123,
|
||||
112,
|
||||
97,
|
||||
114,
|
||||
101,
|
||||
110,
|
||||
116,
|
||||
61,
|
||||
117,
|
||||
115,
|
||||
101,
|
||||
114,
|
||||
115,
|
||||
47,
|
||||
42,
|
||||
125,
|
||||
47,
|
||||
115,
|
||||
101,
|
||||
115,
|
||||
115,
|
||||
105,
|
||||
111,
|
||||
110,
|
||||
115,
|
||||
]),
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
/** RevokeUserSession revokes a specific session for a user. */
|
||||
revokeUserSession: {
|
||||
name: "RevokeUserSession",
|
||||
requestType: RevokeUserSessionRequest,
|
||||
requestStream: false,
|
||||
responseType: Empty,
|
||||
responseStream: false,
|
||||
options: {
|
||||
_unknownFields: {
|
||||
8410: [new Uint8Array([4, 110, 97, 109, 101])],
|
||||
578365826: [
|
||||
new Uint8Array([
|
||||
35,
|
||||
42,
|
||||
33,
|
||||
47,
|
||||
97,
|
||||
112,
|
||||
105,
|
||||
47,
|
||||
118,
|
||||
49,
|
||||
47,
|
||||
123,
|
||||
110,
|
||||
97,
|
||||
109,
|
||||
101,
|
||||
61,
|
||||
117,
|
||||
115,
|
||||
101,
|
||||
114,
|
||||
115,
|
||||
47,
|
||||
42,
|
||||
47,
|
||||
115,
|
||||
101,
|
||||
115,
|
||||
115,
|
||||
105,
|
||||
111,
|
||||
110,
|
||||
115,
|
||||
47,
|
||||
42,
|
||||
125,
|
||||
]),
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue