2024-07-02 18:54:16 +03:00
|
|
|
/*
|
|
|
|
* SPDX-FileCopyrightText: 2020 Nextcloud GmbH and Nextcloud contributors
|
|
|
|
* SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
*/
|
|
|
|
|
2021-02-02 03:14:27 +03:00
|
|
|
use dashmap::DashMap;
|
2021-02-03 23:09:30 +03:00
|
|
|
use flexi_logger::{Logger, LoggerHandle};
|
2021-02-02 03:14:27 +03:00
|
|
|
use futures::future::select;
|
|
|
|
use futures::{pin_mut, FutureExt};
|
|
|
|
use futures::{SinkExt, StreamExt};
|
|
|
|
use http_auth_basic::Credentials;
|
2021-02-25 18:15:43 +03:00
|
|
|
use notify_push::config::{Bind, Config};
|
2021-12-10 16:44:26 +03:00
|
|
|
use notify_push::message::DEBOUNCE_ENABLE;
|
2021-02-09 02:39:26 +03:00
|
|
|
use notify_push::{listen_loop, serve, App};
|
2021-02-03 23:09:30 +03:00
|
|
|
use once_cell::sync::Lazy;
|
2021-02-02 03:14:27 +03:00
|
|
|
use redis::AsyncCommands;
|
|
|
|
use smallvec::alloc::sync::Arc;
|
2024-05-23 18:24:46 +03:00
|
|
|
use sqlx::AnyPool;
|
2021-02-02 03:14:27 +03:00
|
|
|
use std::net::SocketAddr;
|
2024-01-22 20:32:40 +03:00
|
|
|
use std::sync::atomic::{AtomicU16, Ordering};
|
2021-02-02 03:14:27 +03:00
|
|
|
use tokio::net::{TcpListener, TcpStream};
|
|
|
|
use tokio::sync::oneshot;
|
|
|
|
use tokio::task::spawn;
|
|
|
|
use tokio::time::timeout;
|
2021-02-09 02:39:26 +03:00
|
|
|
use tokio::time::{sleep, Duration};
|
|
|
|
use tokio_stream::wrappers::TcpListenerStream;
|
2021-02-02 03:14:27 +03:00
|
|
|
use tokio_tungstenite::tungstenite::Message;
|
2021-04-12 17:21:09 +03:00
|
|
|
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
|
2021-02-02 03:14:27 +03:00
|
|
|
use warp::http::StatusCode;
|
|
|
|
use warp::{Filter, Reply};
|
|
|
|
|
2024-01-22 20:32:40 +03:00
|
|
|
static LAST_PORT: AtomicU16 = AtomicU16::new(1024);
|
2021-02-02 03:14:27 +03:00
|
|
|
|
|
|
|
async fn listen_available_port() -> Option<TcpListener> {
|
2024-01-22 20:32:40 +03:00
|
|
|
for _ in LAST_PORT.load(Ordering::SeqCst)..65535 {
|
|
|
|
let port = LAST_PORT.fetch_add(1, Ordering::SeqCst);
|
2021-12-10 16:49:51 +03:00
|
|
|
if let Ok(tcp) = TcpListener::bind(("127.0.0.1", port)).await {
|
|
|
|
return Some(tcp);
|
2021-02-02 03:14:27 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Services {
|
|
|
|
redis: SocketAddr,
|
|
|
|
nextcloud: SocketAddr,
|
|
|
|
_redis_shutdown: oneshot::Sender<()>,
|
|
|
|
_nextcloud_shutdown: oneshot::Sender<()>,
|
|
|
|
users: Arc<DashMap<String, String>>,
|
|
|
|
db: AnyPool,
|
|
|
|
}
|
|
|
|
|
2021-06-15 21:18:04 +03:00
|
|
|
static LOG_HANDLE: Lazy<LoggerHandle> =
|
|
|
|
Lazy::new(|| Logger::try_with_str("").unwrap().start().unwrap());
|
2021-02-03 23:09:30 +03:00
|
|
|
|
2021-02-02 03:14:27 +03:00
|
|
|
impl Services {
|
|
|
|
pub async fn new() -> Self {
|
2024-05-23 18:24:46 +03:00
|
|
|
sqlx::any::install_default_drivers();
|
2021-12-10 16:44:26 +03:00
|
|
|
DEBOUNCE_ENABLE.store(false, Ordering::SeqCst);
|
2021-02-02 03:14:27 +03:00
|
|
|
let redis_tcp = listen_available_port()
|
|
|
|
.await
|
|
|
|
.expect("Can't find open port for redis");
|
2021-02-09 02:39:26 +03:00
|
|
|
let nextcloud_tcp = listen_available_port()
|
2021-02-02 03:14:27 +03:00
|
|
|
.await
|
|
|
|
.expect("Can't find open port for nextcloud mock");
|
|
|
|
|
|
|
|
let redis_addr = redis_tcp
|
|
|
|
.local_addr()
|
|
|
|
.expect("Failed to get redis socket address");
|
|
|
|
let nextcloud_addr = nextcloud_tcp
|
|
|
|
.local_addr()
|
|
|
|
.expect("Failed to get nextcloud mock socket address");
|
|
|
|
|
2024-05-23 18:24:46 +03:00
|
|
|
// use the port in the db name to prevent collisions
|
|
|
|
let db = AnyPool::connect(&format!(
|
|
|
|
"sqlite:file:memory{}?mode=memory&cache=shared",
|
|
|
|
nextcloud_addr.port()
|
|
|
|
))
|
|
|
|
.await
|
|
|
|
.expect("Failed to connect sqlite database");
|
2021-02-02 03:14:27 +03:00
|
|
|
|
2024-05-23 18:24:46 +03:00
|
|
|
sqlx::query("CREATE TABLE oc_filecache(fileid BIGINT, path TEXT)")
|
2021-02-02 03:14:27 +03:00
|
|
|
.execute(&db)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
2024-05-23 18:24:46 +03:00
|
|
|
sqlx::query("CREATE INDEX fc_id ON oc_filecache (fileid)")
|
2021-02-02 03:14:27 +03:00
|
|
|
.execute(&db)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
2024-05-23 18:24:46 +03:00
|
|
|
sqlx::query("CREATE TABLE oc_mounts(storage_id BIGINT, root_id BIGINT, user_id TEXT)")
|
|
|
|
.execute(&db)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
sqlx::query("CREATE INDEX mount_storage ON oc_mounts (storage_id)")
|
2021-02-02 03:14:27 +03:00
|
|
|
.execute(&db)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
2024-05-23 18:24:46 +03:00
|
|
|
sqlx::query("CREATE INDEX mount_root ON oc_mounts (root_id)")
|
2021-02-02 03:14:27 +03:00
|
|
|
.execute(&db)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
let users: Arc<DashMap<String, String>> = Arc::default();
|
|
|
|
|
|
|
|
let users_filter = users.clone();
|
|
|
|
let users_filter = warp::any().map(move || users_filter.clone());
|
|
|
|
|
|
|
|
let uid = warp::any()
|
|
|
|
.and(warp::header::<String>("authorization"))
|
|
|
|
.and(users_filter)
|
|
|
|
.map(|auth, users: Arc<DashMap<String, String>>| {
|
|
|
|
let credentials = match Credentials::from_header(auth) {
|
|
|
|
Ok(credentials) => credentials,
|
|
|
|
Err(_) => return Box::new(StatusCode::BAD_REQUEST) as Box<dyn Reply>,
|
|
|
|
};
|
|
|
|
match users.get(&credentials.user_id) {
|
|
|
|
Some(pass) if pass.value() == &credentials.password => {
|
|
|
|
Box::new(credentials.user_id)
|
|
|
|
}
|
|
|
|
_ => Box::new(StatusCode::UNAUTHORIZED),
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
let (redis_shutdown, redis_shutdown_rx) = oneshot::channel();
|
|
|
|
let (nextcloud_shutdown, nextcloud_shutdown_rx) = oneshot::channel();
|
|
|
|
|
|
|
|
spawn(async move {
|
|
|
|
warp::serve(uid)
|
|
|
|
.serve_incoming_with_graceful_shutdown(
|
2021-02-09 02:39:26 +03:00
|
|
|
TcpListenerStream::new(nextcloud_tcp),
|
2021-02-02 03:14:27 +03:00
|
|
|
nextcloud_shutdown_rx.map(|_| ()),
|
|
|
|
)
|
|
|
|
.await;
|
|
|
|
});
|
|
|
|
spawn(async move {
|
|
|
|
mini_redis::server::run(redis_tcp, redis_shutdown_rx)
|
|
|
|
.await
|
|
|
|
.ok();
|
|
|
|
});
|
|
|
|
|
|
|
|
Self {
|
|
|
|
redis: redis_addr,
|
|
|
|
nextcloud: nextcloud_addr,
|
|
|
|
_redis_shutdown: redis_shutdown,
|
|
|
|
_nextcloud_shutdown: nextcloud_shutdown,
|
|
|
|
users,
|
|
|
|
db,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn config(&self) -> Config {
|
|
|
|
Config {
|
2021-02-11 22:23:18 +03:00
|
|
|
database: "sqlite::memory:?cache=shared".parse().unwrap(),
|
2021-02-02 03:14:27 +03:00
|
|
|
database_prefix: "oc_".to_string(),
|
2024-01-22 18:28:11 +03:00
|
|
|
redis: vec![format!("redis://{}", self.redis).parse().unwrap()],
|
2021-02-02 03:14:27 +03:00
|
|
|
nextcloud_url: format!("http://{}/", self.nextcloud),
|
2021-03-09 14:34:49 +03:00
|
|
|
metrics_bind: None,
|
2021-02-25 18:15:43 +03:00
|
|
|
log_level: "".to_string(),
|
2021-12-10 16:49:51 +03:00
|
|
|
bind: Bind::Tcp(self.nextcloud),
|
2021-02-26 17:02:41 +03:00
|
|
|
allow_self_signed: false,
|
2021-06-01 19:43:47 +03:00
|
|
|
no_ansi: false,
|
2021-11-11 19:23:23 +03:00
|
|
|
tls: None,
|
2022-04-29 18:29:31 +03:00
|
|
|
max_debounce_time: 15,
|
2023-06-10 13:57:22 +03:00
|
|
|
max_connection_time: 0,
|
2021-02-02 03:14:27 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn app(&self) -> App {
|
|
|
|
let config = self.config();
|
2021-02-11 23:58:50 +03:00
|
|
|
App::with_connection(self.db.clone(), config, LOG_HANDLE.clone(), false)
|
2021-02-03 23:09:30 +03:00
|
|
|
.await
|
|
|
|
.unwrap()
|
2021-02-02 03:14:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
async fn spawn_server(&self) -> ServerHandle {
|
|
|
|
let app = Arc::new(self.app().await);
|
2021-02-25 18:15:43 +03:00
|
|
|
let addr = async {
|
2021-02-02 03:14:27 +03:00
|
|
|
let tcp = listen_available_port().await.unwrap();
|
2021-02-25 18:15:43 +03:00
|
|
|
tcp.local_addr()
|
2021-02-02 03:14:27 +03:00
|
|
|
}
|
2021-02-25 18:15:43 +03:00
|
|
|
.await
|
|
|
|
.unwrap();
|
2021-02-02 03:14:27 +03:00
|
|
|
|
2021-02-09 02:39:26 +03:00
|
|
|
let (serve_tx, serve_rx) = oneshot::channel();
|
|
|
|
let (listen_tx, listen_rx) = oneshot::channel();
|
2021-02-02 03:14:27 +03:00
|
|
|
|
2021-02-25 18:15:43 +03:00
|
|
|
let bind = Bind::Tcp(addr);
|
2021-02-02 03:14:27 +03:00
|
|
|
spawn(async move {
|
2023-06-10 13:57:22 +03:00
|
|
|
let serve = serve(app.clone(), bind, serve_rx, None, 15, 0).unwrap();
|
2021-02-09 02:39:26 +03:00
|
|
|
let listen = listen_loop(app.clone(), listen_rx);
|
|
|
|
|
2021-02-02 03:14:27 +03:00
|
|
|
pin_mut!(serve);
|
|
|
|
pin_mut!(listen);
|
2021-02-09 02:39:26 +03:00
|
|
|
|
|
|
|
select(serve, listen).await;
|
2021-02-02 03:14:27 +03:00
|
|
|
});
|
|
|
|
|
2021-02-09 02:39:26 +03:00
|
|
|
sleep(Duration::from_millis(10)).await;
|
2021-02-02 03:14:27 +03:00
|
|
|
|
2021-02-09 02:39:26 +03:00
|
|
|
ServerHandle {
|
|
|
|
_serve_handle: serve_tx,
|
|
|
|
_listen_handle: listen_tx,
|
2021-02-25 18:15:43 +03:00
|
|
|
port: addr.port(),
|
2021-02-09 02:39:26 +03:00
|
|
|
}
|
2021-02-02 03:14:27 +03:00
|
|
|
}
|
|
|
|
|
2024-03-11 18:20:11 +03:00
|
|
|
async fn redis_client(&self) -> redis::aio::MultiplexedConnection {
|
2021-03-30 15:37:10 +03:00
|
|
|
let client = redis::Client::open(self.config().redis.first().unwrap().clone()).unwrap();
|
2024-03-11 18:20:11 +03:00
|
|
|
client.get_multiplexed_async_connection().await.unwrap()
|
2021-02-02 03:14:27 +03:00
|
|
|
}
|
|
|
|
|
2021-02-02 03:30:12 +03:00
|
|
|
fn add_user(&self, username: &str, password: &str) {
|
|
|
|
self.users.insert(username.into(), password.into());
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn add_storage_mapping(&self, username: &str, storage: u32, root: u32) {
|
2024-05-23 18:24:46 +03:00
|
|
|
sqlx::query("INSERT INTO oc_mounts(storage_id, root_id, user_id) VALUES(?, ?, ?)")
|
2021-02-02 03:30:12 +03:00
|
|
|
.bind(storage as i64)
|
|
|
|
.bind(root as i64)
|
|
|
|
.bind(username)
|
|
|
|
.execute(&self.db)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
async fn add_filecache_item(&self, fileid: u32, path: &str) {
|
2024-05-23 18:24:46 +03:00
|
|
|
sqlx::query("INSERT INTO oc_filecache(fileid, path) VALUES(?, ?)")
|
2021-02-02 03:30:12 +03:00
|
|
|
.bind(fileid as i64)
|
|
|
|
.bind(path)
|
|
|
|
.execute(&self.db)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
2021-02-02 03:14:27 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct ServerHandle {
|
2021-02-09 02:39:26 +03:00
|
|
|
_serve_handle: oneshot::Sender<()>,
|
|
|
|
_listen_handle: oneshot::Sender<()>,
|
2021-02-02 03:14:27 +03:00
|
|
|
port: u16,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ServerHandle {
|
2021-04-12 17:21:09 +03:00
|
|
|
async fn connect(&self) -> WebSocketStream<MaybeTlsStream<TcpStream>> {
|
2021-02-02 03:14:27 +03:00
|
|
|
tokio_tungstenite::connect_async(format!("ws://127.0.0.1:{}/ws", self.port))
|
|
|
|
.await
|
|
|
|
.unwrap()
|
|
|
|
.0
|
|
|
|
}
|
|
|
|
|
2021-04-12 17:21:09 +03:00
|
|
|
async fn connect_auth(
|
|
|
|
&self,
|
|
|
|
username: &str,
|
|
|
|
password: &str,
|
|
|
|
) -> WebSocketStream<MaybeTlsStream<TcpStream>> {
|
2021-02-02 03:14:27 +03:00
|
|
|
let mut client =
|
|
|
|
tokio_tungstenite::connect_async(format!("ws://127.0.0.1:{}/ws", self.port))
|
|
|
|
.await
|
|
|
|
.unwrap()
|
|
|
|
.0;
|
|
|
|
|
|
|
|
client.send(Message::Text(username.into())).await.unwrap();
|
|
|
|
client.send(Message::Text(password.into())).await.unwrap();
|
|
|
|
|
|
|
|
assert_next_message(&mut client, "authenticated").await;
|
|
|
|
|
|
|
|
client
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-16 13:49:06 +03:00
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
2021-02-02 03:14:27 +03:00
|
|
|
async fn test_auth() {
|
|
|
|
let services = Services::new().await;
|
2021-02-02 03:30:12 +03:00
|
|
|
services.add_user("foo", "bar");
|
2021-02-02 03:14:27 +03:00
|
|
|
|
|
|
|
let server_handle = services.spawn_server().await;
|
|
|
|
let mut client = server_handle.connect().await;
|
|
|
|
client.send(Message::Text("foo".into())).await.unwrap();
|
|
|
|
client.send(Message::Text("bar".into())).await.unwrap();
|
|
|
|
|
|
|
|
assert_next_message(&mut client, "authenticated").await;
|
|
|
|
}
|
|
|
|
|
2021-06-16 13:49:06 +03:00
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
2021-02-02 03:14:27 +03:00
|
|
|
async fn test_auth_failure() {
|
|
|
|
let services = Services::new().await;
|
2021-02-02 03:30:12 +03:00
|
|
|
services.add_user("foo", "bar");
|
2021-02-02 03:14:27 +03:00
|
|
|
|
|
|
|
let server_handle = services.spawn_server().await;
|
|
|
|
let mut client = server_handle.connect().await;
|
|
|
|
client.send(Message::Text("foo".into())).await.unwrap();
|
|
|
|
client.send(Message::Text("not_bar".into())).await.unwrap();
|
|
|
|
|
|
|
|
assert_next_message(&mut client, "err: Invalid credentials").await;
|
|
|
|
}
|
|
|
|
|
2021-04-12 17:21:09 +03:00
|
|
|
async fn assert_next_message(
|
|
|
|
client: &mut WebSocketStream<MaybeTlsStream<TcpStream>>,
|
|
|
|
expected: &str,
|
|
|
|
) {
|
2022-05-18 01:46:36 +03:00
|
|
|
sleep(Duration::from_millis(100)).await;
|
2021-02-02 03:14:27 +03:00
|
|
|
assert_eq!(
|
2021-02-02 03:36:02 +03:00
|
|
|
timeout(Duration::from_millis(200), client.next())
|
2021-02-02 03:14:27 +03:00
|
|
|
.await
|
|
|
|
.unwrap()
|
|
|
|
.unwrap()
|
|
|
|
.unwrap(),
|
|
|
|
Message::Text(expected.to_string())
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-04-12 17:21:09 +03:00
|
|
|
async fn assert_no_message(client: &mut WebSocketStream<MaybeTlsStream<TcpStream>>) {
|
2021-06-16 13:49:06 +03:00
|
|
|
sleep(Duration::from_millis(5)).await;
|
2021-02-02 03:14:27 +03:00
|
|
|
assert!(timeout(Duration::from_millis(10), client.next())
|
|
|
|
.await
|
|
|
|
.is_err());
|
|
|
|
}
|
|
|
|
|
2021-06-16 13:49:06 +03:00
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
2021-02-02 03:14:27 +03:00
|
|
|
async fn test_notify_activity() {
|
|
|
|
let services = Services::new().await;
|
2021-02-02 03:30:12 +03:00
|
|
|
services.add_user("foo", "bar");
|
2021-02-02 03:14:27 +03:00
|
|
|
|
|
|
|
let server_handle = services.spawn_server().await;
|
|
|
|
let mut client = server_handle.connect_auth("foo", "bar").await;
|
|
|
|
|
|
|
|
let mut redis = services.redis_client().await;
|
|
|
|
redis
|
|
|
|
.publish::<_, _, ()>("notify_activity", r#"{"user":"foo"}"#)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
assert_next_message(&mut client, "notify_activity").await;
|
2021-06-16 13:49:06 +03:00
|
|
|
std::mem::forget(services);
|
2021-02-02 03:14:27 +03:00
|
|
|
}
|
|
|
|
|
2021-06-16 13:49:06 +03:00
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
2021-02-02 03:14:27 +03:00
|
|
|
async fn test_notify_activity_other_user() {
|
|
|
|
let services = Services::new().await;
|
2021-02-02 03:30:12 +03:00
|
|
|
services.add_user("foo", "bar");
|
2021-02-02 03:14:27 +03:00
|
|
|
|
|
|
|
let server_handle = services.spawn_server().await;
|
|
|
|
let mut client = server_handle.connect_auth("foo", "bar").await;
|
|
|
|
|
|
|
|
let mut redis = services.redis_client().await;
|
|
|
|
redis
|
|
|
|
.publish::<_, _, ()>("notify_activity", r#"{"user":"someone_else"}"#)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
assert_no_message(&mut client).await;
|
|
|
|
}
|
2021-02-02 03:30:12 +03:00
|
|
|
|
2021-06-16 13:49:06 +03:00
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
2021-02-02 03:30:12 +03:00
|
|
|
async fn test_notify_file() {
|
|
|
|
let services = Services::new().await;
|
|
|
|
services.add_user("foo", "bar");
|
|
|
|
services.add_filecache_item(10, "foo").await;
|
|
|
|
services.add_filecache_item(11, "foo/bar").await;
|
|
|
|
services.add_storage_mapping("foo", 10, 11).await;
|
|
|
|
|
|
|
|
let server_handle = services.spawn_server().await;
|
|
|
|
let mut client = server_handle.connect_auth("foo", "bar").await;
|
|
|
|
|
|
|
|
let mut redis = services.redis_client().await;
|
|
|
|
redis
|
|
|
|
.publish::<_, _, ()>(
|
|
|
|
"notify_storage_update",
|
2023-06-10 13:20:31 +03:00
|
|
|
r#"{"storage":10, "path":"foo/bar", "file_id":5}"#,
|
2021-02-02 03:30:12 +03:00
|
|
|
)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
assert_next_message(&mut client, "notify_file").await;
|
|
|
|
}
|
|
|
|
|
2021-06-16 13:49:06 +03:00
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
2021-02-02 03:30:12 +03:00
|
|
|
async fn test_notify_file_different_storage() {
|
|
|
|
let services = Services::new().await;
|
|
|
|
services.add_user("foo", "bar");
|
|
|
|
services.add_filecache_item(10, "foo").await;
|
|
|
|
services.add_filecache_item(11, "foo/bar").await;
|
|
|
|
services.add_storage_mapping("foo", 10, 11).await;
|
|
|
|
|
|
|
|
let server_handle = services.spawn_server().await;
|
|
|
|
let mut client = server_handle.connect_auth("foo", "bar").await;
|
|
|
|
|
|
|
|
let mut redis = services.redis_client().await;
|
|
|
|
redis
|
|
|
|
.publish::<_, _, ()>(
|
|
|
|
"notify_storage_update",
|
2023-06-10 13:20:31 +03:00
|
|
|
r#"{"storage":11, "path":"foo/bar", "file_id":5}"#,
|
2021-02-02 03:30:12 +03:00
|
|
|
)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
assert_no_message(&mut client).await;
|
|
|
|
}
|
|
|
|
|
2021-06-16 13:49:06 +03:00
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
2021-02-02 03:30:12 +03:00
|
|
|
async fn test_notify_file_multiple() {
|
|
|
|
let services = Services::new().await;
|
|
|
|
services.add_user("foo", "bar");
|
|
|
|
services.add_user("foo2", "bar");
|
|
|
|
services.add_user("foo3", "bar");
|
|
|
|
|
|
|
|
services.add_filecache_item(10, "foo").await;
|
|
|
|
services.add_filecache_item(11, "foo/bar").await;
|
|
|
|
services.add_filecache_item(12, "foo/outside").await;
|
|
|
|
|
|
|
|
services.add_storage_mapping("foo", 10, 10).await;
|
|
|
|
services.add_storage_mapping("foo2", 10, 11).await;
|
|
|
|
services.add_storage_mapping("foo2", 10, 12).await;
|
|
|
|
|
|
|
|
let server_handle = services.spawn_server().await;
|
|
|
|
let mut client1 = server_handle.connect_auth("foo", "bar").await;
|
|
|
|
let mut client2 = server_handle.connect_auth("foo2", "bar").await;
|
|
|
|
let mut client3 = server_handle.connect_auth("foo3", "bar").await;
|
|
|
|
|
|
|
|
let mut redis = services.redis_client().await;
|
|
|
|
redis
|
|
|
|
.publish::<_, _, ()>(
|
|
|
|
"notify_storage_update",
|
2023-06-10 13:20:31 +03:00
|
|
|
r#"{"storage":10, "path":"foo/bar", "file_id":5}"#,
|
2021-02-02 03:30:12 +03:00
|
|
|
)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
assert_next_message(&mut client1, "notify_file").await;
|
|
|
|
assert_next_message(&mut client2, "notify_file").await;
|
|
|
|
assert_no_message(&mut client3).await;
|
|
|
|
}
|
2021-02-02 03:36:02 +03:00
|
|
|
|
2021-06-16 13:49:06 +03:00
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
2021-02-02 03:36:02 +03:00
|
|
|
async fn test_pre_auth() {
|
|
|
|
let services = Services::new().await;
|
|
|
|
|
|
|
|
let server_handle = services.spawn_server().await;
|
|
|
|
|
2022-05-18 01:46:36 +03:00
|
|
|
sleep(Duration::from_millis(500)).await;
|
|
|
|
|
2021-02-02 03:36:02 +03:00
|
|
|
let mut redis = services.redis_client().await;
|
|
|
|
redis
|
|
|
|
.publish::<_, _, ()>("notify_pre_auth", r#"{"user":"foo", "token": "token"}"#)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
2021-02-09 02:39:26 +03:00
|
|
|
sleep(Duration::from_millis(100)).await;
|
2021-02-03 23:57:34 +03:00
|
|
|
|
2021-02-02 03:36:02 +03:00
|
|
|
let mut client = server_handle.connect_auth("", "token").await;
|
|
|
|
|
|
|
|
// verify that we are the correct user
|
|
|
|
redis
|
|
|
|
.publish::<_, _, ()>("notify_activity", r#"{"user":"foo"}"#)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
assert_next_message(&mut client, "notify_activity").await;
|
|
|
|
}
|
2021-02-05 22:37:43 +03:00
|
|
|
|
2021-06-16 13:49:06 +03:00
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
2021-02-05 22:37:43 +03:00
|
|
|
async fn test_notify_notification() {
|
|
|
|
let services = Services::new().await;
|
|
|
|
services.add_user("foo", "bar");
|
|
|
|
services.add_user("foo2", "bar");
|
|
|
|
|
|
|
|
let server_handle = services.spawn_server().await;
|
|
|
|
let mut client1 = server_handle.connect_auth("foo", "bar").await;
|
|
|
|
let mut client2 = server_handle.connect_auth("foo2", "bar").await;
|
|
|
|
|
|
|
|
let mut redis = services.redis_client().await;
|
|
|
|
redis
|
|
|
|
.publish::<_, _, ()>("notify_notification", r#"{"user":"foo"}"#)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
assert_next_message(&mut client1, "notify_notification").await;
|
|
|
|
assert_no_message(&mut client2).await;
|
|
|
|
}
|
|
|
|
|
2021-06-16 13:49:06 +03:00
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
2021-02-05 22:37:43 +03:00
|
|
|
async fn test_notify_share() {
|
|
|
|
let services = Services::new().await;
|
|
|
|
services.add_user("foo", "bar");
|
|
|
|
services.add_user("foo2", "bar");
|
|
|
|
|
|
|
|
let server_handle = services.spawn_server().await;
|
|
|
|
let mut client1 = server_handle.connect_auth("foo", "bar").await;
|
|
|
|
let mut client2 = server_handle.connect_auth("foo2", "bar").await;
|
|
|
|
|
|
|
|
let mut redis = services.redis_client().await;
|
|
|
|
redis
|
|
|
|
.publish::<_, _, ()>("notify_user_share_created", r#"{"user":"foo"}"#)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
assert_next_message(&mut client1, "notify_file").await;
|
|
|
|
assert_no_message(&mut client2).await;
|
|
|
|
}
|
|
|
|
|
2021-06-16 13:49:06 +03:00
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
2021-02-05 22:37:43 +03:00
|
|
|
async fn test_notify_group() {
|
|
|
|
let services = Services::new().await;
|
|
|
|
services.add_user("foo", "bar");
|
|
|
|
services.add_user("foo2", "bar");
|
|
|
|
|
|
|
|
let server_handle = services.spawn_server().await;
|
|
|
|
let mut client1 = server_handle.connect_auth("foo", "bar").await;
|
|
|
|
let mut client2 = server_handle.connect_auth("foo2", "bar").await;
|
|
|
|
|
|
|
|
let mut redis = services.redis_client().await;
|
|
|
|
redis
|
|
|
|
.publish::<_, _, ()>(
|
|
|
|
"notify_group_membership_update",
|
|
|
|
r#"{"user":"foo", "group":"asd"}"#,
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
assert_next_message(&mut client1, "notify_file").await;
|
|
|
|
assert_no_message(&mut client2).await;
|
|
|
|
}
|
|
|
|
|
2021-06-16 13:49:06 +03:00
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
2021-02-05 22:37:43 +03:00
|
|
|
async fn test_notify_custom() {
|
|
|
|
let services = Services::new().await;
|
|
|
|
services.add_user("foo", "bar");
|
|
|
|
services.add_user("foo2", "bar");
|
|
|
|
|
|
|
|
let server_handle = services.spawn_server().await;
|
|
|
|
let mut client1 = server_handle.connect_auth("foo", "bar").await;
|
|
|
|
let mut client2 = server_handle.connect_auth("foo2", "bar").await;
|
|
|
|
|
|
|
|
let mut redis = services.redis_client().await;
|
|
|
|
redis
|
|
|
|
.publish::<_, _, ()>(
|
|
|
|
"notify_custom",
|
|
|
|
r#"{"user":"foo", "message":"my_custom_message"}"#,
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
assert_next_message(&mut client1, "my_custom_message").await;
|
|
|
|
assert_no_message(&mut client2).await;
|
|
|
|
}
|
|
|
|
|
2021-06-16 13:49:06 +03:00
|
|
|
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
|
2021-02-05 22:37:43 +03:00
|
|
|
async fn test_notify_custom_body() {
|
|
|
|
let services = Services::new().await;
|
|
|
|
services.add_user("foo", "bar");
|
|
|
|
services.add_user("foo2", "bar");
|
|
|
|
|
|
|
|
let server_handle = services.spawn_server().await;
|
|
|
|
let mut client1 = server_handle.connect_auth("foo", "bar").await;
|
|
|
|
let mut client2 = server_handle.connect_auth("foo2", "bar").await;
|
|
|
|
|
|
|
|
let mut redis = services.redis_client().await;
|
|
|
|
redis
|
|
|
|
.publish::<_, _, ()>(
|
|
|
|
"notify_custom",
|
|
|
|
r#"{"user":"foo", "message":"my_custom_message", "body": [1,2,3]}"#,
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
assert_next_message(&mut client1, "my_custom_message [1,2,3]").await;
|
|
|
|
assert_no_message(&mut client2).await;
|
|
|
|
}
|