mirror of
https://github.com/usememos/memos.git
synced 2025-10-18 10:16:00 +08:00
feat: sliding expiration for user sessions
This commit is contained in:
parent
e93d695aa8
commit
1fffc41f79
17 changed files with 204 additions and 367 deletions
|
@ -38,8 +38,9 @@ message GetCurrentSessionRequest {}
|
|||
message GetCurrentSessionResponse {
|
||||
User user = 1;
|
||||
|
||||
// Current session expiration time (if available).
|
||||
google.protobuf.Timestamp expires_at = 2;
|
||||
// Last time the session was accessed.
|
||||
// Used for sliding expiration calculation (last_accessed_time + 2 weeks).
|
||||
google.protobuf.Timestamp last_accessed_at = 2;
|
||||
}
|
||||
|
||||
message CreateSessionRequest {
|
||||
|
@ -78,18 +79,15 @@ message CreateSessionRequest {
|
|||
// SSO provider authentication method.
|
||||
SSOCredentials sso_credentials = 2;
|
||||
}
|
||||
|
||||
// Whether the session should never expire.
|
||||
// Optional field that defaults to false for security.
|
||||
bool never_expire = 3 [(google.api.field_behavior) = OPTIONAL];
|
||||
}
|
||||
|
||||
message CreateSessionResponse {
|
||||
// The authenticated user information.
|
||||
User user = 1;
|
||||
|
||||
// Token expiration time.
|
||||
google.protobuf.Timestamp expires_at = 2;
|
||||
// Last time the session was accessed.
|
||||
// Used for sliding expiration calculation (last_accessed_time + 2 weeks).
|
||||
google.protobuf.Timestamp last_accessed_at = 2;
|
||||
}
|
||||
|
||||
message DeleteSessionRequest {}
|
||||
|
|
|
@ -481,14 +481,12 @@ message UserSession {
|
|||
// 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];
|
||||
// Used for sliding expiration calculation (last_accessed_time + 2 weeks).
|
||||
google.protobuf.Timestamp last_accessed_time = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
|
||||
// Client information associated with this session.
|
||||
ClientInfo client_info = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
ClientInfo client_info = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
|
||||
|
||||
message ClientInfo {
|
||||
// User agent string of the client.
|
||||
|
|
|
@ -63,10 +63,11 @@ func (*GetCurrentSessionRequest) Descriptor() ([]byte, []int) {
|
|||
type GetCurrentSessionResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
|
||||
// Current session expiration time (if available).
|
||||
ExpiresAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=expires_at,json=expiresAt,proto3" json:"expires_at,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
// Last time the session was accessed.
|
||||
// Used for sliding expiration calculation (last_accessed_time + 2 weeks).
|
||||
LastAccessedAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=last_accessed_at,json=lastAccessedAt,proto3" json:"last_accessed_at,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetCurrentSessionResponse) Reset() {
|
||||
|
@ -106,9 +107,9 @@ func (x *GetCurrentSessionResponse) GetUser() *User {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (x *GetCurrentSessionResponse) GetExpiresAt() *timestamppb.Timestamp {
|
||||
func (x *GetCurrentSessionResponse) GetLastAccessedAt() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.ExpiresAt
|
||||
return x.LastAccessedAt
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -122,10 +123,7 @@ type CreateSessionRequest struct {
|
|||
//
|
||||
// *CreateSessionRequest_PasswordCredentials_
|
||||
// *CreateSessionRequest_SsoCredentials
|
||||
Credentials isCreateSessionRequest_Credentials `protobuf_oneof:"credentials"`
|
||||
// Whether the session should never expire.
|
||||
// Optional field that defaults to false for security.
|
||||
NeverExpire bool `protobuf:"varint,3,opt,name=never_expire,json=neverExpire,proto3" json:"never_expire,omitempty"`
|
||||
Credentials isCreateSessionRequest_Credentials `protobuf_oneof:"credentials"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
@ -185,13 +183,6 @@ func (x *CreateSessionRequest) GetSsoCredentials() *CreateSessionRequest_SSOCred
|
|||
return nil
|
||||
}
|
||||
|
||||
func (x *CreateSessionRequest) GetNeverExpire() bool {
|
||||
if x != nil {
|
||||
return x.NeverExpire
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
type isCreateSessionRequest_Credentials interface {
|
||||
isCreateSessionRequest_Credentials()
|
||||
}
|
||||
|
@ -214,10 +205,11 @@ type CreateSessionResponse struct {
|
|||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// The authenticated user information.
|
||||
User *User `protobuf:"bytes,1,opt,name=user,proto3" json:"user,omitempty"`
|
||||
// Token expiration time.
|
||||
ExpiresAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=expires_at,json=expiresAt,proto3" json:"expires_at,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
// Last time the session was accessed.
|
||||
// Used for sliding expiration calculation (last_accessed_time + 2 weeks).
|
||||
LastAccessedAt *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=last_accessed_at,json=lastAccessedAt,proto3" json:"last_accessed_at,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *CreateSessionResponse) Reset() {
|
||||
|
@ -257,9 +249,9 @@ func (x *CreateSessionResponse) GetUser() *User {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (x *CreateSessionResponse) GetExpiresAt() *timestamppb.Timestamp {
|
||||
func (x *CreateSessionResponse) GetLastAccessedAt() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.ExpiresAt
|
||||
return x.LastAccessedAt
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -429,15 +421,13 @@ var File_api_v1_auth_service_proto protoreflect.FileDescriptor
|
|||
const file_api_v1_auth_service_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\x19api/v1/auth_service.proto\x12\fmemos.api.v1\x1a\x19api/v1/user_service.proto\x1a\x1cgoogle/api/annotations.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\x1a\n" +
|
||||
"\x18GetCurrentSessionRequest\"~\n" +
|
||||
"\x18GetCurrentSessionRequest\"\x89\x01\n" +
|
||||
"\x19GetCurrentSessionResponse\x12&\n" +
|
||||
"\x04user\x18\x01 \x01(\v2\x12.memos.api.v1.UserR\x04user\x129\n" +
|
||||
"\n" +
|
||||
"expires_at\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\texpiresAt\"\xe0\x03\n" +
|
||||
"\x04user\x18\x01 \x01(\v2\x12.memos.api.v1.UserR\x04user\x12D\n" +
|
||||
"\x10last_accessed_at\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\x0elastAccessedAt\"\xb8\x03\n" +
|
||||
"\x14CreateSessionRequest\x12k\n" +
|
||||
"\x14password_credentials\x18\x01 \x01(\v26.memos.api.v1.CreateSessionRequest.PasswordCredentialsH\x00R\x13passwordCredentials\x12\\\n" +
|
||||
"\x0fsso_credentials\x18\x02 \x01(\v21.memos.api.v1.CreateSessionRequest.SSOCredentialsH\x00R\x0essoCredentials\x12&\n" +
|
||||
"\fnever_expire\x18\x03 \x01(\bB\x03\xe0A\x01R\vneverExpire\x1aW\n" +
|
||||
"\x0fsso_credentials\x18\x02 \x01(\v21.memos.api.v1.CreateSessionRequest.SSOCredentialsH\x00R\x0essoCredentials\x1aW\n" +
|
||||
"\x13PasswordCredentials\x12\x1f\n" +
|
||||
"\busername\x18\x01 \x01(\tB\x03\xe0A\x02R\busername\x12\x1f\n" +
|
||||
"\bpassword\x18\x02 \x01(\tB\x03\xe0A\x02R\bpassword\x1am\n" +
|
||||
|
@ -445,11 +435,10 @@ const file_api_v1_auth_service_proto_rawDesc = "" +
|
|||
"\x06idp_id\x18\x01 \x01(\x05B\x03\xe0A\x02R\x05idpId\x12\x17\n" +
|
||||
"\x04code\x18\x02 \x01(\tB\x03\xe0A\x02R\x04code\x12&\n" +
|
||||
"\fredirect_uri\x18\x03 \x01(\tB\x03\xe0A\x02R\vredirectUriB\r\n" +
|
||||
"\vcredentials\"z\n" +
|
||||
"\vcredentials\"\x85\x01\n" +
|
||||
"\x15CreateSessionResponse\x12&\n" +
|
||||
"\x04user\x18\x01 \x01(\v2\x12.memos.api.v1.UserR\x04user\x129\n" +
|
||||
"\n" +
|
||||
"expires_at\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\texpiresAt\"\x16\n" +
|
||||
"\x04user\x18\x01 \x01(\v2\x12.memos.api.v1.UserR\x04user\x12D\n" +
|
||||
"\x10last_accessed_at\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\x0elastAccessedAt\"\x16\n" +
|
||||
"\x14DeleteSessionRequest2\x8b\x03\n" +
|
||||
"\vAuthService\x12\x8b\x01\n" +
|
||||
"\x11GetCurrentSession\x12&.memos.api.v1.GetCurrentSessionRequest\x1a'.memos.api.v1.GetCurrentSessionResponse\"%\x82\xd3\xe4\x93\x02\x1f\x12\x1d/api/v1/auth/sessions/current\x12z\n" +
|
||||
|
@ -484,11 +473,11 @@ var file_api_v1_auth_service_proto_goTypes = []any{
|
|||
}
|
||||
var file_api_v1_auth_service_proto_depIdxs = []int32{
|
||||
7, // 0: memos.api.v1.GetCurrentSessionResponse.user:type_name -> memos.api.v1.User
|
||||
8, // 1: memos.api.v1.GetCurrentSessionResponse.expires_at:type_name -> google.protobuf.Timestamp
|
||||
8, // 1: memos.api.v1.GetCurrentSessionResponse.last_accessed_at:type_name -> google.protobuf.Timestamp
|
||||
5, // 2: memos.api.v1.CreateSessionRequest.password_credentials:type_name -> memos.api.v1.CreateSessionRequest.PasswordCredentials
|
||||
6, // 3: memos.api.v1.CreateSessionRequest.sso_credentials:type_name -> memos.api.v1.CreateSessionRequest.SSOCredentials
|
||||
7, // 4: memos.api.v1.CreateSessionResponse.user:type_name -> memos.api.v1.User
|
||||
8, // 5: memos.api.v1.CreateSessionResponse.expires_at:type_name -> google.protobuf.Timestamp
|
||||
8, // 5: memos.api.v1.CreateSessionResponse.last_accessed_at:type_name -> google.protobuf.Timestamp
|
||||
0, // 6: memos.api.v1.AuthService.GetCurrentSession:input_type -> memos.api.v1.GetCurrentSessionRequest
|
||||
2, // 7: memos.api.v1.AuthService.CreateSession:input_type -> memos.api.v1.CreateSessionRequest
|
||||
4, // 8: memos.api.v1.AuthService.DeleteSession:input_type -> memos.api.v1.DeleteSessionRequest
|
||||
|
|
|
@ -1434,12 +1434,11 @@ type UserSession struct {
|
|||
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"`
|
||||
// Used for sliding expiration calculation (last_accessed_time + 2 weeks).
|
||||
LastAccessedTime *timestamppb.Timestamp `protobuf:"bytes,4,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"`
|
||||
ClientInfo *UserSession_ClientInfo `protobuf:"bytes,5,opt,name=client_info,json=clientInfo,proto3" json:"client_info,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
@ -1495,13 +1494,6 @@ func (x *UserSession) GetCreateTime() *timestamppb.Timestamp {
|
|||
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
|
||||
|
@ -2055,17 +2047,15 @@ 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\"\xd6\x04\n" +
|
||||
"\x1cmemos.api.v1/UserAccessTokenR\x04name\"\x94\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" +
|
||||
"createTime\x12M\n" +
|
||||
"\x12last_accessed_time\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampB\x03\xe0A\x03R\x10lastAccessedTime\x12J\n" +
|
||||
"\vclient_info\x18\x05 \x01(\v2$.memos.api.v1.UserSession.ClientInfoB\x03\xe0A\x03R\n" +
|
||||
"clientInfo\x1a\xa4\x01\n" +
|
||||
"\n" +
|
||||
"ClientInfo\x12\x1d\n" +
|
||||
|
@ -2190,48 +2180,47 @@ var file_api_v1_user_service_proto_depIdxs = []int32{
|
|||
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
|
||||
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
|
||||
31, // 20: memos.api.v1.UserSession.last_accessed_time:type_name -> google.protobuf.Timestamp
|
||||
29, // 21: memos.api.v1.UserSession.client_info:type_name -> memos.api.v1.UserSession.ClientInfo
|
||||
21, // 22: memos.api.v1.ListUserSessionsResponse.sessions:type_name -> memos.api.v1.UserSession
|
||||
11, // 23: memos.api.v1.ListAllUserStatsResponse.user_stats:type_name -> memos.api.v1.UserStats
|
||||
2, // 24: memos.api.v1.UserService.ListUsers:input_type -> memos.api.v1.ListUsersRequest
|
||||
4, // 25: memos.api.v1.UserService.GetUser:input_type -> memos.api.v1.GetUserRequest
|
||||
5, // 26: memos.api.v1.UserService.CreateUser:input_type -> memos.api.v1.CreateUserRequest
|
||||
6, // 27: memos.api.v1.UserService.UpdateUser:input_type -> memos.api.v1.UpdateUserRequest
|
||||
7, // 28: memos.api.v1.UserService.DeleteUser:input_type -> memos.api.v1.DeleteUserRequest
|
||||
8, // 29: memos.api.v1.UserService.SearchUsers:input_type -> memos.api.v1.SearchUsersRequest
|
||||
10, // 30: memos.api.v1.UserService.GetUserAvatar:input_type -> memos.api.v1.GetUserAvatarRequest
|
||||
25, // 31: memos.api.v1.UserService.ListAllUserStats:input_type -> memos.api.v1.ListAllUserStatsRequest
|
||||
12, // 32: memos.api.v1.UserService.GetUserStats:input_type -> memos.api.v1.GetUserStatsRequest
|
||||
14, // 33: memos.api.v1.UserService.GetUserSetting:input_type -> memos.api.v1.GetUserSettingRequest
|
||||
15, // 34: memos.api.v1.UserService.UpdateUserSetting:input_type -> memos.api.v1.UpdateUserSettingRequest
|
||||
17, // 35: memos.api.v1.UserService.ListUserAccessTokens:input_type -> memos.api.v1.ListUserAccessTokensRequest
|
||||
19, // 36: memos.api.v1.UserService.CreateUserAccessToken:input_type -> memos.api.v1.CreateUserAccessTokenRequest
|
||||
20, // 37: memos.api.v1.UserService.DeleteUserAccessToken:input_type -> memos.api.v1.DeleteUserAccessTokenRequest
|
||||
22, // 38: memos.api.v1.UserService.ListUserSessions:input_type -> memos.api.v1.ListUserSessionsRequest
|
||||
24, // 39: memos.api.v1.UserService.RevokeUserSession:input_type -> memos.api.v1.RevokeUserSessionRequest
|
||||
3, // 40: memos.api.v1.UserService.ListUsers:output_type -> memos.api.v1.ListUsersResponse
|
||||
1, // 41: memos.api.v1.UserService.GetUser:output_type -> memos.api.v1.User
|
||||
1, // 42: memos.api.v1.UserService.CreateUser:output_type -> memos.api.v1.User
|
||||
1, // 43: memos.api.v1.UserService.UpdateUser:output_type -> memos.api.v1.User
|
||||
33, // 44: memos.api.v1.UserService.DeleteUser:output_type -> google.protobuf.Empty
|
||||
9, // 45: memos.api.v1.UserService.SearchUsers:output_type -> memos.api.v1.SearchUsersResponse
|
||||
34, // 46: memos.api.v1.UserService.GetUserAvatar:output_type -> google.api.HttpBody
|
||||
26, // 47: memos.api.v1.UserService.ListAllUserStats:output_type -> memos.api.v1.ListAllUserStatsResponse
|
||||
11, // 48: memos.api.v1.UserService.GetUserStats:output_type -> memos.api.v1.UserStats
|
||||
13, // 49: memos.api.v1.UserService.GetUserSetting:output_type -> memos.api.v1.UserSetting
|
||||
13, // 50: memos.api.v1.UserService.UpdateUserSetting:output_type -> memos.api.v1.UserSetting
|
||||
18, // 51: memos.api.v1.UserService.ListUserAccessTokens:output_type -> memos.api.v1.ListUserAccessTokensResponse
|
||||
16, // 52: memos.api.v1.UserService.CreateUserAccessToken:output_type -> memos.api.v1.UserAccessToken
|
||||
33, // 53: memos.api.v1.UserService.DeleteUserAccessToken:output_type -> google.protobuf.Empty
|
||||
23, // 54: memos.api.v1.UserService.ListUserSessions:output_type -> memos.api.v1.ListUserSessionsResponse
|
||||
33, // 55: memos.api.v1.UserService.RevokeUserSession:output_type -> google.protobuf.Empty
|
||||
40, // [40:56] is the sub-list for method output_type
|
||||
24, // [24:40] is the sub-list for method input_type
|
||||
24, // [24:24] is the sub-list for extension type_name
|
||||
24, // [24:24] is the sub-list for extension extendee
|
||||
0, // [0:24] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_api_v1_user_service_proto_init() }
|
||||
|
|
|
@ -3282,21 +3282,18 @@ definitions:
|
|||
ssoCredentials:
|
||||
$ref: '#/definitions/CreateSessionRequestSSOCredentials'
|
||||
description: SSO provider authentication method.
|
||||
neverExpire:
|
||||
type: boolean
|
||||
description: |-
|
||||
Whether the session should never expire.
|
||||
Optional field that defaults to false for security.
|
||||
v1CreateSessionResponse:
|
||||
type: object
|
||||
properties:
|
||||
user:
|
||||
$ref: '#/definitions/v1User'
|
||||
description: The authenticated user information.
|
||||
expiresAt:
|
||||
lastAccessedAt:
|
||||
type: string
|
||||
format: date-time
|
||||
description: Token expiration time.
|
||||
description: |-
|
||||
Last time the session was accessed.
|
||||
Used for sliding expiration calculation (last_accessed_time + 2 weeks).
|
||||
v1EmbeddedContentNode:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -3316,10 +3313,12 @@ definitions:
|
|||
properties:
|
||||
user:
|
||||
$ref: '#/definitions/v1User'
|
||||
expiresAt:
|
||||
lastAccessedAt:
|
||||
type: string
|
||||
format: date-time
|
||||
description: Current session expiration time (if available).
|
||||
description: |-
|
||||
Last time the session was accessed.
|
||||
Used for sliding expiration calculation (last_accessed_time + 2 weeks).
|
||||
v1HTMLElementNode:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -4152,15 +4151,12 @@ definitions:
|
|||
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.
|
||||
description: |-
|
||||
The timestamp when the session was last accessed.
|
||||
Used for sliding expiration calculation (last_accessed_time + 2 weeks).
|
||||
readOnly: true
|
||||
clientInfo:
|
||||
$ref: '#/definitions/v1UserSessionClientInfo'
|
||||
|
|
|
@ -476,12 +476,11 @@ type SessionsUserSetting_Session struct {
|
|||
SessionId string `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"`
|
||||
// Timestamp when the session was created.
|
||||
CreateTime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=create_time,json=createTime,proto3" json:"create_time,omitempty"`
|
||||
// Timestamp when the session expires.
|
||||
ExpireTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=expire_time,json=expireTime,proto3" json:"expire_time,omitempty"`
|
||||
// Timestamp when the session was last accessed.
|
||||
LastAccessedTime *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=last_accessed_time,json=lastAccessedTime,proto3" json:"last_accessed_time,omitempty"`
|
||||
// Used for sliding expiration calculation (last_accessed_time + 2 weeks).
|
||||
LastAccessedTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=last_accessed_time,json=lastAccessedTime,proto3" json:"last_accessed_time,omitempty"`
|
||||
// Client information associated with this session.
|
||||
ClientInfo *SessionsUserSetting_ClientInfo `protobuf:"bytes,5,opt,name=client_info,json=clientInfo,proto3" json:"client_info,omitempty"`
|
||||
ClientInfo *SessionsUserSetting_ClientInfo `protobuf:"bytes,4,opt,name=client_info,json=clientInfo,proto3" json:"client_info,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
@ -530,13 +529,6 @@ func (x *SessionsUserSetting_Session) GetCreateTime() *timestamppb.Timestamp {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (x *SessionsUserSetting_Session) GetExpireTime() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.ExpireTime
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *SessionsUserSetting_Session) GetLastAccessedTime() *timestamppb.Timestamp {
|
||||
if x != nil {
|
||||
return x.LastAccessedTime
|
||||
|
@ -836,18 +828,16 @@ const file_store_user_setting_proto_rawDesc = "" +
|
|||
"\n" +
|
||||
"appearance\x18\x02 \x01(\tR\n" +
|
||||
"appearance\x12'\n" +
|
||||
"\x0fmemo_visibility\x18\x03 \x01(\tR\x0ememoVisibility\"\xb0\x04\n" +
|
||||
"\x0fmemo_visibility\x18\x03 \x01(\tR\x0ememoVisibility\"\xf3\x03\n" +
|
||||
"\x13SessionsUserSetting\x12D\n" +
|
||||
"\bsessions\x18\x01 \x03(\v2(.memos.store.SessionsUserSetting.SessionR\bsessions\x1a\xba\x02\n" +
|
||||
"\bsessions\x18\x01 \x03(\v2(.memos.store.SessionsUserSetting.SessionR\bsessions\x1a\xfd\x01\n" +
|
||||
"\aSession\x12\x1d\n" +
|
||||
"\n" +
|
||||
"session_id\x18\x01 \x01(\tR\tsessionId\x12;\n" +
|
||||
"\vcreate_time\x18\x02 \x01(\v2\x1a.google.protobuf.TimestampR\n" +
|
||||
"createTime\x12;\n" +
|
||||
"\vexpire_time\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampR\n" +
|
||||
"expireTime\x12H\n" +
|
||||
"\x12last_accessed_time\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampR\x10lastAccessedTime\x12L\n" +
|
||||
"\vclient_info\x18\x05 \x01(\v2+.memos.store.SessionsUserSetting.ClientInfoR\n" +
|
||||
"createTime\x12H\n" +
|
||||
"\x12last_accessed_time\x18\x03 \x01(\v2\x1a.google.protobuf.TimestampR\x10lastAccessedTime\x12L\n" +
|
||||
"\vclient_info\x18\x04 \x01(\v2+.memos.store.SessionsUserSetting.ClientInfoR\n" +
|
||||
"clientInfo\x1a\x95\x01\n" +
|
||||
"\n" +
|
||||
"ClientInfo\x12\x1d\n" +
|
||||
|
@ -919,14 +909,13 @@ var file_store_user_setting_proto_depIdxs = []int32{
|
|||
10, // 8: memos.store.ShortcutsUserSetting.shortcuts:type_name -> memos.store.ShortcutsUserSetting.Shortcut
|
||||
11, // 9: memos.store.WebhooksUserSetting.webhooks:type_name -> memos.store.WebhooksUserSetting.Webhook
|
||||
12, // 10: memos.store.SessionsUserSetting.Session.create_time:type_name -> google.protobuf.Timestamp
|
||||
12, // 11: memos.store.SessionsUserSetting.Session.expire_time:type_name -> google.protobuf.Timestamp
|
||||
12, // 12: memos.store.SessionsUserSetting.Session.last_accessed_time:type_name -> google.protobuf.Timestamp
|
||||
8, // 13: memos.store.SessionsUserSetting.Session.client_info:type_name -> memos.store.SessionsUserSetting.ClientInfo
|
||||
14, // [14:14] is the sub-list for method output_type
|
||||
14, // [14:14] is the sub-list for method input_type
|
||||
14, // [14:14] is the sub-list for extension type_name
|
||||
14, // [14:14] is the sub-list for extension extendee
|
||||
0, // [0:14] is the sub-list for field type_name
|
||||
12, // 11: memos.store.SessionsUserSetting.Session.last_accessed_time:type_name -> google.protobuf.Timestamp
|
||||
8, // 12: memos.store.SessionsUserSetting.Session.client_info:type_name -> memos.store.SessionsUserSetting.ClientInfo
|
||||
13, // [13:13] is the sub-list for method output_type
|
||||
13, // [13:13] is the sub-list for method input_type
|
||||
13, // [13:13] is the sub-list for extension type_name
|
||||
13, // [13:13] is the sub-list for extension extendee
|
||||
0, // [0:13] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_store_user_setting_proto_init() }
|
||||
|
|
|
@ -48,12 +48,11 @@ message SessionsUserSetting {
|
|||
string session_id = 1;
|
||||
// Timestamp when the session was created.
|
||||
google.protobuf.Timestamp create_time = 2;
|
||||
// Timestamp when the session expires.
|
||||
google.protobuf.Timestamp expire_time = 3;
|
||||
// Timestamp when the session was last accessed.
|
||||
google.protobuf.Timestamp last_accessed_time = 4;
|
||||
// Used for sliding expiration calculation (last_accessed_time + 2 weeks).
|
||||
google.protobuf.Timestamp last_accessed_time = 3;
|
||||
// Client information associated with this session.
|
||||
ClientInfo client_info = 5;
|
||||
ClientInfo client_info = 4;
|
||||
}
|
||||
|
||||
message ClientInfo {
|
||||
|
|
|
@ -203,13 +203,16 @@ func (in *GRPCAuthInterceptor) updateSessionLastAccessed(ctx context.Context, us
|
|||
return in.Store.UpdateUserSessionLastAccessed(ctx, userID, sessionID, timestamppb.Now())
|
||||
}
|
||||
|
||||
// validateUserSession checks if a session exists and is still valid.
|
||||
// validateUserSession checks if a session exists and is still valid using sliding expiration.
|
||||
func validateUserSession(sessionID string, userSessions []*storepb.SessionsUserSetting_Session) bool {
|
||||
for _, session := range userSessions {
|
||||
if sessionID == session.SessionId {
|
||||
// Check if session has expired
|
||||
if session.ExpireTime != nil && session.ExpireTime.AsTime().Before(time.Now()) {
|
||||
return false
|
||||
// Use sliding expiration: check if last_accessed_time + 2 weeks > current_time
|
||||
if session.LastAccessedTime != nil {
|
||||
expirationTime := session.LastAccessedTime.AsTime().Add(SessionSlidingDuration)
|
||||
if expirationTime.Before(time.Now()) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -19,11 +19,10 @@ const (
|
|||
KeyID = "v1"
|
||||
// AccessTokenAudienceName is the audience name of the access token.
|
||||
AccessTokenAudienceName = "user.access-token"
|
||||
AccessTokenDuration = 7 * 24 * time.Hour
|
||||
// SessionSlidingDuration is the sliding expiration duration for user sessions (2 weeks).
|
||||
// Sessions are considered valid if last_accessed_time + SessionSlidingDuration > current_time.
|
||||
SessionSlidingDuration = 14 * 24 * time.Hour
|
||||
|
||||
// CookieExpDuration expires slightly earlier than the jwt expiration. Client would be logged out if the user
|
||||
// cookie expires, thus the client would always logout first before attempting to make a request with the expired jwt.
|
||||
CookieExpDuration = AccessTokenDuration - 1*time.Minute
|
||||
// SessionCookieName is the cookie name of user session ID.
|
||||
SessionCookieName = "user_session"
|
||||
)
|
||||
|
|
|
@ -42,16 +42,20 @@ func (s *APIV1Service) GetCurrentSession(ctx context.Context, _ *v1pb.GetCurrent
|
|||
return nil, status.Errorf(codes.Unauthenticated, "user not found")
|
||||
}
|
||||
|
||||
// Update session last accessed time if we have a session ID
|
||||
var lastAccessedAt *timestamppb.Timestamp
|
||||
// Update session last accessed time if we have a session ID and get the current session info
|
||||
if sessionID, ok := ctx.Value(sessionIDContextKey).(string); ok && sessionID != "" {
|
||||
if err := s.Store.UpdateUserSessionLastAccessed(ctx, user.ID, sessionID, timestamppb.Now()); err != nil {
|
||||
now := timestamppb.Now()
|
||||
if err := s.Store.UpdateUserSessionLastAccessed(ctx, user.ID, sessionID, now); err != nil {
|
||||
// Log error but don't fail the request
|
||||
slog.Error("failed to update session last accessed time", "error", err)
|
||||
}
|
||||
lastAccessedAt = now
|
||||
}
|
||||
|
||||
return &v1pb.GetCurrentSessionResponse{
|
||||
User: convertUserFromStore(user),
|
||||
User: convertUserFromStore(user),
|
||||
LastAccessedAt: lastAccessedAt,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -167,18 +171,15 @@ func (s *APIV1Service) CreateSession(ctx context.Context, request *v1pb.CreateSe
|
|||
return nil, status.Errorf(codes.PermissionDenied, "user has been archived with username %s", existingUser.Username)
|
||||
}
|
||||
|
||||
expireTime := time.Now().Add(AccessTokenDuration)
|
||||
if request.NeverExpire {
|
||||
// Set the expire time to 100 years.
|
||||
expireTime = time.Now().Add(100 * 365 * 24 * time.Hour)
|
||||
}
|
||||
// Default session expiration time is 100 year
|
||||
expireTime := time.Now().Add(100 * 365 * 24 * time.Hour)
|
||||
if err := s.doSignIn(ctx, existingUser, expireTime); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "failed to sign in, error: %v", err)
|
||||
}
|
||||
|
||||
return &v1pb.CreateSessionResponse{
|
||||
User: convertUserFromStore(existingUser),
|
||||
ExpiresAt: timestamppb.New(expireTime),
|
||||
User: convertUserFromStore(existingUser),
|
||||
LastAccessedAt: timestamppb.Now(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -190,7 +191,7 @@ func (s *APIV1Service) doSignIn(ctx context.Context, user *store.User, expireTim
|
|||
}
|
||||
|
||||
// Track session in user settings
|
||||
if err := s.trackUserSession(ctx, user.ID, sessionID, expireTime); err != nil {
|
||||
if err := s.trackUserSession(ctx, user.ID, sessionID); err != nil {
|
||||
// Log the error but don't fail the login if session tracking fails
|
||||
// This ensures backward compatibility
|
||||
slog.Error("failed to track user session", "error", err)
|
||||
|
@ -308,14 +309,13 @@ func (s *APIV1Service) GetCurrentUser(ctx context.Context) (*store.User, error)
|
|||
}
|
||||
|
||||
// Helper function to track user session for session management.
|
||||
func (s *APIV1Service) trackUserSession(ctx context.Context, userID int32, sessionID string, expireTime time.Time) error {
|
||||
func (s *APIV1Service) trackUserSession(ctx context.Context, userID int32, sessionID string) 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,
|
||||
}
|
||||
|
|
|
@ -650,7 +650,6 @@ func (s *APIV1Service) ListUserSessions(ctx context.Context, request *v1pb.ListU
|
|||
Name: fmt.Sprintf("users/%d/sessions/%s", userID, userSession.SessionId),
|
||||
SessionId: userSession.SessionId,
|
||||
CreateTime: userSession.CreateTime,
|
||||
ExpireTime: userSession.ExpireTime,
|
||||
LastAccessedTime: userSession.LastAccessedTime,
|
||||
}
|
||||
|
||||
|
@ -715,7 +714,6 @@ func (s *APIV1Service) UpsertUserSession(ctx context.Context, userID int32, sess
|
|||
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,
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { Button, Checkbox, Input } from "@usememos/mui";
|
||||
import { Button, Input } from "@usememos/mui";
|
||||
import { LoaderIcon } from "lucide-react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { ClientError } from "nice-grpc-web";
|
||||
|
@ -17,7 +17,6 @@ const PasswordSignInForm = observer(() => {
|
|||
const actionBtnLoadingState = useLoading(false);
|
||||
const [username, setUsername] = useState(workspaceStore.state.profile.mode === "demo" ? "yourselfhosted" : "");
|
||||
const [password, setPassword] = useState(workspaceStore.state.profile.mode === "demo" ? "yourselfhosted" : "");
|
||||
const [remember, setRemember] = useState(true);
|
||||
|
||||
const handleUsernameInputChanged = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const text = e.target.value as string;
|
||||
|
@ -47,7 +46,6 @@ const PasswordSignInForm = observer(() => {
|
|||
actionBtnLoadingState.setLoading();
|
||||
await authServiceClient.createSession({
|
||||
passwordCredentials: { username, password },
|
||||
neverExpire: remember,
|
||||
});
|
||||
await initialUserStore();
|
||||
navigateTo("/");
|
||||
|
@ -94,9 +92,6 @@ const PasswordSignInForm = observer(() => {
|
|||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-row justify-start items-center w-full mt-6">
|
||||
<Checkbox label={t("common.remember-me")} checked={remember} onChange={(e) => setRemember(e.target.checked)} />
|
||||
</div>
|
||||
<div className="flex flex-row justify-end items-center w-full mt-6">
|
||||
<Button
|
||||
type="submit"
|
||||
|
|
|
@ -60,6 +60,18 @@ const UserSessionsSection = () => {
|
|||
return parts.length > 0 ? parts.join(" • ") : "Unknown Device";
|
||||
};
|
||||
|
||||
const getSessionExpirationDate = (session: UserSession) => {
|
||||
if (!session.lastAccessedTime) return null;
|
||||
// Calculate expiration as last_accessed_time + 2 weeks (14 days)
|
||||
const expirationDate = new Date(session.lastAccessedTime.getTime() + 14 * 24 * 60 * 60 * 1000);
|
||||
return expirationDate;
|
||||
};
|
||||
|
||||
const isSessionExpired = (session: UserSession) => {
|
||||
const expirationDate = getSessionExpirationDate(session);
|
||||
return expirationDate ? expirationDate < new Date() : false;
|
||||
};
|
||||
|
||||
const isCurrentSession = (session: UserSession) => {
|
||||
// A simple heuristic: the most recently accessed session is likely the current one
|
||||
if (userSessions.length === 0) return false;
|
||||
|
@ -126,7 +138,13 @@ const UserSessionsSection = () => {
|
|||
</div>
|
||||
</td>
|
||||
<td className="whitespace-nowrap px-3 py-2 text-sm text-gray-500 dark:text-gray-400">
|
||||
{userSession.expireTime?.toLocaleString() ?? t("setting.user-sessions-section.never")}
|
||||
<div className="flex items-center space-x-1">
|
||||
<ClockIcon className="w-4 h-4" />
|
||||
<span>
|
||||
{getSessionExpirationDate(userSession)?.toLocaleString() ?? t("setting.user-sessions-section.never")}
|
||||
{isSessionExpired(userSession) && <span className="ml-2 text-red-600 text-xs">(Expired)</span>}
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td className="relative whitespace-nowrap py-2 pl-3 pr-4 text-right text-sm">
|
||||
<Button
|
||||
|
|
|
@ -253,7 +253,7 @@
|
|||
},
|
||||
"user-sessions-section": {
|
||||
"title": "Active Sessions",
|
||||
"description": "A list of all active sessions for your account. You can revoke any session except the current one.",
|
||||
"description": "A list of all active sessions for your account. Sessions automatically expire 2 weeks after the last activity. You can revoke any session except the current one.",
|
||||
"device": "Device",
|
||||
"location": "Location",
|
||||
"last-active": "Last Active",
|
||||
|
@ -442,4 +442,4 @@
|
|||
"rename-tag": "Rename tag",
|
||||
"rename-tip": "All your memos with this tag will be updated."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,11 @@ export interface GetCurrentSessionResponse {
|
|||
user?:
|
||||
| User
|
||||
| undefined;
|
||||
/** Current session expiration time (if available). */
|
||||
expiresAt?: Date | undefined;
|
||||
/**
|
||||
* Last time the session was accessed.
|
||||
* Used for sliding expiration calculation (last_accessed_time + 2 weeks).
|
||||
*/
|
||||
lastAccessedAt?: Date | undefined;
|
||||
}
|
||||
|
||||
export interface CreateSessionRequest {
|
||||
|
@ -29,14 +32,7 @@ export interface CreateSessionRequest {
|
|||
| CreateSessionRequest_PasswordCredentials
|
||||
| undefined;
|
||||
/** SSO provider authentication method. */
|
||||
ssoCredentials?:
|
||||
| CreateSessionRequest_SSOCredentials
|
||||
| undefined;
|
||||
/**
|
||||
* Whether the session should never expire.
|
||||
* Optional field that defaults to false for security.
|
||||
*/
|
||||
neverExpire: boolean;
|
||||
ssoCredentials?: CreateSessionRequest_SSOCredentials | undefined;
|
||||
}
|
||||
|
||||
/** Nested message for password-based authentication credentials. */
|
||||
|
@ -77,8 +73,11 @@ export interface CreateSessionResponse {
|
|||
user?:
|
||||
| User
|
||||
| undefined;
|
||||
/** Token expiration time. */
|
||||
expiresAt?: Date | undefined;
|
||||
/**
|
||||
* Last time the session was accessed.
|
||||
* Used for sliding expiration calculation (last_accessed_time + 2 weeks).
|
||||
*/
|
||||
lastAccessedAt?: Date | undefined;
|
||||
}
|
||||
|
||||
export interface DeleteSessionRequest {
|
||||
|
@ -119,7 +118,7 @@ export const GetCurrentSessionRequest: MessageFns<GetCurrentSessionRequest> = {
|
|||
};
|
||||
|
||||
function createBaseGetCurrentSessionResponse(): GetCurrentSessionResponse {
|
||||
return { user: undefined, expiresAt: undefined };
|
||||
return { user: undefined, lastAccessedAt: undefined };
|
||||
}
|
||||
|
||||
export const GetCurrentSessionResponse: MessageFns<GetCurrentSessionResponse> = {
|
||||
|
@ -127,8 +126,8 @@ export const GetCurrentSessionResponse: MessageFns<GetCurrentSessionResponse> =
|
|||
if (message.user !== undefined) {
|
||||
User.encode(message.user, writer.uint32(10).fork()).join();
|
||||
}
|
||||
if (message.expiresAt !== undefined) {
|
||||
Timestamp.encode(toTimestamp(message.expiresAt), writer.uint32(18).fork()).join();
|
||||
if (message.lastAccessedAt !== undefined) {
|
||||
Timestamp.encode(toTimestamp(message.lastAccessedAt), writer.uint32(18).fork()).join();
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
|
@ -153,7 +152,7 @@ export const GetCurrentSessionResponse: MessageFns<GetCurrentSessionResponse> =
|
|||
break;
|
||||
}
|
||||
|
||||
message.expiresAt = fromTimestamp(Timestamp.decode(reader, reader.uint32()));
|
||||
message.lastAccessedAt = fromTimestamp(Timestamp.decode(reader, reader.uint32()));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -171,13 +170,13 @@ export const GetCurrentSessionResponse: MessageFns<GetCurrentSessionResponse> =
|
|||
fromPartial(object: DeepPartial<GetCurrentSessionResponse>): GetCurrentSessionResponse {
|
||||
const message = createBaseGetCurrentSessionResponse();
|
||||
message.user = (object.user !== undefined && object.user !== null) ? User.fromPartial(object.user) : undefined;
|
||||
message.expiresAt = object.expiresAt ?? undefined;
|
||||
message.lastAccessedAt = object.lastAccessedAt ?? undefined;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
||||
function createBaseCreateSessionRequest(): CreateSessionRequest {
|
||||
return { passwordCredentials: undefined, ssoCredentials: undefined, neverExpire: false };
|
||||
return { passwordCredentials: undefined, ssoCredentials: undefined };
|
||||
}
|
||||
|
||||
export const CreateSessionRequest: MessageFns<CreateSessionRequest> = {
|
||||
|
@ -188,9 +187,6 @@ export const CreateSessionRequest: MessageFns<CreateSessionRequest> = {
|
|||
if (message.ssoCredentials !== undefined) {
|
||||
CreateSessionRequest_SSOCredentials.encode(message.ssoCredentials, writer.uint32(18).fork()).join();
|
||||
}
|
||||
if (message.neverExpire !== false) {
|
||||
writer.uint32(24).bool(message.neverExpire);
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
|
||||
|
@ -217,14 +213,6 @@ export const CreateSessionRequest: MessageFns<CreateSessionRequest> = {
|
|||
message.ssoCredentials = CreateSessionRequest_SSOCredentials.decode(reader, reader.uint32());
|
||||
continue;
|
||||
}
|
||||
case 3: {
|
||||
if (tag !== 24) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.neverExpire = reader.bool();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
|
@ -245,7 +233,6 @@ export const CreateSessionRequest: MessageFns<CreateSessionRequest> = {
|
|||
message.ssoCredentials = (object.ssoCredentials !== undefined && object.ssoCredentials !== null)
|
||||
? CreateSessionRequest_SSOCredentials.fromPartial(object.ssoCredentials)
|
||||
: undefined;
|
||||
message.neverExpire = object.neverExpire ?? false;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
@ -379,7 +366,7 @@ export const CreateSessionRequest_SSOCredentials: MessageFns<CreateSessionReques
|
|||
};
|
||||
|
||||
function createBaseCreateSessionResponse(): CreateSessionResponse {
|
||||
return { user: undefined, expiresAt: undefined };
|
||||
return { user: undefined, lastAccessedAt: undefined };
|
||||
}
|
||||
|
||||
export const CreateSessionResponse: MessageFns<CreateSessionResponse> = {
|
||||
|
@ -387,8 +374,8 @@ export const CreateSessionResponse: MessageFns<CreateSessionResponse> = {
|
|||
if (message.user !== undefined) {
|
||||
User.encode(message.user, writer.uint32(10).fork()).join();
|
||||
}
|
||||
if (message.expiresAt !== undefined) {
|
||||
Timestamp.encode(toTimestamp(message.expiresAt), writer.uint32(18).fork()).join();
|
||||
if (message.lastAccessedAt !== undefined) {
|
||||
Timestamp.encode(toTimestamp(message.lastAccessedAt), writer.uint32(18).fork()).join();
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
|
@ -413,7 +400,7 @@ export const CreateSessionResponse: MessageFns<CreateSessionResponse> = {
|
|||
break;
|
||||
}
|
||||
|
||||
message.expiresAt = fromTimestamp(Timestamp.decode(reader, reader.uint32()));
|
||||
message.lastAccessedAt = fromTimestamp(Timestamp.decode(reader, reader.uint32()));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -431,7 +418,7 @@ export const CreateSessionResponse: MessageFns<CreateSessionResponse> = {
|
|||
fromPartial(object: DeepPartial<CreateSessionResponse>): CreateSessionResponse {
|
||||
const message = createBaseCreateSessionResponse();
|
||||
message.user = (object.user !== undefined && object.user !== null) ? User.fromPartial(object.user) : undefined;
|
||||
message.expiresAt = object.expiresAt ?? undefined;
|
||||
message.lastAccessedAt = object.lastAccessedAt ?? undefined;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -365,11 +365,10 @@ export interface UserSession {
|
|||
createTime?:
|
||||
| Date
|
||||
| undefined;
|
||||
/** The timestamp when the session expires. */
|
||||
expireTime?:
|
||||
| Date
|
||||
| undefined;
|
||||
/** The timestamp when the session was last accessed. */
|
||||
/**
|
||||
* The timestamp when the session was last accessed.
|
||||
* Used for sliding expiration calculation (last_accessed_time + 2 weeks).
|
||||
*/
|
||||
lastAccessedTime?:
|
||||
| Date
|
||||
| undefined;
|
||||
|
@ -2073,14 +2072,7 @@ export const DeleteUserAccessTokenRequest: MessageFns<DeleteUserAccessTokenReque
|
|||
};
|
||||
|
||||
function createBaseUserSession(): UserSession {
|
||||
return {
|
||||
name: "",
|
||||
sessionId: "",
|
||||
createTime: undefined,
|
||||
expireTime: undefined,
|
||||
lastAccessedTime: undefined,
|
||||
clientInfo: undefined,
|
||||
};
|
||||
return { name: "", sessionId: "", createTime: undefined, lastAccessedTime: undefined, clientInfo: undefined };
|
||||
}
|
||||
|
||||
export const UserSession: MessageFns<UserSession> = {
|
||||
|
@ -2094,14 +2086,11 @@ export const UserSession: MessageFns<UserSession> = {
|
|||
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();
|
||||
Timestamp.encode(toTimestamp(message.lastAccessedTime), writer.uint32(34).fork()).join();
|
||||
}
|
||||
if (message.clientInfo !== undefined) {
|
||||
UserSession_ClientInfo.encode(message.clientInfo, writer.uint32(50).fork()).join();
|
||||
UserSession_ClientInfo.encode(message.clientInfo, writer.uint32(42).fork()).join();
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
|
@ -2142,7 +2131,7 @@ export const UserSession: MessageFns<UserSession> = {
|
|||
break;
|
||||
}
|
||||
|
||||
message.expireTime = fromTimestamp(Timestamp.decode(reader, reader.uint32()));
|
||||
message.lastAccessedTime = fromTimestamp(Timestamp.decode(reader, reader.uint32()));
|
||||
continue;
|
||||
}
|
||||
case 5: {
|
||||
|
@ -2150,14 +2139,6 @@ export const UserSession: MessageFns<UserSession> = {
|
|||
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;
|
||||
}
|
||||
|
@ -2178,7 +2159,6 @@ export const UserSession: MessageFns<UserSession> = {
|
|||
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)
|
||||
|
|
|
@ -35,7 +35,7 @@ export enum Edition {
|
|||
EDITION_2024 = "EDITION_2024",
|
||||
/**
|
||||
* EDITION_1_TEST_ONLY - Placeholder editions for testing feature resolution. These should not be
|
||||
* used or relied on outside of tests.
|
||||
* used or relyed on outside of tests.
|
||||
*/
|
||||
EDITION_1_TEST_ONLY = "EDITION_1_TEST_ONLY",
|
||||
EDITION_2_TEST_ONLY = "EDITION_2_TEST_ONLY",
|
||||
|
@ -177,19 +177,11 @@ export interface FileDescriptorProto {
|
|||
* The supported values are "proto2", "proto3", and "editions".
|
||||
*
|
||||
* If `edition` is present, this value must be "editions".
|
||||
* WARNING: This field should only be used by protobuf plugins or special
|
||||
* cases like the proto compiler. Other uses are discouraged and
|
||||
* developers should rely on the protoreflect APIs for their client language.
|
||||
*/
|
||||
syntax?:
|
||||
| string
|
||||
| undefined;
|
||||
/**
|
||||
* The edition of the proto file.
|
||||
* WARNING: This field should only be used by protobuf plugins or special
|
||||
* cases like the proto compiler. Other uses are discouraged and
|
||||
* developers should rely on the protoreflect APIs for their client language.
|
||||
*/
|
||||
/** The edition of the proto file. */
|
||||
edition?: Edition | undefined;
|
||||
}
|
||||
|
||||
|
@ -836,12 +828,7 @@ export interface FileOptions {
|
|||
rubyPackage?:
|
||||
| string
|
||||
| undefined;
|
||||
/**
|
||||
* Any features defined in the specific edition.
|
||||
* WARNING: This field should only be used by protobuf plugins or special
|
||||
* cases like the proto compiler. Other uses are discouraged and
|
||||
* developers should rely on the protoreflect APIs for their client language.
|
||||
*/
|
||||
/** Any features defined in the specific edition. */
|
||||
features?:
|
||||
| FeatureSet
|
||||
| undefined;
|
||||
|
@ -979,12 +966,7 @@ export interface MessageOptions {
|
|||
deprecatedLegacyJsonFieldConflicts?:
|
||||
| boolean
|
||||
| undefined;
|
||||
/**
|
||||
* Any features defined in the specific edition.
|
||||
* WARNING: This field should only be used by protobuf plugins or special
|
||||
* cases like the proto compiler. Other uses are discouraged and
|
||||
* developers should rely on the protoreflect APIs for their client language.
|
||||
*/
|
||||
/** Any features defined in the specific edition. */
|
||||
features?:
|
||||
| FeatureSet
|
||||
| undefined;
|
||||
|
@ -994,13 +976,12 @@ export interface MessageOptions {
|
|||
|
||||
export interface FieldOptions {
|
||||
/**
|
||||
* NOTE: ctype is deprecated. Use `features.(pb.cpp).string_type` instead.
|
||||
* The ctype option instructs the C++ code generator to use a different
|
||||
* representation of the field than it normally would. See the specific
|
||||
* options below. This option is only implemented to support use of
|
||||
* [ctype=CORD] and [ctype=STRING] (the default) on non-repeated fields of
|
||||
* type "bytes" in the open source release.
|
||||
* TODO: make ctype actually deprecated.
|
||||
* type "bytes" in the open source release -- sorry, we'll try to include
|
||||
* other types in a future version!
|
||||
*/
|
||||
ctype?:
|
||||
| FieldOptions_CType
|
||||
|
@ -1089,12 +1070,7 @@ export interface FieldOptions {
|
|||
retention?: FieldOptions_OptionRetention | undefined;
|
||||
targets: FieldOptions_OptionTargetType[];
|
||||
editionDefaults: FieldOptions_EditionDefault[];
|
||||
/**
|
||||
* Any features defined in the specific edition.
|
||||
* WARNING: This field should only be used by protobuf plugins or special
|
||||
* cases like the proto compiler. Other uses are discouraged and
|
||||
* developers should rely on the protoreflect APIs for their client language.
|
||||
*/
|
||||
/** Any features defined in the specific edition. */
|
||||
features?: FeatureSet | undefined;
|
||||
featureSupport?:
|
||||
| FieldOptions_FeatureSupport
|
||||
|
@ -1193,7 +1169,11 @@ export function fieldOptions_JSTypeToNumber(object: FieldOptions_JSType): number
|
|||
}
|
||||
}
|
||||
|
||||
/** If set to RETENTION_SOURCE, the option will be omitted from the binary. */
|
||||
/**
|
||||
* If set to RETENTION_SOURCE, the option will be omitted from the binary.
|
||||
* Note: as of January 2023, support for this is in progress and does not yet
|
||||
* have an effect (b/264593489).
|
||||
*/
|
||||
export enum FieldOptions_OptionRetention {
|
||||
RETENTION_UNKNOWN = "RETENTION_UNKNOWN",
|
||||
RETENTION_RUNTIME = "RETENTION_RUNTIME",
|
||||
|
@ -1236,7 +1216,8 @@ export function fieldOptions_OptionRetentionToNumber(object: FieldOptions_Option
|
|||
/**
|
||||
* This indicates the types of entities that the field may apply to when used
|
||||
* as an option. If it is unset, then the field may be freely used as an
|
||||
* option on any kind of entity.
|
||||
* option on any kind of entity. Note: as of January 2023, support for this is
|
||||
* in progress and does not yet have an effect (b/264593489).
|
||||
*/
|
||||
export enum FieldOptions_OptionTargetType {
|
||||
TARGET_TYPE_UNKNOWN = "TARGET_TYPE_UNKNOWN",
|
||||
|
@ -1360,12 +1341,7 @@ export interface FieldOptions_FeatureSupport {
|
|||
}
|
||||
|
||||
export interface OneofOptions {
|
||||
/**
|
||||
* Any features defined in the specific edition.
|
||||
* WARNING: This field should only be used by protobuf plugins or special
|
||||
* cases like the proto compiler. Other uses are discouraged and
|
||||
* developers should rely on the protoreflect APIs for their client language.
|
||||
*/
|
||||
/** Any features defined in the specific edition. */
|
||||
features?:
|
||||
| FeatureSet
|
||||
| undefined;
|
||||
|
@ -1403,12 +1379,7 @@ export interface EnumOptions {
|
|||
deprecatedLegacyJsonFieldConflicts?:
|
||||
| boolean
|
||||
| undefined;
|
||||
/**
|
||||
* Any features defined in the specific edition.
|
||||
* WARNING: This field should only be used by protobuf plugins or special
|
||||
* cases like the proto compiler. Other uses are discouraged and
|
||||
* developers should rely on the protoreflect APIs for their client language.
|
||||
*/
|
||||
/** Any features defined in the specific edition. */
|
||||
features?:
|
||||
| FeatureSet
|
||||
| undefined;
|
||||
|
@ -1426,12 +1397,7 @@ export interface EnumValueOptions {
|
|||
deprecated?:
|
||||
| boolean
|
||||
| undefined;
|
||||
/**
|
||||
* Any features defined in the specific edition.
|
||||
* WARNING: This field should only be used by protobuf plugins or special
|
||||
* cases like the proto compiler. Other uses are discouraged and
|
||||
* developers should rely on the protoreflect APIs for their client language.
|
||||
*/
|
||||
/** Any features defined in the specific edition. */
|
||||
features?:
|
||||
| FeatureSet
|
||||
| undefined;
|
||||
|
@ -1452,12 +1418,7 @@ export interface EnumValueOptions {
|
|||
}
|
||||
|
||||
export interface ServiceOptions {
|
||||
/**
|
||||
* Any features defined in the specific edition.
|
||||
* WARNING: This field should only be used by protobuf plugins or special
|
||||
* cases like the proto compiler. Other uses are discouraged and
|
||||
* developers should rely on the protoreflect APIs for their client language.
|
||||
*/
|
||||
/** Any features defined in the specific edition. */
|
||||
features?:
|
||||
| FeatureSet
|
||||
| undefined;
|
||||
|
@ -1485,12 +1446,7 @@ export interface MethodOptions {
|
|||
idempotencyLevel?:
|
||||
| MethodOptions_IdempotencyLevel
|
||||
| undefined;
|
||||
/**
|
||||
* Any features defined in the specific edition.
|
||||
* WARNING: This field should only be used by protobuf plugins or special
|
||||
* cases like the proto compiler. Other uses are discouraged and
|
||||
* developers should rely on the protoreflect APIs for their client language.
|
||||
*/
|
||||
/** Any features defined in the specific edition. */
|
||||
features?:
|
||||
| FeatureSet
|
||||
| undefined;
|
||||
|
@ -1593,7 +1549,6 @@ export interface FeatureSet {
|
|||
utf8Validation?: FeatureSet_Utf8Validation | undefined;
|
||||
messageEncoding?: FeatureSet_MessageEncoding | undefined;
|
||||
jsonFormat?: FeatureSet_JsonFormat | undefined;
|
||||
enforceNamingStyle?: FeatureSet_EnforceNamingStyle | undefined;
|
||||
}
|
||||
|
||||
export enum FeatureSet_FieldPresence {
|
||||
|
@ -1836,45 +1791,6 @@ export function featureSet_JsonFormatToNumber(object: FeatureSet_JsonFormat): nu
|
|||
}
|
||||
}
|
||||
|
||||
export enum FeatureSet_EnforceNamingStyle {
|
||||
ENFORCE_NAMING_STYLE_UNKNOWN = "ENFORCE_NAMING_STYLE_UNKNOWN",
|
||||
STYLE2024 = "STYLE2024",
|
||||
STYLE_LEGACY = "STYLE_LEGACY",
|
||||
UNRECOGNIZED = "UNRECOGNIZED",
|
||||
}
|
||||
|
||||
export function featureSet_EnforceNamingStyleFromJSON(object: any): FeatureSet_EnforceNamingStyle {
|
||||
switch (object) {
|
||||
case 0:
|
||||
case "ENFORCE_NAMING_STYLE_UNKNOWN":
|
||||
return FeatureSet_EnforceNamingStyle.ENFORCE_NAMING_STYLE_UNKNOWN;
|
||||
case 1:
|
||||
case "STYLE2024":
|
||||
return FeatureSet_EnforceNamingStyle.STYLE2024;
|
||||
case 2:
|
||||
case "STYLE_LEGACY":
|
||||
return FeatureSet_EnforceNamingStyle.STYLE_LEGACY;
|
||||
case -1:
|
||||
case "UNRECOGNIZED":
|
||||
default:
|
||||
return FeatureSet_EnforceNamingStyle.UNRECOGNIZED;
|
||||
}
|
||||
}
|
||||
|
||||
export function featureSet_EnforceNamingStyleToNumber(object: FeatureSet_EnforceNamingStyle): number {
|
||||
switch (object) {
|
||||
case FeatureSet_EnforceNamingStyle.ENFORCE_NAMING_STYLE_UNKNOWN:
|
||||
return 0;
|
||||
case FeatureSet_EnforceNamingStyle.STYLE2024:
|
||||
return 1;
|
||||
case FeatureSet_EnforceNamingStyle.STYLE_LEGACY:
|
||||
return 2;
|
||||
case FeatureSet_EnforceNamingStyle.UNRECOGNIZED:
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A compiled specification for the defaults of a set of features. These
|
||||
* messages are generated from FeatureSet extensions and can be used to seed
|
||||
|
@ -4998,7 +4914,6 @@ function createBaseFeatureSet(): FeatureSet {
|
|||
utf8Validation: FeatureSet_Utf8Validation.UTF8_VALIDATION_UNKNOWN,
|
||||
messageEncoding: FeatureSet_MessageEncoding.MESSAGE_ENCODING_UNKNOWN,
|
||||
jsonFormat: FeatureSet_JsonFormat.JSON_FORMAT_UNKNOWN,
|
||||
enforceNamingStyle: FeatureSet_EnforceNamingStyle.ENFORCE_NAMING_STYLE_UNKNOWN,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -5033,12 +4948,6 @@ export const FeatureSet: MessageFns<FeatureSet> = {
|
|||
if (message.jsonFormat !== undefined && message.jsonFormat !== FeatureSet_JsonFormat.JSON_FORMAT_UNKNOWN) {
|
||||
writer.uint32(48).int32(featureSet_JsonFormatToNumber(message.jsonFormat));
|
||||
}
|
||||
if (
|
||||
message.enforceNamingStyle !== undefined &&
|
||||
message.enforceNamingStyle !== FeatureSet_EnforceNamingStyle.ENFORCE_NAMING_STYLE_UNKNOWN
|
||||
) {
|
||||
writer.uint32(56).int32(featureSet_EnforceNamingStyleToNumber(message.enforceNamingStyle));
|
||||
}
|
||||
return writer;
|
||||
},
|
||||
|
||||
|
@ -5097,14 +5006,6 @@ export const FeatureSet: MessageFns<FeatureSet> = {
|
|||
message.jsonFormat = featureSet_JsonFormatFromJSON(reader.int32());
|
||||
continue;
|
||||
}
|
||||
case 7: {
|
||||
if (tag !== 56) {
|
||||
break;
|
||||
}
|
||||
|
||||
message.enforceNamingStyle = featureSet_EnforceNamingStyleFromJSON(reader.int32());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break;
|
||||
|
@ -5126,8 +5027,6 @@ export const FeatureSet: MessageFns<FeatureSet> = {
|
|||
message.utf8Validation = object.utf8Validation ?? FeatureSet_Utf8Validation.UTF8_VALIDATION_UNKNOWN;
|
||||
message.messageEncoding = object.messageEncoding ?? FeatureSet_MessageEncoding.MESSAGE_ENCODING_UNKNOWN;
|
||||
message.jsonFormat = object.jsonFormat ?? FeatureSet_JsonFormat.JSON_FORMAT_UNKNOWN;
|
||||
message.enforceNamingStyle = object.enforceNamingStyle ??
|
||||
FeatureSet_EnforceNamingStyle.ENFORCE_NAMING_STYLE_UNKNOWN;
|
||||
return message;
|
||||
},
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue