fix share password issues
This commit is contained in:
@@ -60,6 +60,9 @@ pub trait WarrenMetrics: Clone + Send + Sync + 'static {
|
|||||||
|
|
||||||
fn record_warren_share_cat_success(&self) -> impl Future<Output = ()> + Send;
|
fn record_warren_share_cat_success(&self) -> impl Future<Output = ()> + Send;
|
||||||
fn record_warren_share_cat_failure(&self) -> impl Future<Output = ()> + Send;
|
fn record_warren_share_cat_failure(&self) -> impl Future<Output = ()> + Send;
|
||||||
|
|
||||||
|
fn record_warren_share_password_verification_success(&self) -> impl Future<Output = ()> + Send;
|
||||||
|
fn record_warren_share_password_verification_failure(&self) -> impl Future<Output = ()> + Send;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FileSystemMetrics: Clone + Send + Sync + 'static {
|
pub trait FileSystemMetrics: Clone + Send + Sync + 'static {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ use super::models::{
|
|||||||
DeleteShareError, DeleteShareRequest, DeleteShareResponse, GetShareError, GetShareRequest,
|
DeleteShareError, DeleteShareRequest, DeleteShareResponse, GetShareError, GetShareRequest,
|
||||||
GetShareResponse, ListSharesError, ListSharesRequest, ListSharesResponse, ShareCatError,
|
GetShareResponse, ListSharesError, ListSharesRequest, ListSharesResponse, ShareCatError,
|
||||||
ShareCatRequest, ShareCatResponse, ShareLsError, ShareLsRequest, ShareLsResponse,
|
ShareCatRequest, ShareCatResponse, ShareLsError, ShareLsRequest, ShareLsResponse,
|
||||||
|
VerifySharePasswordError, VerifySharePasswordRequest, VerifySharePasswordResponse,
|
||||||
},
|
},
|
||||||
user::{
|
user::{
|
||||||
CreateUserError, CreateUserRequest, DeleteUserError, DeleteUserRequest, EditUserError,
|
CreateUserError, CreateUserRequest, DeleteUserError, DeleteUserRequest, EditUserError,
|
||||||
@@ -138,6 +139,10 @@ pub trait WarrenService: Clone + Send + Sync + 'static {
|
|||||||
&self,
|
&self,
|
||||||
request: ShareCatRequest,
|
request: ShareCatRequest,
|
||||||
) -> impl Future<Output = Result<ShareCatResponse, ShareCatError>> + Send;
|
) -> impl Future<Output = Result<ShareCatResponse, ShareCatError>> + Send;
|
||||||
|
fn verify_warren_share_password(
|
||||||
|
&self,
|
||||||
|
request: VerifySharePasswordRequest,
|
||||||
|
) -> impl Future<Output = Result<VerifySharePasswordResponse, VerifySharePasswordError>> + Send;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FileSystemService: Clone + Send + Sync + 'static {
|
pub trait FileSystemService: Clone + Send + Sync + 'static {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ use crate::domain::warren::models::{
|
|||||||
file::{AbsoluteFilePath, AbsoluteFilePathList, LsResponse},
|
file::{AbsoluteFilePath, AbsoluteFilePathList, LsResponse},
|
||||||
share::{
|
share::{
|
||||||
CreateShareResponse, DeleteShareResponse, GetShareResponse, ListSharesResponse,
|
CreateShareResponse, DeleteShareResponse, GetShareResponse, ListSharesResponse,
|
||||||
ShareCatResponse, ShareLsResponse,
|
ShareCatResponse, ShareLsResponse, VerifySharePasswordResponse,
|
||||||
},
|
},
|
||||||
user::{ListAllUsersAndWarrensResponse, LoginUserOidcResponse, LoginUserResponse, User},
|
user::{ListAllUsersAndWarrensResponse, LoginUserOidcResponse, LoginUserResponse, User},
|
||||||
user_warren::UserWarren,
|
user_warren::UserWarren,
|
||||||
@@ -64,6 +64,10 @@ pub trait WarrenNotifier: Clone + Send + Sync + 'static {
|
|||||||
) -> impl Future<Output = ()> + Send;
|
) -> impl Future<Output = ()> + Send;
|
||||||
fn warren_share_ls(&self, response: &ShareLsResponse) -> impl Future<Output = ()> + Send;
|
fn warren_share_ls(&self, response: &ShareLsResponse) -> impl Future<Output = ()> + Send;
|
||||||
fn warren_share_cat(&self, response: &ShareCatResponse) -> impl Future<Output = ()> + Send;
|
fn warren_share_cat(&self, response: &ShareCatResponse) -> impl Future<Output = ()> + Send;
|
||||||
|
fn warren_share_password_verified(
|
||||||
|
&self,
|
||||||
|
response: &VerifySharePasswordResponse,
|
||||||
|
) -> impl Future<Output = ()> + Send;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait FileSystemNotifier: Clone + Send + Sync + 'static {
|
pub trait FileSystemNotifier: Clone + Send + Sync + 'static {
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ use crate::domain::warren::{
|
|||||||
DeleteShareRequest, DeleteShareResponse, GetShareError, GetShareRequest,
|
DeleteShareRequest, DeleteShareResponse, GetShareError, GetShareRequest,
|
||||||
GetShareResponse, ListSharesError, ListSharesRequest, ListSharesResponse, Share,
|
GetShareResponse, ListSharesError, ListSharesRequest, ListSharesResponse, Share,
|
||||||
ShareCatError, ShareCatRequest, ShareCatResponse, ShareLsError, ShareLsRequest,
|
ShareCatError, ShareCatRequest, ShareCatResponse, ShareLsError, ShareLsRequest,
|
||||||
ShareLsResponse,
|
ShareLsResponse, VerifySharePasswordError, VerifySharePasswordRequest,
|
||||||
|
VerifySharePasswordResponse,
|
||||||
},
|
},
|
||||||
warren::{
|
warren::{
|
||||||
CreateWarrenError, CreateWarrenRequest, DeleteWarrenError, DeleteWarrenRequest,
|
CreateWarrenError, CreateWarrenRequest, DeleteWarrenError, DeleteWarrenRequest,
|
||||||
@@ -528,4 +529,24 @@ where
|
|||||||
|
|
||||||
Ok(response)
|
Ok(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn verify_warren_share_password(
|
||||||
|
&self,
|
||||||
|
request: VerifySharePasswordRequest,
|
||||||
|
) -> Result<VerifySharePasswordResponse, VerifySharePasswordError> {
|
||||||
|
let result = self.repository.verify_warren_share_password(request).await;
|
||||||
|
|
||||||
|
if let Ok(response) = result.as_ref() {
|
||||||
|
self.metrics
|
||||||
|
.record_warren_share_password_verification_success()
|
||||||
|
.await;
|
||||||
|
self.notifier.warren_share_password_verified(response).await;
|
||||||
|
} else {
|
||||||
|
self.metrics
|
||||||
|
.record_warren_share_password_verification_failure()
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
inbound::http::{
|
inbound::http::{
|
||||||
AppState,
|
AppState,
|
||||||
|
handlers::extractors::SharePasswordHeader,
|
||||||
responses::{ApiError, ApiSuccess},
|
responses::{ApiError, ApiSuccess},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -59,17 +60,14 @@ impl From<ParseShareLsHttpRequestError> for ApiError {
|
|||||||
pub(super) struct LsShareHttpRequestBody {
|
pub(super) struct LsShareHttpRequestBody {
|
||||||
share_id: Uuid,
|
share_id: Uuid,
|
||||||
path: String,
|
path: String,
|
||||||
password: Option<String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LsShareHttpRequestBody {
|
impl LsShareHttpRequestBody {
|
||||||
fn try_into_domain(self) -> Result<ShareLsRequest, ParseShareLsHttpRequestError> {
|
fn try_into_domain(
|
||||||
|
self,
|
||||||
|
password: Option<SharePassword>,
|
||||||
|
) -> Result<ShareLsRequest, ParseShareLsHttpRequestError> {
|
||||||
let path = FilePath::new(&self.path)?.try_into()?;
|
let path = FilePath::new(&self.path)?.try_into()?;
|
||||||
let password = if let Some(password) = self.password.as_ref() {
|
|
||||||
Some(SharePassword::new(password)?)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(ShareLsRequest::new(self.share_id, path, password))
|
Ok(ShareLsRequest::new(self.share_id, path, password))
|
||||||
}
|
}
|
||||||
@@ -98,9 +96,10 @@ impl From<ShareLsResponse> for ShareLsResponseData {
|
|||||||
|
|
||||||
pub async fn ls_share<WS: WarrenService, AS: AuthService>(
|
pub async fn ls_share<WS: WarrenService, AS: AuthService>(
|
||||||
State(state): State<AppState<WS, AS>>,
|
State(state): State<AppState<WS, AS>>,
|
||||||
|
SharePasswordHeader(password): SharePasswordHeader,
|
||||||
Json(request): Json<LsShareHttpRequestBody>,
|
Json(request): Json<LsShareHttpRequestBody>,
|
||||||
) -> Result<ApiSuccess<ShareLsResponseData>, ApiError> {
|
) -> Result<ApiSuccess<ShareLsResponseData>, ApiError> {
|
||||||
let domain_request = request.try_into_domain()?;
|
let domain_request = request.try_into_domain(password)?;
|
||||||
|
|
||||||
state
|
state
|
||||||
.warren_service
|
.warren_service
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ mod list_shares;
|
|||||||
mod list_warrens;
|
mod list_warrens;
|
||||||
mod ls_share;
|
mod ls_share;
|
||||||
mod upload_warren_files;
|
mod upload_warren_files;
|
||||||
|
mod verify_share_password;
|
||||||
mod warren_cat;
|
mod warren_cat;
|
||||||
mod warren_cp;
|
mod warren_cp;
|
||||||
mod warren_ls;
|
mod warren_ls;
|
||||||
@@ -37,6 +38,7 @@ use get_share::get_share;
|
|||||||
use list_shares::list_shares;
|
use list_shares::list_shares;
|
||||||
use ls_share::ls_share;
|
use ls_share::ls_share;
|
||||||
use upload_warren_files::warren_save;
|
use upload_warren_files::warren_save;
|
||||||
|
use verify_share_password::verify_share_password;
|
||||||
use warren_cat::fetch_file;
|
use warren_cat::fetch_file;
|
||||||
use warren_cp::warren_cp;
|
use warren_cp::warren_cp;
|
||||||
use warren_mv::warren_mv;
|
use warren_mv::warren_mv;
|
||||||
@@ -116,4 +118,5 @@ pub fn routes<WS: WarrenService, AS: AuthService>() -> Router<AppState<WS, AS>>
|
|||||||
.route("/files/get_share", post(get_share))
|
.route("/files/get_share", post(get_share))
|
||||||
.route("/files/ls_share", post(ls_share))
|
.route("/files/ls_share", post(ls_share))
|
||||||
.route("/files/cat_share", get(cat_share))
|
.route("/files/cat_share", get(cat_share))
|
||||||
|
.route("/files/verify_share_password", post(verify_share_password))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
use axum::{Json, extract::State, http::StatusCode};
|
||||||
|
use serde::Deserialize;
|
||||||
|
use thiserror::Error;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
domain::warren::{
|
||||||
|
models::share::{SharePassword, SharePasswordError, VerifySharePasswordRequest},
|
||||||
|
ports::{AuthService, WarrenService},
|
||||||
|
},
|
||||||
|
inbound::http::{
|
||||||
|
AppState,
|
||||||
|
responses::{ApiError, ApiSuccess},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
enum ParseVerifySharePasswordHttpRequestError {
|
||||||
|
#[error(transparent)]
|
||||||
|
SharePassword(#[from] SharePasswordError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ParseVerifySharePasswordHttpRequestError> for ApiError {
|
||||||
|
fn from(value: ParseVerifySharePasswordHttpRequestError) -> Self {
|
||||||
|
match value {
|
||||||
|
ParseVerifySharePasswordHttpRequestError::SharePassword(err) => Self::BadRequest(
|
||||||
|
match err {
|
||||||
|
SharePasswordError::Empty => "The provided password is empty",
|
||||||
|
SharePasswordError::LeadingWhitespace
|
||||||
|
| SharePasswordError::TrailingWhitespace
|
||||||
|
| SharePasswordError::TooShort
|
||||||
|
| SharePasswordError::TooLong => "",
|
||||||
|
}
|
||||||
|
.to_string(),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(super) struct VerifySharePasswordHttpRequestBody {
|
||||||
|
share_id: Uuid,
|
||||||
|
password: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VerifySharePasswordHttpRequestBody {
|
||||||
|
fn try_into_domain(
|
||||||
|
self,
|
||||||
|
) -> Result<VerifySharePasswordRequest, ParseVerifySharePasswordHttpRequestError> {
|
||||||
|
let password = SharePassword::new(&self.password)?;
|
||||||
|
|
||||||
|
Ok(VerifySharePasswordRequest::new(
|
||||||
|
self.share_id,
|
||||||
|
Some(password),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn verify_share_password<WS: WarrenService, AS: AuthService>(
|
||||||
|
State(state): State<AppState<WS, AS>>,
|
||||||
|
Json(request): Json<VerifySharePasswordHttpRequestBody>,
|
||||||
|
) -> Result<ApiSuccess<()>, ApiError> {
|
||||||
|
let domain_request = request.try_into_domain()?;
|
||||||
|
|
||||||
|
state
|
||||||
|
.warren_service
|
||||||
|
.verify_warren_share_password(domain_request)
|
||||||
|
.await
|
||||||
|
.map(|_| ApiSuccess::new(StatusCode::OK, ()))
|
||||||
|
.map_err(ApiError::from)
|
||||||
|
}
|
||||||
@@ -151,6 +151,13 @@ impl WarrenMetrics for MetricsDebugLogger {
|
|||||||
async fn record_warren_share_cat_failure(&self) {
|
async fn record_warren_share_cat_failure(&self) {
|
||||||
tracing::debug!("[Metrics] Warren share cat failed");
|
tracing::debug!("[Metrics] Warren share cat failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn record_warren_share_password_verification_success(&self) {
|
||||||
|
tracing::debug!("[Metrics] Warren share password verification succeeded");
|
||||||
|
}
|
||||||
|
async fn record_warren_share_password_verification_failure(&self) {
|
||||||
|
tracing::debug!("[Metrics] Warren share password verification failed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FileSystemMetrics for MetricsDebugLogger {
|
impl FileSystemMetrics for MetricsDebugLogger {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use crate::domain::{
|
|||||||
file::{AbsoluteFilePath, AbsoluteFilePathList, LsResponse},
|
file::{AbsoluteFilePath, AbsoluteFilePathList, LsResponse},
|
||||||
share::{
|
share::{
|
||||||
CreateShareResponse, DeleteShareResponse, GetShareResponse, ListSharesResponse,
|
CreateShareResponse, DeleteShareResponse, GetShareResponse, ListSharesResponse,
|
||||||
ShareCatResponse, ShareLsResponse,
|
ShareCatResponse, ShareLsResponse, VerifySharePasswordResponse,
|
||||||
},
|
},
|
||||||
user::{
|
user::{
|
||||||
ListAllUsersAndWarrensResponse, LoginUserOidcResponse, LoginUserResponse, User,
|
ListAllUsersAndWarrensResponse, LoginUserOidcResponse, LoginUserResponse, User,
|
||||||
@@ -201,6 +201,13 @@ impl WarrenNotifier for NotifierDebugLogger {
|
|||||||
response.share().id(),
|
response.share().id(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn warren_share_password_verified(&self, response: &VerifySharePasswordResponse) {
|
||||||
|
tracing::debug!(
|
||||||
|
"[Notifier] Verified password for share {}",
|
||||||
|
response.share().id()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FileSystemNotifier for NotifierDebugLogger {
|
impl FileSystemNotifier for NotifierDebugLogger {
|
||||||
|
|||||||
@@ -120,19 +120,24 @@ export async function listShareFiles(
|
|||||||
| { success: true; files: DirectoryEntry[]; parent: DirectoryEntry | null }
|
| { success: true; files: DirectoryEntry[]; parent: DirectoryEntry | null }
|
||||||
| { success: false }
|
| { success: false }
|
||||||
> {
|
> {
|
||||||
const { data } = await useFetch<
|
const { data, error } = await useFetch<
|
||||||
ApiResponse<{ files: DirectoryEntry[]; parent: DirectoryEntry | null }>
|
ApiResponse<{ files: DirectoryEntry[]; parent: DirectoryEntry | null }>
|
||||||
>(getApiUrl('warrens/files/ls_share'), {
|
>(getApiUrl('warrens/files/ls_share'), {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: getApiHeaders(),
|
// This is only required for development
|
||||||
|
headers:
|
||||||
|
password != null
|
||||||
|
? { ...getApiHeaders(), 'X-Share-Password': password }
|
||||||
|
: getApiHeaders(),
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
shareId: shareId,
|
shareId: shareId,
|
||||||
path: path,
|
path: path,
|
||||||
password: password,
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (data.value == null) {
|
if (data.value == null) {
|
||||||
|
const errorMessage = await error.value?.data;
|
||||||
|
console.log(errorMessage);
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
};
|
};
|
||||||
@@ -174,3 +179,32 @@ export async function fetchShareFile(
|
|||||||
data: data.value,
|
data: data.value,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function verifySharePassword(
|
||||||
|
shareId: string,
|
||||||
|
password: string
|
||||||
|
): Promise<{ success: boolean }> {
|
||||||
|
const { data } = await useFetch<ApiResponse<null>>(
|
||||||
|
getApiUrl(`warrens/files/verify_share_password`),
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
headers: getApiHeaders(),
|
||||||
|
body: JSON.stringify({
|
||||||
|
shareId: shareId,
|
||||||
|
password: password,
|
||||||
|
}),
|
||||||
|
responseType: 'json',
|
||||||
|
cache: 'default',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (data.value == null || data.value.status !== 200) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { fetchShareFile, getShare, listShareFiles } from '~/lib/api/shares';
|
import byteSize from 'byte-size';
|
||||||
|
import { toast } from 'vue-sonner';
|
||||||
|
import {
|
||||||
|
fetchShareFile,
|
||||||
|
getShare,
|
||||||
|
listShareFiles,
|
||||||
|
verifySharePassword,
|
||||||
|
} from '~/lib/api/shares';
|
||||||
import type { DirectoryEntry } from '~/shared/types';
|
import type { DirectoryEntry } from '~/shared/types';
|
||||||
import type { Share } from '~/shared/types/shares';
|
import type { Share } from '~/shared/types/shares';
|
||||||
import { useImageViewer, useTextEditor } from '~/stores/viewers';
|
import { useImageViewer, useTextEditor } from '~/stores/viewers';
|
||||||
@@ -60,7 +67,39 @@ async function getShareFromQuery(): Promise<{
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function submitPassword() {
|
async function submitPassword() {
|
||||||
loadFiles();
|
if (share == null || loading.value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!passwordValid.value) {
|
||||||
|
loading.value = true;
|
||||||
|
const result = await verifySharePassword(share.data.id, password.value);
|
||||||
|
loading.value = false;
|
||||||
|
|
||||||
|
if (result.success) {
|
||||||
|
passwordValid.value = true;
|
||||||
|
let cookie = `X-Share-Password=${password.value}; Path=/; SameSite=Lax; Secure;`;
|
||||||
|
|
||||||
|
if (share.data.expiresAt != null) {
|
||||||
|
const dayjs = useDayjs();
|
||||||
|
|
||||||
|
const diff = dayjs(share.data.expiresAt).diff(dayjs()) / 1000;
|
||||||
|
cookie += `Max-Age=${diff};`;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.cookie = cookie;
|
||||||
|
} else {
|
||||||
|
toast.error('Share', {
|
||||||
|
id: 'SHARE_PASSWORD_TOAST',
|
||||||
|
description: 'Invalid password',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (share.file.fileType === 'directory') {
|
||||||
|
loadFiles();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadFiles() {
|
async function loadFiles() {
|
||||||
@@ -68,10 +107,6 @@ async function loadFiles() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (share.file.fileType !== 'directory') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
|
|
||||||
const result = await listShareFiles(
|
const result = await listShareFiles(
|
||||||
@@ -81,18 +116,6 @@ async function loadFiles() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
passwordValid.value = true;
|
|
||||||
let cookie = `X-Share-Password=${password.value}; Path=/; SameSite=Lax; Secure;`;
|
|
||||||
|
|
||||||
if (share.data.expiresAt != null) {
|
|
||||||
const dayjs = useDayjs();
|
|
||||||
|
|
||||||
const diff = dayjs(share.data.expiresAt).diff(dayjs()) / 1000;
|
|
||||||
cookie += `Max-Age=${diff};`;
|
|
||||||
}
|
|
||||||
|
|
||||||
document.cookie = cookie;
|
|
||||||
|
|
||||||
warrenStore.setCurrentWarrenEntries(result.files, result.parent);
|
warrenStore.setCurrentWarrenEntries(result.files, result.parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,7 +125,11 @@ async function loadFiles() {
|
|||||||
async function onEntryClicked(entry: DirectoryEntry, event: MouseEvent) {
|
async function onEntryClicked(entry: DirectoryEntry, event: MouseEvent) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
if (warrenStore.current == null) {
|
if (
|
||||||
|
warrenStore.current == null ||
|
||||||
|
share == null ||
|
||||||
|
(share.data.password && !passwordValid.value)
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +137,10 @@ async function onEntryClicked(entry: DirectoryEntry, event: MouseEvent) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const entryPath = joinPaths(warrenStore.current.path, entry.name);
|
const entryPath =
|
||||||
|
entry !== share.file
|
||||||
|
? joinPaths(warrenStore.current.path, entry.name)
|
||||||
|
: warrenStore.current.path;
|
||||||
|
|
||||||
if (entry.fileType === 'directory') {
|
if (entry.fileType === 'directory') {
|
||||||
warrenStore.setCurrentWarrenPath(entryPath);
|
warrenStore.setCurrentWarrenPath(entryPath);
|
||||||
@@ -217,17 +247,35 @@ function onEntryDownload(entry: DirectoryEntry) {
|
|||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
:class="[
|
:class="[
|
||||||
'h-[min(98vh,600px)] w-full max-w-screen-xl rounded-lg border transition-all',
|
'w-full rounded-lg border transition-all',
|
||||||
passwordValid ? 'max-w-screen-xl' : 'max-w-lg',
|
passwordValid && share.file.fileType === 'directory'
|
||||||
|
? 'h-[min(98vh,600px)] max-w-screen-xl'
|
||||||
|
: 'max-w-2xl',
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
<div
|
<div class="flex flex-row items-center justify-between gap-4 p-6">
|
||||||
class="flex flex-row items-center justify-between gap-4 px-6 pt-6"
|
<button
|
||||||
>
|
:disabled="share.data.password && !passwordValid"
|
||||||
<div class="flex w-full flex-row">
|
:class="[
|
||||||
<div class="flex grow flex-col gap-1.5">
|
'flex min-w-0 grow flex-row items-center gap-2 text-left',
|
||||||
<h3 class="leading-none font-semibold">Share</h3>
|
(!share.data.password || passwordValid) &&
|
||||||
<p class="text-muted-foreground text-sm">
|
'cursor-pointer',
|
||||||
|
]"
|
||||||
|
@click="(e) => onEntryClicked(share!.file, e)"
|
||||||
|
>
|
||||||
|
<DirectoryEntryIcon :entry="share.file" />
|
||||||
|
|
||||||
|
<div class="flex flex-col overflow-hidden">
|
||||||
|
<h3
|
||||||
|
:title="share.file.name"
|
||||||
|
class="truncate leading-none font-semibold"
|
||||||
|
>
|
||||||
|
{{ share.file.name }}
|
||||||
|
</h3>
|
||||||
|
<p class="text-muted-foreground text-sm text-nowrap">
|
||||||
|
{{ byteSize(share.file.size) }}
|
||||||
|
</p>
|
||||||
|
<p class="text-muted-foreground text-sm text-nowrap">
|
||||||
Created
|
Created
|
||||||
{{
|
{{
|
||||||
$dayjs(share.data.createdAt).format(
|
$dayjs(share.data.createdAt).format(
|
||||||
@@ -236,19 +284,12 @@ function onEntryDownload(entry: DirectoryEntry) {
|
|||||||
}}
|
}}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row items-center justify-end gap-4">
|
</button>
|
||||||
<p>{{ share.file.name }}</p>
|
|
||||||
<DirectoryEntryIcon
|
|
||||||
:entry="{ ...share.file, name: '/' }"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-row items-end">
|
<div class="flex flex-row items-end">
|
||||||
<Button
|
<Button
|
||||||
:class="
|
:class="
|
||||||
share.file.fileType !== 'file' &&
|
share.data.password && !passwordValid && 'hidden'
|
||||||
entries == null &&
|
|
||||||
'hidden'
|
|
||||||
"
|
"
|
||||||
size="icon"
|
size="icon"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
@@ -258,7 +299,13 @@ function onEntryDownload(entry: DirectoryEntry) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex w-full flex-col p-6">
|
<div
|
||||||
|
v-if="
|
||||||
|
share.file.fileType === 'directory' ||
|
||||||
|
(share.data.password && !passwordValid)
|
||||||
|
"
|
||||||
|
class="flex w-full flex-col px-6 pb-6"
|
||||||
|
>
|
||||||
<DirectoryList
|
<DirectoryList
|
||||||
v-if="entries != null"
|
v-if="entries != null"
|
||||||
:entries
|
:entries
|
||||||
|
|||||||
Reference in New Issue
Block a user