mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
ws connect to server
This commit is contained in:
parent
7e9d7c0304
commit
1fd460f3e5
@ -18,7 +18,7 @@ export 'package:app_flowy/welcome/domain/i_splash.dart';
|
|||||||
class SplashUserImpl implements ISplashUser {
|
class SplashUserImpl implements ISplashUser {
|
||||||
@override
|
@override
|
||||||
Future<AuthState> currentUserProfile() {
|
Future<AuthState> currentUserProfile() {
|
||||||
final result = UserEventGetUserProfile().send();
|
final result = UserEventInitUser().send();
|
||||||
return result.then((result) {
|
return result.then((result) {
|
||||||
return result.fold(
|
return result.fold(
|
||||||
(userProfile) {
|
(userProfile) {
|
||||||
@ -32,7 +32,6 @@ class SplashUserImpl implements ISplashUser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class SplashRoute implements ISplashRoute {
|
class SplashRoute implements ISplashRoute {
|
||||||
@override
|
@override
|
||||||
Future<void> pushWelcomeScreen(BuildContext context, UserProfile user) async {
|
Future<void> pushWelcomeScreen(BuildContext context, UserProfile user) async {
|
||||||
|
@ -288,12 +288,12 @@ class WorkspaceEventApplyChangeset {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class UserEventGetUserProfile {
|
class UserEventInitUser {
|
||||||
UserEventGetUserProfile();
|
UserEventInitUser();
|
||||||
|
|
||||||
Future<Either<UserProfile, UserError>> send() {
|
Future<Either<UserProfile, UserError>> send() {
|
||||||
final request = FFIRequest.create()
|
final request = FFIRequest.create()
|
||||||
..event = UserEvent.GetUserProfile.toString();
|
..event = UserEvent.InitUser.toString();
|
||||||
|
|
||||||
return Dispatch.asyncRequest(request).then((bytesResult) => bytesResult.fold(
|
return Dispatch.asyncRequest(request).then((bytesResult) => bytesResult.fold(
|
||||||
(okBytes) => left(UserProfile.fromBuffer(okBytes)),
|
(okBytes) => left(UserProfile.fromBuffer(okBytes)),
|
||||||
@ -367,3 +367,17 @@ class UserEventUpdateUser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class UserEventGetUserProfile {
|
||||||
|
UserEventGetUserProfile();
|
||||||
|
|
||||||
|
Future<Either<UserProfile, UserError>> send() {
|
||||||
|
final request = FFIRequest.create()
|
||||||
|
..event = UserEvent.GetUserProfile.toString();
|
||||||
|
|
||||||
|
return Dispatch.asyncRequest(request).then((bytesResult) => bytesResult.fold(
|
||||||
|
(okBytes) => left(UserProfile.fromBuffer(okBytes)),
|
||||||
|
(errBytes) => right(UserError.fromBuffer(errBytes)),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -10,18 +10,20 @@ import 'dart:core' as $core;
|
|||||||
import 'package:protobuf/protobuf.dart' as $pb;
|
import 'package:protobuf/protobuf.dart' as $pb;
|
||||||
|
|
||||||
class UserEvent extends $pb.ProtobufEnum {
|
class UserEvent extends $pb.ProtobufEnum {
|
||||||
static const UserEvent GetUserProfile = UserEvent._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetUserProfile');
|
static const UserEvent InitUser = UserEvent._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'InitUser');
|
||||||
static const UserEvent SignIn = UserEvent._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'SignIn');
|
static const UserEvent SignIn = UserEvent._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'SignIn');
|
||||||
static const UserEvent SignUp = UserEvent._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'SignUp');
|
static const UserEvent SignUp = UserEvent._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'SignUp');
|
||||||
static const UserEvent SignOut = UserEvent._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'SignOut');
|
static const UserEvent SignOut = UserEvent._(3, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'SignOut');
|
||||||
static const UserEvent UpdateUser = UserEvent._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateUser');
|
static const UserEvent UpdateUser = UserEvent._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateUser');
|
||||||
|
static const UserEvent GetUserProfile = UserEvent._(5, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetUserProfile');
|
||||||
|
|
||||||
static const $core.List<UserEvent> values = <UserEvent> [
|
static const $core.List<UserEvent> values = <UserEvent> [
|
||||||
GetUserProfile,
|
InitUser,
|
||||||
SignIn,
|
SignIn,
|
||||||
SignUp,
|
SignUp,
|
||||||
SignOut,
|
SignOut,
|
||||||
UpdateUser,
|
UpdateUser,
|
||||||
|
GetUserProfile,
|
||||||
];
|
];
|
||||||
|
|
||||||
static final $core.Map<$core.int, UserEvent> _byValue = $pb.ProtobufEnum.initByValue(values);
|
static final $core.Map<$core.int, UserEvent> _byValue = $pb.ProtobufEnum.initByValue(values);
|
||||||
|
@ -12,13 +12,14 @@ import 'dart:typed_data' as $typed_data;
|
|||||||
const UserEvent$json = const {
|
const UserEvent$json = const {
|
||||||
'1': 'UserEvent',
|
'1': 'UserEvent',
|
||||||
'2': const [
|
'2': const [
|
||||||
const {'1': 'GetUserProfile', '2': 0},
|
const {'1': 'InitUser', '2': 0},
|
||||||
const {'1': 'SignIn', '2': 1},
|
const {'1': 'SignIn', '2': 1},
|
||||||
const {'1': 'SignUp', '2': 2},
|
const {'1': 'SignUp', '2': 2},
|
||||||
const {'1': 'SignOut', '2': 3},
|
const {'1': 'SignOut', '2': 3},
|
||||||
const {'1': 'UpdateUser', '2': 4},
|
const {'1': 'UpdateUser', '2': 4},
|
||||||
|
const {'1': 'GetUserProfile', '2': 5},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Descriptor for `UserEvent`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
/// Descriptor for `UserEvent`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
||||||
final $typed_data.Uint8List userEventDescriptor = $convert.base64Decode('CglVc2VyRXZlbnQSEgoOR2V0VXNlclByb2ZpbGUQABIKCgZTaWduSW4QARIKCgZTaWduVXAQAhILCgdTaWduT3V0EAMSDgoKVXBkYXRlVXNlchAE');
|
final $typed_data.Uint8List userEventDescriptor = $convert.base64Decode('CglVc2VyRXZlbnQSDAoISW5pdFVzZXIQABIKCgZTaWduSW4QARIKCgZTaWduVXAQAhILCgdTaWduT3V0EAMSDgoKVXBkYXRlVXNlchAEEhIKDkdldFVzZXJQcm9maWxlEAU=');
|
||||||
|
@ -9,8 +9,6 @@ import 'dart:core' as $core;
|
|||||||
|
|
||||||
import 'package:protobuf/protobuf.dart' as $pb;
|
import 'package:protobuf/protobuf.dart' as $pb;
|
||||||
|
|
||||||
export 'user_profile.pbenum.dart';
|
|
||||||
|
|
||||||
class UserToken extends $pb.GeneratedMessage {
|
class UserToken extends $pb.GeneratedMessage {
|
||||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'UserToken', createEmptyInstance: create)
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'UserToken', createEmptyInstance: create)
|
||||||
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'token')
|
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'token')
|
||||||
|
@ -5,24 +5,3 @@
|
|||||||
// @dart = 2.12
|
// @dart = 2.12
|
||||||
// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
|
// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
|
||||||
|
|
||||||
// ignore_for_file: UNDEFINED_SHOWN_NAME
|
|
||||||
import 'dart:core' as $core;
|
|
||||||
import 'package:protobuf/protobuf.dart' as $pb;
|
|
||||||
|
|
||||||
class UserStatus extends $pb.ProtobufEnum {
|
|
||||||
static const UserStatus Unknown = UserStatus._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Unknown');
|
|
||||||
static const UserStatus Login = UserStatus._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Login');
|
|
||||||
static const UserStatus Expired = UserStatus._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Expired');
|
|
||||||
|
|
||||||
static const $core.List<UserStatus> values = <UserStatus> [
|
|
||||||
Unknown,
|
|
||||||
Login,
|
|
||||||
Expired,
|
|
||||||
];
|
|
||||||
|
|
||||||
static final $core.Map<$core.int, UserStatus> _byValue = $pb.ProtobufEnum.initByValue(values);
|
|
||||||
static UserStatus? valueOf($core.int value) => _byValue[value];
|
|
||||||
|
|
||||||
const UserStatus._($core.int v, $core.String n) : super(v, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -8,18 +8,6 @@
|
|||||||
import 'dart:core' as $core;
|
import 'dart:core' as $core;
|
||||||
import 'dart:convert' as $convert;
|
import 'dart:convert' as $convert;
|
||||||
import 'dart:typed_data' as $typed_data;
|
import 'dart:typed_data' as $typed_data;
|
||||||
@$core.Deprecated('Use userStatusDescriptor instead')
|
|
||||||
const UserStatus$json = const {
|
|
||||||
'1': 'UserStatus',
|
|
||||||
'2': const [
|
|
||||||
const {'1': 'Unknown', '2': 0},
|
|
||||||
const {'1': 'Login', '2': 1},
|
|
||||||
const {'1': 'Expired', '2': 2},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Descriptor for `UserStatus`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
|
||||||
final $typed_data.Uint8List userStatusDescriptor = $convert.base64Decode('CgpVc2VyU3RhdHVzEgsKB1Vua25vd24QABIJCgVMb2dpbhABEgsKB0V4cGlyZWQQAg==');
|
|
||||||
@$core.Deprecated('Use userTokenDescriptor instead')
|
@$core.Deprecated('Use userTokenDescriptor instead')
|
||||||
const UserToken$json = const {
|
const UserToken$json = const {
|
||||||
'1': 'UserToken',
|
'1': 'UserToken',
|
||||||
|
@ -86,4 +86,5 @@ path = "src/main.rs"
|
|||||||
once_cell = "1.7.2"
|
once_cell = "1.7.2"
|
||||||
linkify = "0.5.0"
|
linkify = "0.5.0"
|
||||||
flowy-user = { path = "../rust-lib/flowy-user" }
|
flowy-user = { path = "../rust-lib/flowy-user" }
|
||||||
flowy-workspace = { path = "../rust-lib/flowy-workspace" }
|
flowy-workspace = { path = "../rust-lib/flowy-workspace" }
|
||||||
|
flowy-ws = { path = "../rust-lib/flowy-ws" }
|
@ -4,4 +4,4 @@ pub const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(8);
|
|||||||
pub const PING_TIMEOUT: Duration = Duration::from_secs(60);
|
pub const PING_TIMEOUT: Duration = Duration::from_secs(60);
|
||||||
pub const MAX_PAYLOAD_SIZE: usize = 262_144; // max payload size is 256k
|
pub const MAX_PAYLOAD_SIZE: usize = 262_144; // max payload size is 256k
|
||||||
|
|
||||||
pub const IGNORE_ROUTES: [&str; 2] = ["/api/register", "/api/auth"];
|
pub const IGNORE_ROUTES: [&str; 3] = ["/api/register", "/api/auth", "/ws"];
|
||||||
|
@ -32,7 +32,7 @@ impl Claim {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_user_id(self) -> String { self.user_id }
|
pub fn user_id(self) -> String { self.user_id }
|
||||||
}
|
}
|
||||||
|
|
||||||
// impl From<Claim> for User {
|
// impl From<Claim> for User {
|
||||||
|
@ -56,6 +56,7 @@ where
|
|||||||
fn call(&self, req: ServiceRequest) -> Self::Future {
|
fn call(&self, req: ServiceRequest) -> Self::Future {
|
||||||
let mut authenticate_pass: bool = false;
|
let mut authenticate_pass: bool = false;
|
||||||
for ignore_route in IGNORE_ROUTES.iter() {
|
for ignore_route in IGNORE_ROUTES.iter() {
|
||||||
|
log::info!("ignore: {}, path: {}", ignore_route, req.path());
|
||||||
if req.path().starts_with(ignore_route) {
|
if req.path().starts_with(ignore_route) {
|
||||||
authenticate_pass = true;
|
authenticate_pass = true;
|
||||||
break;
|
break;
|
||||||
@ -68,7 +69,6 @@ where
|
|||||||
match result {
|
match result {
|
||||||
Ok(logged_user) => {
|
Ok(logged_user) => {
|
||||||
authenticate_pass = AUTHORIZED_USERS.is_authorized(&logged_user);
|
authenticate_pass = AUTHORIZED_USERS.is_authorized(&logged_user);
|
||||||
|
|
||||||
// Update user timestamp
|
// Update user timestamp
|
||||||
AUTHORIZED_USERS.store_auth(logged_user, true);
|
AUTHORIZED_USERS.store_auth(logged_user, true);
|
||||||
},
|
},
|
||||||
|
@ -49,7 +49,7 @@ pub async fn sign_in(pool: &PgPool, params: SignInParams) -> Result<SignInRespon
|
|||||||
let token = Token::create_token(&user.id.to_string())?;
|
let token = Token::create_token(&user.id.to_string())?;
|
||||||
let logged_user = LoggedUser::new(&user.id.to_string());
|
let logged_user = LoggedUser::new(&user.id.to_string());
|
||||||
|
|
||||||
let _ = AUTHORIZED_USERS.store_auth(logged_user, true)?;
|
AUTHORIZED_USERS.store_auth(logged_user, true);
|
||||||
let mut response_data = SignInResponse::default();
|
let mut response_data = SignInResponse::default();
|
||||||
response_data.set_user_id(user.id.to_string());
|
response_data.set_user_id(user.id.to_string());
|
||||||
response_data.set_name(user.name);
|
response_data.set_name(user.name);
|
||||||
@ -60,7 +60,7 @@ pub async fn sign_in(pool: &PgPool, params: SignInParams) -> Result<SignInRespon
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn sign_out(logged_user: LoggedUser) -> Result<FlowyResponse, ServerError> {
|
pub async fn sign_out(logged_user: LoggedUser) -> Result<FlowyResponse, ServerError> {
|
||||||
let _ = AUTHORIZED_USERS.store_auth(logged_user, false)?;
|
AUTHORIZED_USERS.store_auth(logged_user, false);
|
||||||
Ok(FlowyResponse::success())
|
Ok(FlowyResponse::success())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ pub async fn register_user(
|
|||||||
.context("Failed to insert user")?;
|
.context("Failed to insert user")?;
|
||||||
|
|
||||||
let logged_user = LoggedUser::new(&response_data.user_id);
|
let logged_user = LoggedUser::new(&response_data.user_id);
|
||||||
let _ = AUTHORIZED_USERS.store_auth(logged_user, true)?;
|
AUTHORIZED_USERS.store_auth(logged_user, true);
|
||||||
let _ = create_default_workspace(&mut transaction, response_data.get_user_id()).await?;
|
let _ = create_default_workspace(&mut transaction, response_data.get_user_id()).await?;
|
||||||
|
|
||||||
transaction
|
transaction
|
||||||
@ -112,7 +112,7 @@ pub(crate) async fn get_user_profile(
|
|||||||
.await
|
.await
|
||||||
.context("Failed to acquire a Postgres connection to get user detail")?;
|
.context("Failed to acquire a Postgres connection to get user detail")?;
|
||||||
|
|
||||||
let id = logged_user.get_user_id()?;
|
let id = logged_user.as_uuid()?;
|
||||||
let user_table =
|
let user_table =
|
||||||
sqlx::query_as::<Postgres, UserTable>("SELECT * FROM user_table WHERE id = $1")
|
sqlx::query_as::<Postgres, UserTable>("SELECT * FROM user_table WHERE id = $1")
|
||||||
.bind(id)
|
.bind(id)
|
||||||
@ -126,7 +126,7 @@ pub(crate) async fn get_user_profile(
|
|||||||
.context("Failed to commit SQL transaction to get user detail.")?;
|
.context("Failed to commit SQL transaction to get user detail.")?;
|
||||||
|
|
||||||
// update the user active time
|
// update the user active time
|
||||||
let _ = AUTHORIZED_USERS.store_auth(logged_user, true)?;
|
AUTHORIZED_USERS.store_auth(logged_user, true);
|
||||||
|
|
||||||
let mut user_profile = UserProfile::default();
|
let mut user_profile = UserProfile::default();
|
||||||
user_profile.set_id(user_table.id.to_string());
|
user_profile.set_id(user_table.id.to_string());
|
||||||
@ -178,7 +178,7 @@ pub(crate) async fn set_user_profile(
|
|||||||
.add_some_arg("name", name)
|
.add_some_arg("name", name)
|
||||||
.add_some_arg("email", email)
|
.add_some_arg("email", email)
|
||||||
.add_some_arg("password", password)
|
.add_some_arg("password", password)
|
||||||
.and_where_eq("id", &logged_user.get_user_id()?)
|
.and_where_eq("id", &logged_user.as_uuid()?)
|
||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
sqlx::query_with(&sql, args)
|
sqlx::query_with(&sql, args)
|
||||||
|
@ -13,13 +13,13 @@ lazy_static! {
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
|
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
|
||||||
pub struct LoggedUser {
|
pub struct LoggedUser {
|
||||||
user_id: String,
|
pub user_id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::convert::From<Claim> for LoggedUser {
|
impl std::convert::From<Claim> for LoggedUser {
|
||||||
fn from(c: Claim) -> Self {
|
fn from(c: Claim) -> Self {
|
||||||
Self {
|
Self {
|
||||||
user_id: c.get_user_id(),
|
user_id: c.user_id(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -36,7 +36,7 @@ impl LoggedUser {
|
|||||||
Ok(user)
|
Ok(user)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_user_id(&self) -> Result<uuid::Uuid, ServerError> {
|
pub fn as_uuid(&self) -> Result<uuid::Uuid, ServerError> {
|
||||||
let id = uuid::Uuid::parse_str(&self.user_id)?;
|
let id = uuid::Uuid::parse_str(&self.user_id)?;
|
||||||
Ok(id)
|
Ok(id)
|
||||||
}
|
}
|
||||||
@ -106,13 +106,12 @@ impl AuthorizedUsers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn store_auth(&self, user: LoggedUser, is_auth: bool) -> Result<(), ServerError> {
|
pub fn store_auth(&self, user: LoggedUser, is_auth: bool) {
|
||||||
let status = if is_auth {
|
let status = if is_auth {
|
||||||
AuthStatus::Authorized(Utc::now())
|
AuthStatus::Authorized(Utc::now())
|
||||||
} else {
|
} else {
|
||||||
AuthStatus::NotAuthorized
|
AuthStatus::NotAuthorized
|
||||||
};
|
};
|
||||||
self.0.insert(user, status);
|
self.0.insert(user, status);
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ pub(crate) async fn create_app(
|
|||||||
) -> Result<FlowyResponse, ServerError> {
|
) -> Result<FlowyResponse, ServerError> {
|
||||||
let name = AppName::parse(params.take_name()).map_err(invalid_params)?;
|
let name = AppName::parse(params.take_name()).map_err(invalid_params)?;
|
||||||
let workspace_id = WorkspaceId::parse(params.take_workspace_id()).map_err(invalid_params)?;
|
let workspace_id = WorkspaceId::parse(params.take_workspace_id()).map_err(invalid_params)?;
|
||||||
let user_id = logged_user.get_user_id()?.to_string();
|
let user_id = logged_user.as_uuid()?.to_string();
|
||||||
let desc = AppDesc::parse(params.take_desc()).map_err(invalid_params)?;
|
let desc = AppDesc::parse(params.take_desc()).map_err(invalid_params)?;
|
||||||
let mut transaction = pool
|
let mut transaction = pool
|
||||||
.begin()
|
.begin()
|
||||||
|
@ -28,7 +28,7 @@ pub(crate) async fn create_workspace(
|
|||||||
) -> Result<FlowyResponse, ServerError> {
|
) -> Result<FlowyResponse, ServerError> {
|
||||||
let name = WorkspaceName::parse(params.get_name().to_owned()).map_err(invalid_params)?;
|
let name = WorkspaceName::parse(params.get_name().to_owned()).map_err(invalid_params)?;
|
||||||
let desc = WorkspaceDesc::parse(params.get_desc().to_owned()).map_err(invalid_params)?;
|
let desc = WorkspaceDesc::parse(params.get_desc().to_owned()).map_err(invalid_params)?;
|
||||||
let user_id = logged_user.get_user_id()?.to_string();
|
let user_id = logged_user.as_uuid()?.to_string();
|
||||||
|
|
||||||
let mut transaction = pool
|
let mut transaction = pool
|
||||||
.begin()
|
.begin()
|
||||||
@ -134,7 +134,7 @@ pub async fn read_workspaces(
|
|||||||
workspace_id: Option<String>,
|
workspace_id: Option<String>,
|
||||||
logged_user: LoggedUser,
|
logged_user: LoggedUser,
|
||||||
) -> Result<FlowyResponse, ServerError> {
|
) -> Result<FlowyResponse, ServerError> {
|
||||||
let user_id = logged_user.get_user_id()?.to_string();
|
let user_id = logged_user.as_uuid()?.to_string();
|
||||||
let mut transaction = pool
|
let mut transaction = pool
|
||||||
.begin()
|
.begin()
|
||||||
.await
|
.await
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use crate::service::ws_service::{entities::SessionId, WSClient, WSServer};
|
use crate::service::ws_service::{entities::SessionId, WSClient, WSServer};
|
||||||
use actix::Addr;
|
use actix::Addr;
|
||||||
|
|
||||||
|
use crate::service::user_service::LoggedUser;
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
get,
|
get,
|
||||||
web::{Data, Path, Payload},
|
web::{Data, Path, Payload},
|
||||||
@ -14,17 +15,30 @@ use actix_web_actors::ws;
|
|||||||
pub async fn establish_ws_connection(
|
pub async fn establish_ws_connection(
|
||||||
request: HttpRequest,
|
request: HttpRequest,
|
||||||
payload: Payload,
|
payload: Payload,
|
||||||
path: Path<String>,
|
token: Path<String>,
|
||||||
server: Data<Addr<WSServer>>,
|
server: Data<Addr<WSServer>>,
|
||||||
) -> Result<HttpResponse, Error> {
|
) -> Result<HttpResponse, Error> {
|
||||||
let client = WSClient::new(SessionId::new(path.clone()), server.get_ref().clone());
|
match LoggedUser::from_token(token.clone()) {
|
||||||
let result = ws::start(client, &request, payload);
|
Ok(user) => {
|
||||||
|
let client = WSClient::new(
|
||||||
match result {
|
SessionId::new(user.user_id.clone()),
|
||||||
Ok(response) => Ok(response.into()),
|
server.get_ref().clone(),
|
||||||
|
);
|
||||||
|
let result = ws::start(client, &request, payload);
|
||||||
|
match result {
|
||||||
|
Ok(response) => Ok(response.into()),
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("ws connection error: {:?}", e);
|
||||||
|
Err(e)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("ws connection error: {:?}", e);
|
if e.is_unauthorized() {
|
||||||
Err(e)
|
Ok(HttpResponse::Unauthorized().json(e))
|
||||||
|
} else {
|
||||||
|
Ok(HttpResponse::BadRequest().json(e))
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,6 +179,10 @@ impl TestServer {
|
|||||||
let response = user_sign_up_request(params, &url).await.unwrap();
|
let response = user_sign_up_request(params, &url).await.unwrap();
|
||||||
response
|
response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn ws_addr(&self) -> String {
|
||||||
|
format!("{}/ws/{}", self.address, self.user_token.as_ref().unwrap())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pub async fn spawn_server() -> TestServer {
|
pub async fn spawn_server() -> TestServer {
|
||||||
let database_name = format!("{}", Uuid::new_v4().to_string());
|
let database_name = format!("{}", Uuid::new_v4().to_string());
|
||||||
|
@ -2,3 +2,4 @@ mod auth;
|
|||||||
mod doc;
|
mod doc;
|
||||||
mod helper;
|
mod helper;
|
||||||
mod workspace;
|
mod workspace;
|
||||||
|
mod ws;
|
||||||
|
10
backend/tests/api/ws.rs
Normal file
10
backend/tests/api/ws.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
use crate::helper::TestServer;
|
||||||
|
use flowy_ws::WsController;
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn ws_connect() {
|
||||||
|
let server = TestServer::new().await;
|
||||||
|
let mut controller = WsController::new();
|
||||||
|
let addr = server.ws_addr();
|
||||||
|
let _ = controller.connect(addr).await.unwrap();
|
||||||
|
}
|
@ -20,8 +20,7 @@ byteorder = {version = "1.3.4"}
|
|||||||
ffi-support = {version = "0.4.2"}
|
ffi-support = {version = "0.4.2"}
|
||||||
protobuf = {version = "2.20.0"}
|
protobuf = {version = "2.20.0"}
|
||||||
lazy_static = {version = "1.4.0"}
|
lazy_static = {version = "1.4.0"}
|
||||||
#tokio = { version = "1", features = ["rt", "rt-multi-thread"] }
|
tokio = { version = "1", features = ["rt", "rt-multi-thread"] }
|
||||||
tokio = { version = "1", features = ["full"] }
|
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = {version = "1.0"}
|
serde_json = {version = "1.0"}
|
||||||
|
@ -80,7 +80,6 @@ pub fn category_from_str(type_str: &str) -> TypeCategory {
|
|||||||
| "WorkspaceObservable"
|
| "WorkspaceObservable"
|
||||||
| "DocObservable"
|
| "DocObservable"
|
||||||
| "FFIStatusCode"
|
| "FFIStatusCode"
|
||||||
| "UserStatus"
|
|
||||||
| "UserEvent"
|
| "UserEvent"
|
||||||
| "UserObservable"
|
| "UserObservable"
|
||||||
=> TypeCategory::Enum,
|
=> TypeCategory::Enum,
|
||||||
|
@ -4,7 +4,7 @@ use tokio::runtime;
|
|||||||
|
|
||||||
pub mod ready;
|
pub mod ready;
|
||||||
|
|
||||||
pub(crate) fn tokio_default_runtime() -> io::Result<tokio::runtime::Runtime> {
|
pub fn tokio_default_runtime() -> io::Result<tokio::runtime::Runtime> {
|
||||||
runtime::Builder::new_multi_thread()
|
runtime::Builder::new_multi_thread()
|
||||||
.thread_name("flowy-rt")
|
.thread_name("flowy-rt")
|
||||||
.enable_io()
|
.enable_io()
|
||||||
|
@ -1,16 +0,0 @@
|
|||||||
#[rustfmt::skip]
|
|
||||||
use flowy_dispatch::prelude::*;
|
|
||||||
use std::sync::Once;
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn setup_env() {
|
|
||||||
static INIT: Once = Once::new();
|
|
||||||
(|| env_logger::init());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init_dispatch<F>(module_factory: F) -> EventDispatch
|
|
||||||
where
|
|
||||||
F: FnOnce() -> Vec<Module>,
|
|
||||||
{
|
|
||||||
EventDispatch::construct(module_factory)
|
|
||||||
}
|
|
@ -1,2 +1 @@
|
|||||||
mod helper;
|
|
||||||
mod module;
|
mod module;
|
||||||
|
@ -6,9 +6,10 @@ pub async fn hello() -> String { "say hello".to_string() }
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test() {
|
async fn test() {
|
||||||
setup_env();
|
env_logger::init();
|
||||||
|
|
||||||
let event = "1";
|
let event = "1";
|
||||||
let dispatch = Arc::new(init_dispatch(|| vec![Module::new().event(event, hello)]));
|
let dispatch = Arc::new(EventDispatch::construct(|| vec![Module::new().event(event, hello)]));
|
||||||
let request = ModuleRequest::new(event);
|
let request = ModuleRequest::new(event);
|
||||||
let _ = EventDispatch::async_send_with_callback(dispatch.clone(), request, |resp| {
|
let _ = EventDispatch::async_send_with_callback(dispatch.clone(), request, |resp| {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
|
@ -13,12 +13,12 @@ flowy-infra = { path = "../flowy-infra" }
|
|||||||
flowy-workspace = { path = "../flowy-workspace" }
|
flowy-workspace = { path = "../flowy-workspace" }
|
||||||
flowy-database = { path = "../flowy-database" }
|
flowy-database = { path = "../flowy-database" }
|
||||||
flowy-document = { path = "../flowy-document" }
|
flowy-document = { path = "../flowy-document" }
|
||||||
flowy-ws = { path = "../flowy-ws" }
|
|
||||||
tracing = { version = "0.1" }
|
tracing = { version = "0.1" }
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
futures-core = { version = "0.3", default-features = false }
|
futures-core = { version = "0.3", default-features = false }
|
||||||
color-eyre = { version = "0.5", default-features = false }
|
color-eyre = { version = "0.5", default-features = false }
|
||||||
bytes = "1.0"
|
bytes = "1.0"
|
||||||
|
tokio = { version = "1", features = ["rt"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
@ -3,7 +3,6 @@ mod deps_resolve;
|
|||||||
pub mod module;
|
pub mod module;
|
||||||
|
|
||||||
use flowy_dispatch::prelude::*;
|
use flowy_dispatch::prelude::*;
|
||||||
use flowy_ws::start_ws_connection;
|
|
||||||
use module::build_modules;
|
use module::build_modules;
|
||||||
pub use module::*;
|
pub use module::*;
|
||||||
use std::sync::{
|
use std::sync::{
|
||||||
@ -88,9 +87,5 @@ fn init_log(config: &FlowySDKConfig) {
|
|||||||
fn init_dispatch(root: &str) -> EventDispatch {
|
fn init_dispatch(root: &str) -> EventDispatch {
|
||||||
let config = ModuleConfig { root: root.to_owned() };
|
let config = ModuleConfig { root: root.to_owned() };
|
||||||
let dispatch = EventDispatch::construct(|| build_modules(config));
|
let dispatch = EventDispatch::construct(|| build_modules(config));
|
||||||
|
|
||||||
dispatch.spawn(async {
|
|
||||||
start_ws_connection();
|
|
||||||
});
|
|
||||||
dispatch
|
dispatch
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,10 @@ pub struct ModuleConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_modules(config: ModuleConfig) -> Vec<Module> {
|
pub fn build_modules(config: ModuleConfig) -> Vec<Module> {
|
||||||
|
// runtime.spawn(async move {
|
||||||
|
// start_ws_connection("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
|
||||||
|
// eyJpc3MiOiJsb2NhbGhvc3QiLCJzdWIiOiJhdXRoIiwiaWF0IjoxNjMxNzcwODQ2LCJleHAiOjE2MzIyMDI4NDYsInVzZXJfaWQiOiI5ZmFiN2I4MS1mZDAyLTRhN2EtYjA4Zi05NDM3NTdmZmE5MDcifQ.
|
||||||
|
// UzV01tHnWEZWBp3nJPTmFi7ypxBoCe56AjEPb9bnsFE") });
|
||||||
let user_session = Arc::new(UserSessionBuilder::new().root_dir(&config.root).build());
|
let user_session = Arc::new(UserSessionBuilder::new().root_dir(&config.root).build());
|
||||||
|
|
||||||
let workspace_user_impl = Arc::new(WorkspaceUserImpl {
|
let workspace_user_impl = Arc::new(WorkspaceUserImpl {
|
||||||
|
@ -13,6 +13,7 @@ flowy-database = { path = "../flowy-database" }
|
|||||||
flowy-sqlite = { path = "../flowy-sqlite" }
|
flowy-sqlite = { path = "../flowy-sqlite" }
|
||||||
flowy-infra = { path = "../flowy-infra" }
|
flowy-infra = { path = "../flowy-infra" }
|
||||||
flowy-net = { path = "../flowy-net", features = ["flowy_request"] }
|
flowy-net = { path = "../flowy-net", features = ["flowy_request"] }
|
||||||
|
flowy-ws = { path = "../flowy-ws"}
|
||||||
flowy-observable = { path = "../flowy-observable" }
|
flowy-observable = { path = "../flowy-observable" }
|
||||||
|
|
||||||
tracing = { version = "0.1", features = ["log"] }
|
tracing = { version = "0.1", features = ["log"] }
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
|
use flowy_derive::ProtoBuf;
|
||||||
|
|
||||||
#[derive(Default, ProtoBuf)]
|
#[derive(Default, ProtoBuf)]
|
||||||
pub struct UserToken {
|
pub struct UserToken {
|
||||||
@ -6,17 +6,6 @@ pub struct UserToken {
|
|||||||
pub token: String,
|
pub token: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, ProtoBuf_Enum)]
|
|
||||||
pub enum UserStatus {
|
|
||||||
Unknown = 0,
|
|
||||||
Login = 1,
|
|
||||||
Expired = 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::default::Default for UserStatus {
|
|
||||||
fn default() -> Self { UserStatus::Unknown }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(ProtoBuf, Default, Debug, PartialEq, Eq, Clone)]
|
#[derive(ProtoBuf, Default, Debug, PartialEq, Eq, Clone)]
|
||||||
pub struct UserProfile {
|
pub struct UserProfile {
|
||||||
#[pb(index = 1)]
|
#[pb(index = 1)]
|
||||||
|
@ -5,7 +5,7 @@ use strum_macros::Display;
|
|||||||
#[event_err = "UserError"]
|
#[event_err = "UserError"]
|
||||||
pub enum UserEvent {
|
pub enum UserEvent {
|
||||||
#[event(output = "UserProfile")]
|
#[event(output = "UserProfile")]
|
||||||
GetUserProfile = 0,
|
InitUser = 0,
|
||||||
|
|
||||||
#[event(input = "SignInRequest", output = "UserProfile")]
|
#[event(input = "SignInRequest", output = "UserProfile")]
|
||||||
SignIn = 1,
|
SignIn = 1,
|
||||||
@ -18,4 +18,7 @@ pub enum UserEvent {
|
|||||||
|
|
||||||
#[event(input = "UpdateUserRequest")]
|
#[event(input = "UpdateUserRequest")]
|
||||||
UpdateUser = 4,
|
UpdateUser = 4,
|
||||||
|
|
||||||
|
#[event(output = "UserProfile")]
|
||||||
|
GetUserProfile = 5,
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,14 @@ use flowy_dispatch::prelude::*;
|
|||||||
|
|
||||||
use std::{convert::TryInto, sync::Arc};
|
use std::{convert::TryInto, sync::Arc};
|
||||||
|
|
||||||
#[tracing::instrument(name = "get_profile", skip(session))]
|
#[tracing::instrument(skip(session))]
|
||||||
pub async fn user_profile_handler(session: Unit<Arc<UserSession>>) -> DataResult<UserProfile, UserError> {
|
pub async fn init_user_handler(session: Unit<Arc<UserSession>>) -> DataResult<UserProfile, UserError> {
|
||||||
|
let user_profile = session.init_user().await?;
|
||||||
|
data_result(user_profile)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(skip(session))]
|
||||||
|
pub async fn get_user_profile_handler(session: Unit<Arc<UserSession>>) -> DataResult<UserProfile, UserError> {
|
||||||
let user_profile = session.user_profile().await?;
|
let user_profile = session.user_profile().await?;
|
||||||
data_result(user_profile)
|
data_result(user_profile)
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,8 @@ pub fn create(user_session: Arc<UserSession>) -> Module {
|
|||||||
.data(user_session)
|
.data(user_session)
|
||||||
.event(UserEvent::SignIn, sign_in)
|
.event(UserEvent::SignIn, sign_in)
|
||||||
.event(UserEvent::SignUp, sign_up)
|
.event(UserEvent::SignUp, sign_up)
|
||||||
.event(UserEvent::GetUserProfile, user_profile_handler)
|
.event(UserEvent::InitUser, init_user_handler)
|
||||||
|
.event(UserEvent::GetUserProfile, get_user_profile_handler)
|
||||||
.event(UserEvent::SignOut, sign_out)
|
.event(UserEvent::SignOut, sign_out)
|
||||||
.event(UserEvent::UpdateUser, update_user_handler)
|
.event(UserEvent::UpdateUser, update_user_handler)
|
||||||
}
|
}
|
||||||
|
@ -25,11 +25,12 @@
|
|||||||
|
|
||||||
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
|
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
|
||||||
pub enum UserEvent {
|
pub enum UserEvent {
|
||||||
GetUserProfile = 0,
|
InitUser = 0,
|
||||||
SignIn = 1,
|
SignIn = 1,
|
||||||
SignUp = 2,
|
SignUp = 2,
|
||||||
SignOut = 3,
|
SignOut = 3,
|
||||||
UpdateUser = 4,
|
UpdateUser = 4,
|
||||||
|
GetUserProfile = 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::protobuf::ProtobufEnum for UserEvent {
|
impl ::protobuf::ProtobufEnum for UserEvent {
|
||||||
@ -39,22 +40,24 @@ impl ::protobuf::ProtobufEnum for UserEvent {
|
|||||||
|
|
||||||
fn from_i32(value: i32) -> ::std::option::Option<UserEvent> {
|
fn from_i32(value: i32) -> ::std::option::Option<UserEvent> {
|
||||||
match value {
|
match value {
|
||||||
0 => ::std::option::Option::Some(UserEvent::GetUserProfile),
|
0 => ::std::option::Option::Some(UserEvent::InitUser),
|
||||||
1 => ::std::option::Option::Some(UserEvent::SignIn),
|
1 => ::std::option::Option::Some(UserEvent::SignIn),
|
||||||
2 => ::std::option::Option::Some(UserEvent::SignUp),
|
2 => ::std::option::Option::Some(UserEvent::SignUp),
|
||||||
3 => ::std::option::Option::Some(UserEvent::SignOut),
|
3 => ::std::option::Option::Some(UserEvent::SignOut),
|
||||||
4 => ::std::option::Option::Some(UserEvent::UpdateUser),
|
4 => ::std::option::Option::Some(UserEvent::UpdateUser),
|
||||||
|
5 => ::std::option::Option::Some(UserEvent::GetUserProfile),
|
||||||
_ => ::std::option::Option::None
|
_ => ::std::option::Option::None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn values() -> &'static [Self] {
|
fn values() -> &'static [Self] {
|
||||||
static values: &'static [UserEvent] = &[
|
static values: &'static [UserEvent] = &[
|
||||||
UserEvent::GetUserProfile,
|
UserEvent::InitUser,
|
||||||
UserEvent::SignIn,
|
UserEvent::SignIn,
|
||||||
UserEvent::SignUp,
|
UserEvent::SignUp,
|
||||||
UserEvent::SignOut,
|
UserEvent::SignOut,
|
||||||
UserEvent::UpdateUser,
|
UserEvent::UpdateUser,
|
||||||
|
UserEvent::GetUserProfile,
|
||||||
];
|
];
|
||||||
values
|
values
|
||||||
}
|
}
|
||||||
@ -72,7 +75,7 @@ impl ::std::marker::Copy for UserEvent {
|
|||||||
|
|
||||||
impl ::std::default::Default for UserEvent {
|
impl ::std::default::Default for UserEvent {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
UserEvent::GetUserProfile
|
UserEvent::InitUser
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,21 +86,24 @@ impl ::protobuf::reflect::ProtobufValue for UserEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static file_descriptor_proto_data: &'static [u8] = b"\
|
static file_descriptor_proto_data: &'static [u8] = b"\
|
||||||
\n\x0bevent.proto*T\n\tUserEvent\x12\x12\n\x0eGetUserProfile\x10\0\x12\n\
|
\n\x0bevent.proto*b\n\tUserEvent\x12\x0c\n\x08InitUser\x10\0\x12\n\n\x06\
|
||||||
\n\x06SignIn\x10\x01\x12\n\n\x06SignUp\x10\x02\x12\x0b\n\x07SignOut\x10\
|
SignIn\x10\x01\x12\n\n\x06SignUp\x10\x02\x12\x0b\n\x07SignOut\x10\x03\
|
||||||
\x03\x12\x0e\n\nUpdateUser\x10\x04J\xf7\x01\n\x06\x12\x04\0\0\x08\x01\n\
|
\x12\x0e\n\nUpdateUser\x10\x04\x12\x12\n\x0eGetUserProfile\x10\x05J\xa0\
|
||||||
\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x05\0\x12\x04\x02\0\x08\x01\n\n\
|
\x02\n\x06\x12\x04\0\0\t\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\
|
||||||
\n\x03\x05\0\x01\x12\x03\x02\x05\x0e\n\x0b\n\x04\x05\0\x02\0\x12\x03\x03\
|
\x05\0\x12\x04\x02\0\t\x01\n\n\n\x03\x05\0\x01\x12\x03\x02\x05\x0e\n\x0b\
|
||||||
\x04\x17\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x03\x04\x12\n\x0c\n\x05\x05\
|
\n\x04\x05\0\x02\0\x12\x03\x03\x04\x11\n\x0c\n\x05\x05\0\x02\0\x01\x12\
|
||||||
\0\x02\0\x02\x12\x03\x03\x15\x16\n\x0b\n\x04\x05\0\x02\x01\x12\x03\x04\
|
\x03\x03\x04\x0c\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x03\x0f\x10\n\x0b\n\
|
||||||
\x04\x0f\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x04\x04\n\n\x0c\n\x05\x05\
|
\x04\x05\0\x02\x01\x12\x03\x04\x04\x0f\n\x0c\n\x05\x05\0\x02\x01\x01\x12\
|
||||||
\0\x02\x01\x02\x12\x03\x04\r\x0e\n\x0b\n\x04\x05\0\x02\x02\x12\x03\x05\
|
\x03\x04\x04\n\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x04\r\x0e\n\x0b\n\
|
||||||
\x04\x0f\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\x05\x04\n\n\x0c\n\x05\x05\
|
\x04\x05\0\x02\x02\x12\x03\x05\x04\x0f\n\x0c\n\x05\x05\0\x02\x02\x01\x12\
|
||||||
\0\x02\x02\x02\x12\x03\x05\r\x0e\n\x0b\n\x04\x05\0\x02\x03\x12\x03\x06\
|
\x03\x05\x04\n\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\x05\r\x0e\n\x0b\n\
|
||||||
\x04\x10\n\x0c\n\x05\x05\0\x02\x03\x01\x12\x03\x06\x04\x0b\n\x0c\n\x05\
|
\x04\x05\0\x02\x03\x12\x03\x06\x04\x10\n\x0c\n\x05\x05\0\x02\x03\x01\x12\
|
||||||
\x05\0\x02\x03\x02\x12\x03\x06\x0e\x0f\n\x0b\n\x04\x05\0\x02\x04\x12\x03\
|
\x03\x06\x04\x0b\n\x0c\n\x05\x05\0\x02\x03\x02\x12\x03\x06\x0e\x0f\n\x0b\
|
||||||
\x07\x04\x13\n\x0c\n\x05\x05\0\x02\x04\x01\x12\x03\x07\x04\x0e\n\x0c\n\
|
\n\x04\x05\0\x02\x04\x12\x03\x07\x04\x13\n\x0c\n\x05\x05\0\x02\x04\x01\
|
||||||
\x05\x05\0\x02\x04\x02\x12\x03\x07\x11\x12b\x06proto3\
|
\x12\x03\x07\x04\x0e\n\x0c\n\x05\x05\0\x02\x04\x02\x12\x03\x07\x11\x12\n\
|
||||||
|
\x0b\n\x04\x05\0\x02\x05\x12\x03\x08\x04\x17\n\x0c\n\x05\x05\0\x02\x05\
|
||||||
|
\x01\x12\x03\x08\x04\x12\n\x0c\n\x05\x05\0\x02\x05\x02\x12\x03\x08\x15\
|
||||||
|
\x16b\x06proto3\
|
||||||
";
|
";
|
||||||
|
|
||||||
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
||||||
|
@ -1273,59 +1273,6 @@ impl ::protobuf::reflect::ProtobufValue for UpdateUserParams {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
|
|
||||||
pub enum UserStatus {
|
|
||||||
Unknown = 0,
|
|
||||||
Login = 1,
|
|
||||||
Expired = 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ::protobuf::ProtobufEnum for UserStatus {
|
|
||||||
fn value(&self) -> i32 {
|
|
||||||
*self as i32
|
|
||||||
}
|
|
||||||
|
|
||||||
fn from_i32(value: i32) -> ::std::option::Option<UserStatus> {
|
|
||||||
match value {
|
|
||||||
0 => ::std::option::Option::Some(UserStatus::Unknown),
|
|
||||||
1 => ::std::option::Option::Some(UserStatus::Login),
|
|
||||||
2 => ::std::option::Option::Some(UserStatus::Expired),
|
|
||||||
_ => ::std::option::Option::None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn values() -> &'static [Self] {
|
|
||||||
static values: &'static [UserStatus] = &[
|
|
||||||
UserStatus::Unknown,
|
|
||||||
UserStatus::Login,
|
|
||||||
UserStatus::Expired,
|
|
||||||
];
|
|
||||||
values
|
|
||||||
}
|
|
||||||
|
|
||||||
fn enum_descriptor_static() -> &'static ::protobuf::reflect::EnumDescriptor {
|
|
||||||
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::LazyV2::INIT;
|
|
||||||
descriptor.get(|| {
|
|
||||||
::protobuf::reflect::EnumDescriptor::new_pb_name::<UserStatus>("UserStatus", file_descriptor_proto())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ::std::marker::Copy for UserStatus {
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ::std::default::Default for UserStatus {
|
|
||||||
fn default() -> Self {
|
|
||||||
UserStatus::Unknown
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ::protobuf::reflect::ProtobufValue for UserStatus {
|
|
||||||
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
|
|
||||||
::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static file_descriptor_proto_data: &'static [u8] = b"\
|
static file_descriptor_proto_data: &'static [u8] = b"\
|
||||||
\n\x12user_profile.proto\"!\n\tUserToken\x12\x14\n\x05token\x18\x01\x20\
|
\n\x12user_profile.proto\"!\n\tUserToken\x12\x14\n\x05token\x18\x01\x20\
|
||||||
\x01(\tR\x05token\"]\n\x0bUserProfile\x12\x0e\n\x02id\x18\x01\x20\x01(\t\
|
\x01(\tR\x05token\"]\n\x0bUserProfile\x12\x0e\n\x02id\x18\x01\x20\x01(\t\
|
||||||
@ -1339,64 +1286,56 @@ static file_descriptor_proto_data: &'static [u8] = b"\
|
|||||||
id\x18\x01\x20\x01(\tR\x02id\x12\x14\n\x04name\x18\x02\x20\x01(\tH\0R\
|
id\x18\x01\x20\x01(\tR\x02id\x12\x14\n\x04name\x18\x02\x20\x01(\tH\0R\
|
||||||
\x04name\x12\x16\n\x05email\x18\x03\x20\x01(\tH\x01R\x05email\x12\x1c\n\
|
\x04name\x12\x16\n\x05email\x18\x03\x20\x01(\tH\x01R\x05email\x12\x1c\n\
|
||||||
\x08password\x18\x04\x20\x01(\tH\x02R\x08passwordB\r\n\x0bone_of_nameB\
|
\x08password\x18\x04\x20\x01(\tH\x02R\x08passwordB\r\n\x0bone_of_nameB\
|
||||||
\x0e\n\x0cone_of_emailB\x11\n\x0fone_of_password*1\n\nUserStatus\x12\x0b\
|
\x0e\n\x0cone_of_emailB\x11\n\x0fone_of_passwordJ\xdf\x07\n\x06\x12\x04\
|
||||||
\n\x07Unknown\x10\0\x12\t\n\x05Login\x10\x01\x12\x0b\n\x07Expired\x10\
|
\0\0\x16\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\
|
||||||
\x02J\xf2\x08\n\x06\x12\x04\0\0\x1b\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\
|
\0\x04\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x11\n\x0b\n\x04\x04\0\x02\
|
||||||
\n\n\n\x02\x04\0\x12\x04\x02\0\x04\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\
|
\0\x12\x03\x03\x04\x15\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\
|
||||||
\x08\x11\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\x15\n\x0c\n\x05\x04\0\
|
\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x0b\x10\n\x0c\n\x05\x04\0\x02\0\
|
||||||
\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x0b\
|
\x03\x12\x03\x03\x13\x14\n\n\n\x02\x04\x01\x12\x04\x05\0\n\x01\n\n\n\x03\
|
||||||
\x10\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x13\x14\n\n\n\x02\x04\x01\
|
\x04\x01\x01\x12\x03\x05\x08\x13\n\x0b\n\x04\x04\x01\x02\0\x12\x03\x06\
|
||||||
\x12\x04\x05\0\n\x01\n\n\n\x03\x04\x01\x01\x12\x03\x05\x08\x13\n\x0b\n\
|
\x04\x12\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\x06\x04\n\n\x0c\n\x05\x04\
|
||||||
\x04\x04\x01\x02\0\x12\x03\x06\x04\x12\n\x0c\n\x05\x04\x01\x02\0\x05\x12\
|
\x01\x02\0\x01\x12\x03\x06\x0b\r\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\
|
||||||
\x03\x06\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\x06\x0b\r\n\x0c\n\
|
\x06\x10\x11\n\x0b\n\x04\x04\x01\x02\x01\x12\x03\x07\x04\x15\n\x0c\n\x05\
|
||||||
\x05\x04\x01\x02\0\x03\x12\x03\x06\x10\x11\n\x0b\n\x04\x04\x01\x02\x01\
|
\x04\x01\x02\x01\x05\x12\x03\x07\x04\n\n\x0c\n\x05\x04\x01\x02\x01\x01\
|
||||||
\x12\x03\x07\x04\x15\n\x0c\n\x05\x04\x01\x02\x01\x05\x12\x03\x07\x04\n\n\
|
\x12\x03\x07\x0b\x10\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x03\x07\x13\x14\
|
||||||
\x0c\n\x05\x04\x01\x02\x01\x01\x12\x03\x07\x0b\x10\n\x0c\n\x05\x04\x01\
|
\n\x0b\n\x04\x04\x01\x02\x02\x12\x03\x08\x04\x14\n\x0c\n\x05\x04\x01\x02\
|
||||||
\x02\x01\x03\x12\x03\x07\x13\x14\n\x0b\n\x04\x04\x01\x02\x02\x12\x03\x08\
|
\x02\x05\x12\x03\x08\x04\n\n\x0c\n\x05\x04\x01\x02\x02\x01\x12\x03\x08\
|
||||||
\x04\x14\n\x0c\n\x05\x04\x01\x02\x02\x05\x12\x03\x08\x04\n\n\x0c\n\x05\
|
\x0b\x0f\n\x0c\n\x05\x04\x01\x02\x02\x03\x12\x03\x08\x12\x13\n\x0b\n\x04\
|
||||||
\x04\x01\x02\x02\x01\x12\x03\x08\x0b\x0f\n\x0c\n\x05\x04\x01\x02\x02\x03\
|
\x04\x01\x02\x03\x12\x03\t\x04\x15\n\x0c\n\x05\x04\x01\x02\x03\x05\x12\
|
||||||
\x12\x03\x08\x12\x13\n\x0b\n\x04\x04\x01\x02\x03\x12\x03\t\x04\x15\n\x0c\
|
\x03\t\x04\n\n\x0c\n\x05\x04\x01\x02\x03\x01\x12\x03\t\x0b\x10\n\x0c\n\
|
||||||
\n\x05\x04\x01\x02\x03\x05\x12\x03\t\x04\n\n\x0c\n\x05\x04\x01\x02\x03\
|
\x05\x04\x01\x02\x03\x03\x12\x03\t\x13\x14\n\n\n\x02\x04\x02\x12\x04\x0b\
|
||||||
\x01\x12\x03\t\x0b\x10\n\x0c\n\x05\x04\x01\x02\x03\x03\x12\x03\t\x13\x14\
|
\0\x10\x01\n\n\n\x03\x04\x02\x01\x12\x03\x0b\x08\x19\n\x0b\n\x04\x04\x02\
|
||||||
\n\n\n\x02\x04\x02\x12\x04\x0b\0\x10\x01\n\n\n\x03\x04\x02\x01\x12\x03\
|
\x02\0\x12\x03\x0c\x04\x12\n\x0c\n\x05\x04\x02\x02\0\x05\x12\x03\x0c\x04\
|
||||||
\x0b\x08\x19\n\x0b\n\x04\x04\x02\x02\0\x12\x03\x0c\x04\x12\n\x0c\n\x05\
|
\n\n\x0c\n\x05\x04\x02\x02\0\x01\x12\x03\x0c\x0b\r\n\x0c\n\x05\x04\x02\
|
||||||
\x04\x02\x02\0\x05\x12\x03\x0c\x04\n\n\x0c\n\x05\x04\x02\x02\0\x01\x12\
|
\x02\0\x03\x12\x03\x0c\x10\x11\n\x0b\n\x04\x04\x02\x08\0\x12\x03\r\x04*\
|
||||||
\x03\x0c\x0b\r\n\x0c\n\x05\x04\x02\x02\0\x03\x12\x03\x0c\x10\x11\n\x0b\n\
|
\n\x0c\n\x05\x04\x02\x08\0\x01\x12\x03\r\n\x15\n\x0b\n\x04\x04\x02\x02\
|
||||||
\x04\x04\x02\x08\0\x12\x03\r\x04*\n\x0c\n\x05\x04\x02\x08\0\x01\x12\x03\
|
\x01\x12\x03\r\x18(\n\x0c\n\x05\x04\x02\x02\x01\x05\x12\x03\r\x18\x1e\n\
|
||||||
\r\n\x15\n\x0b\n\x04\x04\x02\x02\x01\x12\x03\r\x18(\n\x0c\n\x05\x04\x02\
|
\x0c\n\x05\x04\x02\x02\x01\x01\x12\x03\r\x1f#\n\x0c\n\x05\x04\x02\x02\
|
||||||
\x02\x01\x05\x12\x03\r\x18\x1e\n\x0c\n\x05\x04\x02\x02\x01\x01\x12\x03\r\
|
\x01\x03\x12\x03\r&'\n\x0b\n\x04\x04\x02\x08\x01\x12\x03\x0e\x04,\n\x0c\
|
||||||
\x1f#\n\x0c\n\x05\x04\x02\x02\x01\x03\x12\x03\r&'\n\x0b\n\x04\x04\x02\
|
\n\x05\x04\x02\x08\x01\x01\x12\x03\x0e\n\x16\n\x0b\n\x04\x04\x02\x02\x02\
|
||||||
\x08\x01\x12\x03\x0e\x04,\n\x0c\n\x05\x04\x02\x08\x01\x01\x12\x03\x0e\n\
|
\x12\x03\x0e\x19*\n\x0c\n\x05\x04\x02\x02\x02\x05\x12\x03\x0e\x19\x1f\n\
|
||||||
\x16\n\x0b\n\x04\x04\x02\x02\x02\x12\x03\x0e\x19*\n\x0c\n\x05\x04\x02\
|
\x0c\n\x05\x04\x02\x02\x02\x01\x12\x03\x0e\x20%\n\x0c\n\x05\x04\x02\x02\
|
||||||
\x02\x02\x05\x12\x03\x0e\x19\x1f\n\x0c\n\x05\x04\x02\x02\x02\x01\x12\x03\
|
\x02\x03\x12\x03\x0e()\n\x0b\n\x04\x04\x02\x08\x02\x12\x03\x0f\x042\n\
|
||||||
\x0e\x20%\n\x0c\n\x05\x04\x02\x02\x02\x03\x12\x03\x0e()\n\x0b\n\x04\x04\
|
\x0c\n\x05\x04\x02\x08\x02\x01\x12\x03\x0f\n\x19\n\x0b\n\x04\x04\x02\x02\
|
||||||
\x02\x08\x02\x12\x03\x0f\x042\n\x0c\n\x05\x04\x02\x08\x02\x01\x12\x03\
|
\x03\x12\x03\x0f\x1c0\n\x0c\n\x05\x04\x02\x02\x03\x05\x12\x03\x0f\x1c\"\
|
||||||
\x0f\n\x19\n\x0b\n\x04\x04\x02\x02\x03\x12\x03\x0f\x1c0\n\x0c\n\x05\x04\
|
\n\x0c\n\x05\x04\x02\x02\x03\x01\x12\x03\x0f#+\n\x0c\n\x05\x04\x02\x02\
|
||||||
\x02\x02\x03\x05\x12\x03\x0f\x1c\"\n\x0c\n\x05\x04\x02\x02\x03\x01\x12\
|
\x03\x03\x12\x03\x0f./\n\n\n\x02\x04\x03\x12\x04\x11\0\x16\x01\n\n\n\x03\
|
||||||
\x03\x0f#+\n\x0c\n\x05\x04\x02\x02\x03\x03\x12\x03\x0f./\n\n\n\x02\x04\
|
\x04\x03\x01\x12\x03\x11\x08\x18\n\x0b\n\x04\x04\x03\x02\0\x12\x03\x12\
|
||||||
\x03\x12\x04\x11\0\x16\x01\n\n\n\x03\x04\x03\x01\x12\x03\x11\x08\x18\n\
|
\x04\x12\n\x0c\n\x05\x04\x03\x02\0\x05\x12\x03\x12\x04\n\n\x0c\n\x05\x04\
|
||||||
\x0b\n\x04\x04\x03\x02\0\x12\x03\x12\x04\x12\n\x0c\n\x05\x04\x03\x02\0\
|
\x03\x02\0\x01\x12\x03\x12\x0b\r\n\x0c\n\x05\x04\x03\x02\0\x03\x12\x03\
|
||||||
\x05\x12\x03\x12\x04\n\n\x0c\n\x05\x04\x03\x02\0\x01\x12\x03\x12\x0b\r\n\
|
\x12\x10\x11\n\x0b\n\x04\x04\x03\x08\0\x12\x03\x13\x04*\n\x0c\n\x05\x04\
|
||||||
\x0c\n\x05\x04\x03\x02\0\x03\x12\x03\x12\x10\x11\n\x0b\n\x04\x04\x03\x08\
|
\x03\x08\0\x01\x12\x03\x13\n\x15\n\x0b\n\x04\x04\x03\x02\x01\x12\x03\x13\
|
||||||
\0\x12\x03\x13\x04*\n\x0c\n\x05\x04\x03\x08\0\x01\x12\x03\x13\n\x15\n\
|
\x18(\n\x0c\n\x05\x04\x03\x02\x01\x05\x12\x03\x13\x18\x1e\n\x0c\n\x05\
|
||||||
\x0b\n\x04\x04\x03\x02\x01\x12\x03\x13\x18(\n\x0c\n\x05\x04\x03\x02\x01\
|
\x04\x03\x02\x01\x01\x12\x03\x13\x1f#\n\x0c\n\x05\x04\x03\x02\x01\x03\
|
||||||
\x05\x12\x03\x13\x18\x1e\n\x0c\n\x05\x04\x03\x02\x01\x01\x12\x03\x13\x1f\
|
\x12\x03\x13&'\n\x0b\n\x04\x04\x03\x08\x01\x12\x03\x14\x04,\n\x0c\n\x05\
|
||||||
#\n\x0c\n\x05\x04\x03\x02\x01\x03\x12\x03\x13&'\n\x0b\n\x04\x04\x03\x08\
|
\x04\x03\x08\x01\x01\x12\x03\x14\n\x16\n\x0b\n\x04\x04\x03\x02\x02\x12\
|
||||||
\x01\x12\x03\x14\x04,\n\x0c\n\x05\x04\x03\x08\x01\x01\x12\x03\x14\n\x16\
|
\x03\x14\x19*\n\x0c\n\x05\x04\x03\x02\x02\x05\x12\x03\x14\x19\x1f\n\x0c\
|
||||||
\n\x0b\n\x04\x04\x03\x02\x02\x12\x03\x14\x19*\n\x0c\n\x05\x04\x03\x02\
|
\n\x05\x04\x03\x02\x02\x01\x12\x03\x14\x20%\n\x0c\n\x05\x04\x03\x02\x02\
|
||||||
\x02\x05\x12\x03\x14\x19\x1f\n\x0c\n\x05\x04\x03\x02\x02\x01\x12\x03\x14\
|
\x03\x12\x03\x14()\n\x0b\n\x04\x04\x03\x08\x02\x12\x03\x15\x042\n\x0c\n\
|
||||||
\x20%\n\x0c\n\x05\x04\x03\x02\x02\x03\x12\x03\x14()\n\x0b\n\x04\x04\x03\
|
\x05\x04\x03\x08\x02\x01\x12\x03\x15\n\x19\n\x0b\n\x04\x04\x03\x02\x03\
|
||||||
\x08\x02\x12\x03\x15\x042\n\x0c\n\x05\x04\x03\x08\x02\x01\x12\x03\x15\n\
|
\x12\x03\x15\x1c0\n\x0c\n\x05\x04\x03\x02\x03\x05\x12\x03\x15\x1c\"\n\
|
||||||
\x19\n\x0b\n\x04\x04\x03\x02\x03\x12\x03\x15\x1c0\n\x0c\n\x05\x04\x03\
|
\x0c\n\x05\x04\x03\x02\x03\x01\x12\x03\x15#+\n\x0c\n\x05\x04\x03\x02\x03\
|
||||||
\x02\x03\x05\x12\x03\x15\x1c\"\n\x0c\n\x05\x04\x03\x02\x03\x01\x12\x03\
|
\x03\x12\x03\x15./b\x06proto3\
|
||||||
\x15#+\n\x0c\n\x05\x04\x03\x02\x03\x03\x12\x03\x15./\n\n\n\x02\x05\0\x12\
|
|
||||||
\x04\x17\0\x1b\x01\n\n\n\x03\x05\0\x01\x12\x03\x17\x05\x0f\n\x0b\n\x04\
|
|
||||||
\x05\0\x02\0\x12\x03\x18\x04\x10\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\x18\
|
|
||||||
\x04\x0b\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x18\x0e\x0f\n\x0b\n\x04\x05\
|
|
||||||
\0\x02\x01\x12\x03\x19\x04\x0e\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x19\
|
|
||||||
\x04\t\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x19\x0c\r\n\x0b\n\x04\x05\0\
|
|
||||||
\x02\x02\x12\x03\x1a\x04\x10\n\x0c\n\x05\x05\0\x02\x02\x01\x12\x03\x1a\
|
|
||||||
\x04\x0b\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\x1a\x0e\x0fb\x06proto3\
|
|
||||||
";
|
";
|
||||||
|
|
||||||
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
enum UserEvent {
|
enum UserEvent {
|
||||||
GetUserProfile = 0;
|
InitUser = 0;
|
||||||
SignIn = 1;
|
SignIn = 1;
|
||||||
SignUp = 2;
|
SignUp = 2;
|
||||||
SignOut = 3;
|
SignOut = 3;
|
||||||
UpdateUser = 4;
|
UpdateUser = 4;
|
||||||
|
GetUserProfile = 5;
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,3 @@ message UpdateUserParams {
|
|||||||
oneof one_of_email { string email = 3; };
|
oneof one_of_email { string email = 3; };
|
||||||
oneof one_of_password { string password = 4; };
|
oneof one_of_password { string password = 4; };
|
||||||
}
|
}
|
||||||
enum UserStatus {
|
|
||||||
Unknown = 0;
|
|
||||||
Login = 1;
|
|
||||||
Expired = 2;
|
|
||||||
}
|
|
||||||
|
@ -1,20 +1,31 @@
|
|||||||
use crate::services::user::{UserSession, UserSessionConfig};
|
use crate::services::user::{SessionStatusCallback, UserSession, UserSessionConfig};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub struct UserSessionBuilder {
|
pub struct UserSessionBuilder {
|
||||||
config: Option<UserSessionConfig>,
|
config: Option<UserSessionConfig>,
|
||||||
|
callback: SessionStatusCallback,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserSessionBuilder {
|
impl UserSessionBuilder {
|
||||||
pub fn new() -> Self { Self { config: None } }
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
config: None,
|
||||||
|
callback: Arc::new(|_| {}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn root_dir(mut self, dir: &str) -> Self {
|
pub fn root_dir(mut self, dir: &str) -> Self {
|
||||||
self.config = Some(UserSessionConfig::new(dir));
|
self.config = Some(UserSessionConfig::new(dir));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn status_callback(mut self, callback: SessionStatusCallback) -> Self {
|
||||||
|
self.callback = callback;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build(mut self) -> UserSession {
|
pub fn build(mut self) -> UserSession {
|
||||||
let config = self.config.take().unwrap();
|
let config = self.config.take().unwrap();
|
||||||
|
UserSession::new(config, self.callback.clone())
|
||||||
UserSession::new(config)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ use flowy_database::{
|
|||||||
};
|
};
|
||||||
use flowy_infra::kv::KV;
|
use flowy_infra::kv::KV;
|
||||||
use flowy_sqlite::ConnectionPool;
|
use flowy_sqlite::ConnectionPool;
|
||||||
|
use flowy_ws::WsController;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -34,24 +35,36 @@ impl UserSessionConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum SessionStatus {
|
||||||
|
Login { token: String },
|
||||||
|
Expired { token: String },
|
||||||
|
}
|
||||||
|
pub type SessionStatusCallback = Arc<dyn Fn(SessionStatus) + Send + Sync>;
|
||||||
|
|
||||||
pub struct UserSession {
|
pub struct UserSession {
|
||||||
database: UserDB,
|
database: UserDB,
|
||||||
config: UserSessionConfig,
|
config: UserSessionConfig,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
server: Server,
|
server: Server,
|
||||||
session: RwLock<Option<Session>>,
|
session: RwLock<Option<Session>>,
|
||||||
|
ws: RwLock<WsController>,
|
||||||
|
status_callback: SessionStatusCallback,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserSession {
|
impl UserSession {
|
||||||
pub fn new(config: UserSessionConfig) -> Self {
|
pub fn new(config: UserSessionConfig, status_callback: SessionStatusCallback) -> Self {
|
||||||
let db = UserDB::new(&config.root_dir);
|
let db = UserDB::new(&config.root_dir);
|
||||||
let server = construct_user_server();
|
let server = construct_user_server();
|
||||||
Self {
|
let ws = RwLock::new(WsController::new());
|
||||||
|
let user_session = Self {
|
||||||
database: db,
|
database: db,
|
||||||
config,
|
config,
|
||||||
server,
|
server,
|
||||||
session: RwLock::new(None),
|
session: RwLock::new(None),
|
||||||
}
|
ws,
|
||||||
|
status_callback,
|
||||||
|
};
|
||||||
|
user_session
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn db_connection(&self) -> Result<DBConnection, UserError> {
|
pub fn db_connection(&self) -> Result<DBConnection, UserError> {
|
||||||
@ -80,6 +93,9 @@ impl UserSession {
|
|||||||
let _ = self.set_session(Some(session))?;
|
let _ = self.set_session(Some(session))?;
|
||||||
let user_table = self.save_user(resp.into()).await?;
|
let user_table = self.save_user(resp.into()).await?;
|
||||||
let user_profile = UserProfile::from(user_table);
|
let user_profile = UserProfile::from(user_table);
|
||||||
|
(self.status_callback)(SessionStatus::Login {
|
||||||
|
token: user_profile.token.clone(),
|
||||||
|
});
|
||||||
Ok(user_profile)
|
Ok(user_profile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,6 +110,9 @@ impl UserSession {
|
|||||||
let _ = self.set_session(Some(session))?;
|
let _ = self.set_session(Some(session))?;
|
||||||
let user_table = self.save_user(resp.into()).await?;
|
let user_table = self.save_user(resp.into()).await?;
|
||||||
let user_profile = UserProfile::from(user_table);
|
let user_profile = UserProfile::from(user_table);
|
||||||
|
(self.status_callback)(SessionStatus::Login {
|
||||||
|
token: user_profile.token.clone(),
|
||||||
|
});
|
||||||
Ok(user_profile)
|
Ok(user_profile)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -104,6 +123,9 @@ impl UserSession {
|
|||||||
let _ = diesel::delete(dsl::user_table.filter(dsl::id.eq(&session.user_id))).execute(&*(self.db_connection()?))?;
|
let _ = diesel::delete(dsl::user_table.filter(dsl::id.eq(&session.user_id))).execute(&*(self.db_connection()?))?;
|
||||||
let _ = self.database.close_user_db(&session.user_id)?;
|
let _ = self.database.close_user_db(&session.user_id)?;
|
||||||
let _ = self.set_session(None)?;
|
let _ = self.set_session(None)?;
|
||||||
|
(self.status_callback)(SessionStatus::Expired {
|
||||||
|
token: session.token.clone(),
|
||||||
|
});
|
||||||
let _ = self.sign_out_on_server(&session.token).await?;
|
let _ = self.sign_out_on_server(&session.token).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -119,13 +141,26 @@ impl UserSession {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn init_user(&self) -> Result<UserProfile, UserError> {
|
||||||
|
let (user_id, token) = self.get_session()?.into_part();
|
||||||
|
|
||||||
|
let user = dsl::user_table
|
||||||
|
.filter(user_table::id.eq(&user_id))
|
||||||
|
.first::<UserTable>(&*(self.db_connection()?))?;
|
||||||
|
|
||||||
|
let _ = self.read_user_profile_on_server(&token)?;
|
||||||
|
let _ = self.start_ws_connection(&token)?;
|
||||||
|
|
||||||
|
Ok(UserProfile::from(user))
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn user_profile(&self) -> Result<UserProfile, UserError> {
|
pub async fn user_profile(&self) -> Result<UserProfile, UserError> {
|
||||||
let (user_id, token) = self.get_session()?.into_part();
|
let (user_id, token) = self.get_session()?.into_part();
|
||||||
let user = dsl::user_table
|
let user = dsl::user_table
|
||||||
.filter(user_table::id.eq(&user_id))
|
.filter(user_table::id.eq(&user_id))
|
||||||
.first::<UserTable>(&*(self.db_connection()?))?;
|
.first::<UserTable>(&*(self.db_connection()?))?;
|
||||||
|
|
||||||
let _ = self.read_user_profile_on_server(&token).await?;
|
let _ = self.read_user_profile_on_server(&token)?;
|
||||||
Ok(UserProfile::from(user))
|
Ok(UserProfile::from(user))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,7 +175,7 @@ impl UserSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl UserSession {
|
impl UserSession {
|
||||||
async fn read_user_profile_on_server(&self, token: &str) -> Result<(), UserError> {
|
fn read_user_profile_on_server(&self, token: &str) -> Result<(), UserError> {
|
||||||
let server = self.server.clone();
|
let server = self.server.clone();
|
||||||
let token = token.to_owned();
|
let token = token.to_owned();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
@ -225,6 +260,25 @@ impl UserSession {
|
|||||||
Err(_) => false,
|
Err(_) => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn start_ws_connection(&self, token: &str) -> Result<(), UserError> {
|
||||||
|
let addr = format!("{}/{}", flowy_net::config::WS_ADDR.as_str(), token);
|
||||||
|
log::debug!("🐴 Try to connect: {}", &addr);
|
||||||
|
let (conn, handlers) = self.ws.write().make_connect(addr);
|
||||||
|
tokio::spawn(async {
|
||||||
|
match conn.await {
|
||||||
|
Ok(_) => {
|
||||||
|
log::debug!("🐴 ws connect success");
|
||||||
|
let _ = handlers.await;
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
// TODO: retry?
|
||||||
|
log::error!("ws connect failed: {}", e);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn update_user(_server: Server, pool: Arc<ConnectionPool>, params: UpdateUserParams) -> Result<(), UserError> {
|
pub async fn update_user(_server: Server, pool: Arc<ConnectionPool>, params: UpdateUserParams) -> Result<(), UserError> {
|
||||||
|
@ -14,8 +14,6 @@ futures-util = "0.3.17"
|
|||||||
futures-channel = "0.3.17"
|
futures-channel = "0.3.17"
|
||||||
tokio = {version = "1", features = ["full"]}
|
tokio = {version = "1", features = ["full"]}
|
||||||
futures = "0.3.17"
|
futures = "0.3.17"
|
||||||
lazy_static = "1.4"
|
|
||||||
parking_lot = "0.11"
|
|
||||||
bytes = "0.5"
|
bytes = "0.5"
|
||||||
pin-project = "1.0.0"
|
pin-project = "1.0.0"
|
||||||
futures-core = { version = "0.3", default-features = false }
|
futures-core = { version = "0.3", default-features = false }
|
||||||
@ -27,4 +25,5 @@ strum = "0.21"
|
|||||||
strum_macros = "0.21"
|
strum_macros = "0.21"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tokio = {version = "1", features = ["full"]}
|
tokio = {version = "1", features = ["full"]}
|
||||||
|
env_logger = "0.8.2"
|
@ -27,6 +27,7 @@ macro_rules! static_user_error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl WsError {
|
impl WsError {
|
||||||
|
#[allow(dead_code)]
|
||||||
pub(crate) fn new(code: ErrorCode) -> WsError { WsError { code, msg: "".to_string() } }
|
pub(crate) fn new(code: ErrorCode) -> WsError { WsError { code, msg: "".to_string() } }
|
||||||
|
|
||||||
pub fn context<T: Debug>(mut self, error: T) -> Self {
|
pub fn context<T: Debug>(mut self, error: T) -> Self {
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
use crate::errors::WsError;
|
use crate::errors::WsError;
|
||||||
|
use flowy_net::{errors::ServerError, response::FlowyResponse};
|
||||||
use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender};
|
use futures_channel::mpsc::{UnboundedReceiver, UnboundedSender};
|
||||||
use futures_core::{future::BoxFuture, ready, Stream};
|
use futures_core::{future::BoxFuture, ready, Stream};
|
||||||
use futures_util::{pin_mut, FutureExt, StreamExt};
|
use futures_util::{pin_mut, FutureExt, StreamExt};
|
||||||
use lazy_static::lazy_static;
|
|
||||||
use parking_lot::RwLock;
|
|
||||||
use pin_project::pin_project;
|
use pin_project::pin_project;
|
||||||
use std::{
|
use std::{
|
||||||
future::Future,
|
future::Future,
|
||||||
@ -14,20 +13,17 @@ use std::{
|
|||||||
use tokio::net::TcpStream;
|
use tokio::net::TcpStream;
|
||||||
use tokio_tungstenite::{
|
use tokio_tungstenite::{
|
||||||
connect_async,
|
connect_async,
|
||||||
tungstenite::{handshake::client::Response, Error, Message},
|
tungstenite::{handshake::client::Response, http::StatusCode, Error, Message},
|
||||||
MaybeTlsStream,
|
MaybeTlsStream,
|
||||||
WebSocketStream,
|
WebSocketStream,
|
||||||
};
|
};
|
||||||
lazy_static! {
|
|
||||||
pub static ref WS: RwLock<WsController> = RwLock::new(WsController::new());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn start_ws_connection() { WS.write().connect(flowy_net::config::WS_ADDR.as_ref()); }
|
|
||||||
|
|
||||||
pub type MsgReceiver = UnboundedReceiver<Message>;
|
pub type MsgReceiver = UnboundedReceiver<Message>;
|
||||||
pub type MsgSender = UnboundedSender<Message>;
|
pub type MsgSender = UnboundedSender<Message>;
|
||||||
pub trait WsMessageHandler: Sync + Send + 'static {
|
pub trait WsMessageHandler: Sync + Send + 'static {
|
||||||
fn handler_message(&self, msg: &Message);
|
fn can_handle(&self) -> bool;
|
||||||
|
fn receive_message(&self, msg: &Message);
|
||||||
|
fn send_message(&self, sender: Arc<WsSender>);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WsController {
|
pub struct WsController {
|
||||||
@ -47,13 +43,15 @@ impl WsController {
|
|||||||
|
|
||||||
pub fn add_handlers(&mut self, handler: Arc<dyn WsMessageHandler>) { self.handlers.push(handler); }
|
pub fn add_handlers(&mut self, handler: Arc<dyn WsMessageHandler>) { self.handlers.push(handler); }
|
||||||
|
|
||||||
pub fn connect(&mut self, addr: &str) {
|
#[allow(dead_code)]
|
||||||
let (ws, handlers) = self.make_connect(&addr);
|
pub async fn connect(&mut self, addr: String) -> Result<(), ServerError> {
|
||||||
let _ = tokio::spawn(ws);
|
let (conn, handlers) = self.make_connect(addr);
|
||||||
|
let _ = conn.await?;
|
||||||
let _ = tokio::spawn(handlers);
|
let _ = tokio::spawn(handlers);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_connect(&mut self, addr: &str) -> (WsRaw, WsHandlers) {
|
pub fn make_connect(&mut self, addr: String) -> (WsConnection, WsHandlers) {
|
||||||
// Stream User
|
// Stream User
|
||||||
// ┌───────────────┐ ┌──────────────┐
|
// ┌───────────────┐ ┌──────────────┐
|
||||||
// ┌──────┐ │ ┌─────────┐ │ ┌────────┐ │ ┌────────┐ │
|
// ┌──────┐ │ ┌─────────┐ │ ┌────────┐ │ ┌────────┐ │
|
||||||
@ -64,15 +62,12 @@ impl WsController {
|
|||||||
// └─────────┼──│ws_write │◀─┼────│ ws_rx │◀──┼──│ ws_tx │ │
|
// └─────────┼──│ws_write │◀─┼────│ ws_rx │◀──┼──│ ws_tx │ │
|
||||||
// │ └─────────┘ │ └────────┘ │ └────────┘ │
|
// │ └─────────┘ │ └────────┘ │ └────────┘ │
|
||||||
// └───────────────┘ └──────────────┘
|
// └───────────────┘ └──────────────┘
|
||||||
let addr = addr.to_string();
|
|
||||||
let (msg_tx, msg_rx) = futures_channel::mpsc::unbounded();
|
let (msg_tx, msg_rx) = futures_channel::mpsc::unbounded();
|
||||||
let (ws_tx, ws_rx) = futures_channel::mpsc::unbounded();
|
let (ws_tx, ws_rx) = futures_channel::mpsc::unbounded();
|
||||||
let sender = Arc::new(WsSender::new(ws_tx));
|
let sender = Arc::new(WsSender::new(ws_tx));
|
||||||
let handlers = self.handlers.clone();
|
let handlers = self.handlers.clone();
|
||||||
self.sender = Some(sender.clone());
|
self.sender = Some(sender.clone());
|
||||||
log::debug!("🐴ws prepare connection");
|
(WsConnection::new(msg_tx, ws_rx, addr), WsHandlers::new(handlers, msg_rx))
|
||||||
|
|
||||||
(WsRaw::new(msg_tx, ws_rx, addr), WsHandlers::new(handlers, msg_rx))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_message(&self, msg: Message) -> Result<(), WsError> {
|
pub fn send_message(&self, msg: Message) -> Result<(), WsError> {
|
||||||
@ -84,7 +79,7 @@ impl WsController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[pin_project]
|
#[pin_project]
|
||||||
struct WsHandlers {
|
pub struct WsHandlers {
|
||||||
#[pin]
|
#[pin]
|
||||||
msg_rx: MsgReceiver,
|
msg_rx: MsgReceiver,
|
||||||
handlers: Vec<Arc<dyn WsMessageHandler>>,
|
handlers: Vec<Arc<dyn WsMessageHandler>>,
|
||||||
@ -101,7 +96,7 @@ impl Future for WsHandlers {
|
|||||||
match ready!(self.as_mut().project().msg_rx.poll_next(cx)) {
|
match ready!(self.as_mut().project().msg_rx.poll_next(cx)) {
|
||||||
None => return Poll::Ready(()),
|
None => return Poll::Ready(()),
|
||||||
Some(message) => self.handlers.iter().for_each(|handler| {
|
Some(message) => self.handlers.iter().for_each(|handler| {
|
||||||
handler.handler_message(&message);
|
handler.receive_message(&message);
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -109,16 +104,16 @@ impl Future for WsHandlers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[pin_project]
|
#[pin_project]
|
||||||
pub struct WsRaw {
|
pub struct WsConnection {
|
||||||
msg_tx: Option<MsgSender>,
|
msg_tx: Option<MsgSender>,
|
||||||
ws_rx: Option<MsgReceiver>,
|
ws_rx: Option<MsgReceiver>,
|
||||||
#[pin]
|
#[pin]
|
||||||
fut: BoxFuture<'static, Result<(WebSocketStream<MaybeTlsStream<TcpStream>>, Response), Error>>,
|
fut: BoxFuture<'static, Result<(WebSocketStream<MaybeTlsStream<TcpStream>>, Response), Error>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WsRaw {
|
impl WsConnection {
|
||||||
pub fn new(msg_tx: MsgSender, ws_rx: MsgReceiver, addr: String) -> Self {
|
pub fn new(msg_tx: MsgSender, ws_rx: MsgReceiver, addr: String) -> Self {
|
||||||
WsRaw {
|
WsConnection {
|
||||||
msg_tx: Some(msg_tx),
|
msg_tx: Some(msg_tx),
|
||||||
ws_rx: Some(ws_rx),
|
ws_rx: Some(ws_rx),
|
||||||
fut: Box::pin(async move { connect_async(&addr).await }),
|
fut: Box::pin(async move { connect_async(&addr).await }),
|
||||||
@ -126,8 +121,8 @@ impl WsRaw {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Future for WsRaw {
|
impl Future for WsConnection {
|
||||||
type Output = ();
|
type Output = Result<(), ServerError>;
|
||||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
// [[pin]]
|
// [[pin]]
|
||||||
// poll async function. The following methods not work.
|
// poll async function. The following methods not work.
|
||||||
@ -147,50 +142,35 @@ impl Future for WsRaw {
|
|||||||
loop {
|
loop {
|
||||||
return match ready!(self.as_mut().project().fut.poll(cx)) {
|
return match ready!(self.as_mut().project().fut.poll(cx)) {
|
||||||
Ok((stream, _)) => {
|
Ok((stream, _)) => {
|
||||||
log::debug!("🐴 ws connect success");
|
|
||||||
let mut ws_stream = WsStream {
|
let mut ws_stream = WsStream {
|
||||||
msg_tx: self.msg_tx.take(),
|
msg_tx: self.msg_tx.take(),
|
||||||
ws_rx: self.ws_rx.take(),
|
ws_rx: self.ws_rx.take(),
|
||||||
stream: Some(stream),
|
stream: Some(stream),
|
||||||
};
|
};
|
||||||
match Pin::new(&mut ws_stream).poll(cx) {
|
match Pin::new(&mut ws_stream).poll(cx) {
|
||||||
Poll::Ready(_a) => Poll::Ready(()),
|
Poll::Ready(_) => Poll::Ready(Ok(())),
|
||||||
Poll::Pending => Poll::Pending,
|
Poll::Pending => Poll::Pending,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(error) => Poll::Ready(Err(error_to_flowy_response(error))),
|
||||||
log::error!("🐴 ws connect failed: {:?}", e);
|
|
||||||
Poll::Ready(())
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[pin_project]
|
fn error_to_flowy_response(error: tokio_tungstenite::tungstenite::Error) -> ServerError {
|
||||||
struct WsConn {
|
let error = match error {
|
||||||
#[pin]
|
Error::Http(response) => {
|
||||||
fut: BoxFuture<'static, Result<(WebSocketStream<MaybeTlsStream<TcpStream>>, Response), Error>>,
|
if response.status() == StatusCode::UNAUTHORIZED {
|
||||||
}
|
ServerError::unauthorized()
|
||||||
|
} else {
|
||||||
|
ServerError::internal().context(response)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => ServerError::internal().context(error),
|
||||||
|
};
|
||||||
|
|
||||||
impl WsConn {
|
error
|
||||||
fn new(addr: String) -> Self {
|
|
||||||
Self {
|
|
||||||
fut: Box::pin(async move { connect_async(&addr).await }),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Future for WsConn {
|
|
||||||
type Output = Result<(WebSocketStream<MaybeTlsStream<TcpStream>>, Response), Error>;
|
|
||||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
|
||||||
loop {
|
|
||||||
return match ready!(self.as_mut().project().fut.poll(cx)) {
|
|
||||||
Ok(o) => Poll::Ready(Ok(o)),
|
|
||||||
Err(e) => Poll::Ready(Err(e)),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WsStream {
|
struct WsStream {
|
||||||
@ -218,7 +198,7 @@ impl Future for WsStream {
|
|||||||
});
|
});
|
||||||
|
|
||||||
pin_mut!(to_ws, from_ws);
|
pin_mut!(to_ws, from_ws);
|
||||||
log::debug!("🐴 ws start poll stream");
|
log::trace!("🐴 ws start poll stream");
|
||||||
match to_ws.poll_unpin(cx) {
|
match to_ws.poll_unpin(cx) {
|
||||||
Poll::Ready(_) => Poll::Ready(()),
|
Poll::Ready(_) => Poll::Ready(()),
|
||||||
Poll::Pending => match from_ws.poll_unpin(cx) {
|
Poll::Pending => match from_ws.poll_unpin(cx) {
|
||||||
@ -245,39 +225,18 @@ impl WsSender {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::WsController;
|
use super::WsController;
|
||||||
use futures_util::{pin_mut, StreamExt};
|
|
||||||
use tokio_tungstenite::connect_async;
|
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn connect() {
|
async fn connect() {
|
||||||
|
std::env::set_var("RUST_LOG", "Debug");
|
||||||
|
env_logger::init();
|
||||||
|
|
||||||
let mut controller = WsController::new();
|
let mut controller = WsController::new();
|
||||||
let addr = format!("{}/123", flowy_net::config::WS_ADDR.as_str());
|
let addr = format!("{}/123", flowy_net::config::WS_ADDR.as_str());
|
||||||
let (a, b) = controller.make_connect(&addr);
|
let (a, b) = controller.make_connect(addr);
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
_ = a => println!("write completed"),
|
r = a => println!("write completed {:?}", r),
|
||||||
_ = b => println!("read completed"),
|
_ = b => println!("read completed"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn connect_raw() {
|
|
||||||
let _controller = WsController::new();
|
|
||||||
let addr = format!("{}/123", flowy_net::config::WS_ADDR.as_str());
|
|
||||||
let (tx, rx) = futures_channel::mpsc::unbounded();
|
|
||||||
let (ws_write, ws_read) = connect_async(&addr).await.unwrap().0.split();
|
|
||||||
let to_ws = rx.map(Ok).forward(ws_write);
|
|
||||||
let from_ws = ws_read.for_each(|message| async {
|
|
||||||
tx.unbounded_send(message.unwrap()).unwrap();
|
|
||||||
});
|
|
||||||
|
|
||||||
pin_mut!(to_ws, from_ws);
|
|
||||||
tokio::select! {
|
|
||||||
_ = to_ws => {
|
|
||||||
log::debug!("ws write completed")
|
|
||||||
}
|
|
||||||
_ = from_ws => {
|
|
||||||
log::debug!("ws read completed")
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user