Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3864b62a4 | ||
|
|
22176f4e0f | ||
|
|
a89d7ec0ea | ||
|
|
8262049e20 | ||
|
|
c61e1e0a2a | ||
|
|
b376cf6c65 |
7
.github/workflows/vulncheck.yaml
vendored
7
.github/workflows/vulncheck.yaml
vendored
@@ -50,11 +50,4 @@ jobs:
|
||||
working-directory: ./web-app
|
||||
continue-on-error: false
|
||||
run: |
|
||||
# Ignore "pdfjs-dist" advisory, because it's a dependency
|
||||
# of "react-pdf" that cannot be upgraded. Because the
|
||||
# "isEvalSupported" value is always set to "false", it
|
||||
# isn't a security problem. See also
|
||||
# - https://github.com/wojtekmaj/react-pdf/issues/1789
|
||||
# - https://github.com/wojtekmaj/react-pdf/discussions/1786
|
||||
# - https://www.npmjs.com/advisories/1097244
|
||||
yarn npm audit --recursive --environment production --no-deprecations
|
||||
|
||||
12
CHANGELOG.md
12
CHANGELOG.md
@@ -2,6 +2,18 @@
|
||||
|
||||
# Changelog
|
||||
|
||||
## Release v1.6.1
|
||||
|
||||
Bug Fix:
|
||||
|
||||
- Fixed objectManager issues under certain conditions
|
||||
- Fixed Security vulnerability in dependencies
|
||||
|
||||
Additional Changes:
|
||||
|
||||
- Improved Share Link behavior
|
||||
|
||||
|
||||
## Release v1.6.0
|
||||
|
||||
Bug Fix:
|
||||
|
||||
@@ -35,9 +35,11 @@ func (wsc *wsMinioClient) objectManager(session *models.Principal) {
|
||||
defer func() {
|
||||
// We close socket at the end of requests
|
||||
wsc.conn.close()
|
||||
cancelContexts.Range(func(_, value interface{}) bool {
|
||||
cancelContexts.Range(func(key, value interface{}) bool {
|
||||
cancelFunc := value.(context.CancelFunc)
|
||||
cancelFunc()
|
||||
|
||||
cancelContexts.Delete(key)
|
||||
return true
|
||||
})
|
||||
}()
|
||||
@@ -55,6 +57,7 @@ func (wsc *wsMinioClient) objectManager(session *models.Principal) {
|
||||
// Read goroutine
|
||||
go func() {
|
||||
defer close(writeChannel)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-done:
|
||||
@@ -72,10 +75,9 @@ func (wsc *wsMinioClient) objectManager(session *models.Principal) {
|
||||
// We get request data & review information
|
||||
var messageRequest ObjectsRequest
|
||||
|
||||
err := json.Unmarshal(message, &messageRequest)
|
||||
if err != nil {
|
||||
LogInfo("Error on message request unmarshal")
|
||||
return
|
||||
if err := json.Unmarshal(message, &messageRequest); err != nil {
|
||||
LogInfo("Error on message request unmarshal", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// new message, new context
|
||||
@@ -84,6 +86,21 @@ func (wsc *wsMinioClient) objectManager(session *models.Principal) {
|
||||
// We store the cancel func associated with this request
|
||||
cancelContexts.Store(messageRequest.RequestID, cancel)
|
||||
|
||||
switch messageRequest.Mode {
|
||||
case "objects", "rewind":
|
||||
// cancel all previous open objects requests for listing
|
||||
cancelContexts.Range(func(key, value interface{}) bool {
|
||||
rid := key.(int64)
|
||||
if rid < messageRequest.RequestID {
|
||||
cancelFunc := value.(context.CancelFunc)
|
||||
cancelFunc()
|
||||
|
||||
cancelContexts.Delete(key)
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
const itemsPerBatch = 1000
|
||||
switch messageRequest.Mode {
|
||||
case "close":
|
||||
@@ -95,173 +112,151 @@ func (wsc *wsMinioClient) objectManager(session *models.Principal) {
|
||||
cancelContexts.Delete(messageRequest.RequestID)
|
||||
}
|
||||
case "objects":
|
||||
// cancel all previous open objects requests for listing
|
||||
cancelContexts.Range(func(key, value interface{}) bool {
|
||||
rid := key.(int64)
|
||||
if rid < messageRequest.RequestID {
|
||||
cancelFunc := value.(context.CancelFunc)
|
||||
cancelFunc()
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
// start listing and writing to web socket
|
||||
go func() {
|
||||
objectRqConfigs, err := getObjectsOptionsFromReq(messageRequest)
|
||||
if err != nil {
|
||||
LogInfo(fmt.Sprintf("Error during Objects OptionsParse %s", err.Error()))
|
||||
objectRqConfigs, err := getObjectsOptionsFromReq(messageRequest)
|
||||
if err != nil {
|
||||
LogInfo(fmt.Sprintf("Error during Objects OptionsParse %s", err.Error()))
|
||||
|
||||
sendWSResponse(WSResponse{
|
||||
RequestID: messageRequest.RequestID,
|
||||
Error: ErrorWithContext(ctx, err),
|
||||
Prefix: messageRequest.Prefix,
|
||||
BucketName: messageRequest.BucketName,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
var buffer []ObjectResponse
|
||||
for lsObj := range startObjectsListing(ctx, wsc.client, objectRqConfigs) {
|
||||
if lsObj.Err != nil {
|
||||
sendWSResponse(WSResponse{
|
||||
RequestID: messageRequest.RequestID,
|
||||
Error: ErrorWithContext(ctx, err),
|
||||
Error: ErrorWithContext(ctx, lsObj.Err),
|
||||
Prefix: messageRequest.Prefix,
|
||||
BucketName: messageRequest.BucketName,
|
||||
})
|
||||
|
||||
return
|
||||
continue
|
||||
}
|
||||
var buffer []ObjectResponse
|
||||
for lsObj := range startObjectsListing(ctx, wsc.client, objectRqConfigs) {
|
||||
if _, ok := cancelContexts.Load(messageRequest.RequestID); !ok {
|
||||
return
|
||||
}
|
||||
|
||||
if lsObj.Err != nil {
|
||||
sendWSResponse(WSResponse{
|
||||
RequestID: messageRequest.RequestID,
|
||||
Error: ErrorWithContext(ctx, lsObj.Err),
|
||||
Prefix: messageRequest.Prefix,
|
||||
BucketName: messageRequest.BucketName,
|
||||
})
|
||||
|
||||
continue
|
||||
}
|
||||
objItem := ObjectResponse{
|
||||
Name: lsObj.Key,
|
||||
Size: lsObj.Size,
|
||||
LastModified: lsObj.LastModified.Format(time.RFC3339),
|
||||
VersionID: lsObj.VersionID,
|
||||
IsLatest: lsObj.IsLatest,
|
||||
DeleteMarker: lsObj.IsDeleteMarker,
|
||||
}
|
||||
buffer = append(buffer, objItem)
|
||||
|
||||
if len(buffer) >= itemsPerBatch {
|
||||
sendWSResponse(WSResponse{
|
||||
RequestID: messageRequest.RequestID,
|
||||
Data: buffer,
|
||||
})
|
||||
buffer = nil
|
||||
}
|
||||
objItem := ObjectResponse{
|
||||
Name: lsObj.Key,
|
||||
Size: lsObj.Size,
|
||||
LastModified: lsObj.LastModified.Format(time.RFC3339),
|
||||
VersionID: lsObj.VersionID,
|
||||
IsLatest: lsObj.IsLatest,
|
||||
DeleteMarker: lsObj.IsDeleteMarker,
|
||||
}
|
||||
if len(buffer) > 0 {
|
||||
buffer = append(buffer, objItem)
|
||||
|
||||
if len(buffer) >= itemsPerBatch {
|
||||
sendWSResponse(WSResponse{
|
||||
RequestID: messageRequest.RequestID,
|
||||
Data: buffer,
|
||||
})
|
||||
buffer = nil
|
||||
}
|
||||
|
||||
}
|
||||
if len(buffer) > 0 {
|
||||
sendWSResponse(WSResponse{
|
||||
RequestID: messageRequest.RequestID,
|
||||
RequestEnd: true,
|
||||
RequestID: messageRequest.RequestID,
|
||||
Data: buffer,
|
||||
})
|
||||
}
|
||||
|
||||
// remove the cancellation context
|
||||
sendWSResponse(WSResponse{
|
||||
RequestID: messageRequest.RequestID,
|
||||
RequestEnd: true,
|
||||
})
|
||||
|
||||
// if we have that request id, cancel it
|
||||
if cancelFunc, ok := cancelContexts.Load(messageRequest.RequestID); ok {
|
||||
cancelFunc.(context.CancelFunc)()
|
||||
cancelContexts.Delete(messageRequest.RequestID)
|
||||
}()
|
||||
}
|
||||
case "rewind":
|
||||
// cancel all previous open objects requests for listing
|
||||
cancelContexts.Range(func(key, value interface{}) bool {
|
||||
rid := key.(int64)
|
||||
if rid < messageRequest.RequestID {
|
||||
cancelFunc := value.(context.CancelFunc)
|
||||
cancelFunc()
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
// start listing and writing to web socket
|
||||
go func() {
|
||||
objectRqConfigs, err := getObjectsOptionsFromReq(messageRequest)
|
||||
if err != nil {
|
||||
LogInfo(fmt.Sprintf("Error during Objects OptionsParse %s", err.Error()))
|
||||
objectRqConfigs, err := getObjectsOptionsFromReq(messageRequest)
|
||||
if err != nil {
|
||||
LogInfo(fmt.Sprintf("Error during Objects OptionsParse %s", err.Error()))
|
||||
sendWSResponse(WSResponse{
|
||||
RequestID: messageRequest.RequestID,
|
||||
Error: ErrorWithContext(ctx, err),
|
||||
Prefix: messageRequest.Prefix,
|
||||
BucketName: messageRequest.BucketName,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
clientIP := wsc.conn.remoteAddress()
|
||||
|
||||
s3Client, err := newS3BucketClient(session, objectRqConfigs.BucketName, objectRqConfigs.Prefix, clientIP)
|
||||
if err != nil {
|
||||
sendWSResponse(WSResponse{
|
||||
RequestID: messageRequest.RequestID,
|
||||
Error: ErrorWithContext(ctx, err),
|
||||
Prefix: messageRequest.Prefix,
|
||||
BucketName: messageRequest.BucketName,
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
mcS3C := mcClient{client: s3Client}
|
||||
|
||||
var buffer []ObjectResponse
|
||||
|
||||
for lsObj := range startRewindListing(ctx, mcS3C, objectRqConfigs) {
|
||||
if lsObj.Err != nil {
|
||||
sendWSResponse(WSResponse{
|
||||
RequestID: messageRequest.RequestID,
|
||||
Error: ErrorWithContext(ctx, err),
|
||||
Error: ErrorWithContext(ctx, lsObj.Err.ToGoError()),
|
||||
Prefix: messageRequest.Prefix,
|
||||
BucketName: messageRequest.BucketName,
|
||||
})
|
||||
|
||||
return
|
||||
continue
|
||||
}
|
||||
|
||||
clientIP := wsc.conn.remoteAddress()
|
||||
name := strings.Replace(lsObj.URL.Path, fmt.Sprintf("/%s/", objectRqConfigs.BucketName), "", 1)
|
||||
|
||||
s3Client, err := newS3BucketClient(session, objectRqConfigs.BucketName, objectRqConfigs.Prefix, clientIP)
|
||||
if err != nil {
|
||||
sendWSResponse(WSResponse{
|
||||
RequestID: messageRequest.RequestID,
|
||||
Error: ErrorWithContext(ctx, err),
|
||||
Prefix: messageRequest.Prefix,
|
||||
BucketName: messageRequest.BucketName,
|
||||
})
|
||||
|
||||
cancel()
|
||||
return
|
||||
objItem := ObjectResponse{
|
||||
Name: name,
|
||||
Size: lsObj.Size,
|
||||
LastModified: lsObj.Time.Format(time.RFC3339),
|
||||
VersionID: lsObj.VersionID,
|
||||
IsLatest: lsObj.IsLatest,
|
||||
DeleteMarker: lsObj.IsDeleteMarker,
|
||||
}
|
||||
buffer = append(buffer, objItem)
|
||||
|
||||
mcS3C := mcClient{client: s3Client}
|
||||
|
||||
var buffer []ObjectResponse
|
||||
|
||||
for lsObj := range startRewindListing(ctx, mcS3C, objectRqConfigs) {
|
||||
if lsObj.Err != nil {
|
||||
sendWSResponse(WSResponse{
|
||||
RequestID: messageRequest.RequestID,
|
||||
Error: ErrorWithContext(ctx, lsObj.Err.ToGoError()),
|
||||
Prefix: messageRequest.Prefix,
|
||||
BucketName: messageRequest.BucketName,
|
||||
})
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
name := strings.Replace(lsObj.URL.Path, fmt.Sprintf("/%s/", objectRqConfigs.BucketName), "", 1)
|
||||
|
||||
objItem := ObjectResponse{
|
||||
Name: name,
|
||||
Size: lsObj.Size,
|
||||
LastModified: lsObj.Time.Format(time.RFC3339),
|
||||
VersionID: lsObj.VersionID,
|
||||
IsLatest: lsObj.IsLatest,
|
||||
DeleteMarker: lsObj.IsDeleteMarker,
|
||||
}
|
||||
buffer = append(buffer, objItem)
|
||||
|
||||
if len(buffer) >= itemsPerBatch {
|
||||
sendWSResponse(WSResponse{
|
||||
RequestID: messageRequest.RequestID,
|
||||
Data: buffer,
|
||||
})
|
||||
buffer = nil
|
||||
}
|
||||
|
||||
}
|
||||
if len(buffer) > 0 {
|
||||
if len(buffer) >= itemsPerBatch {
|
||||
sendWSResponse(WSResponse{
|
||||
RequestID: messageRequest.RequestID,
|
||||
Data: buffer,
|
||||
})
|
||||
buffer = nil
|
||||
}
|
||||
|
||||
}
|
||||
if len(buffer) > 0 {
|
||||
sendWSResponse(WSResponse{
|
||||
RequestID: messageRequest.RequestID,
|
||||
RequestEnd: true,
|
||||
RequestID: messageRequest.RequestID,
|
||||
Data: buffer,
|
||||
})
|
||||
}
|
||||
|
||||
// remove the cancellation context
|
||||
sendWSResponse(WSResponse{
|
||||
RequestID: messageRequest.RequestID,
|
||||
RequestEnd: true,
|
||||
})
|
||||
|
||||
// if we have that request id, cancel it
|
||||
if cancelFunc, ok := cancelContexts.Load(messageRequest.RequestID); ok {
|
||||
cancelFunc.(context.CancelFunc)()
|
||||
cancelContexts.Delete(messageRequest.RequestID)
|
||||
}()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"files": {
|
||||
"main.css": "./static/css/main.e60e4760.css",
|
||||
"main.js": "./static/js/main.3bcbce18.js",
|
||||
"main.js": "./static/js/main.ea59eadd.js",
|
||||
"static/js/5301.2c626a41.chunk.js": "./static/js/5301.2c626a41.chunk.js",
|
||||
"static/js/9361.ce3b326c.chunk.js": "./static/js/9361.ce3b326c.chunk.js",
|
||||
"static/js/843.454ac75f.chunk.js": "./static/js/843.454ac75f.chunk.js",
|
||||
@@ -40,7 +40,7 @@
|
||||
"static/js/4103.926c44ef.chunk.js": "./static/js/4103.926c44ef.chunk.js",
|
||||
"static/js/1702.851e407f.chunk.js": "./static/js/1702.851e407f.chunk.js",
|
||||
"static/js/7601.4e033e78.chunk.js": "./static/js/7601.4e033e78.chunk.js",
|
||||
"static/js/7945.24a46b62.chunk.js": "./static/js/7945.24a46b62.chunk.js",
|
||||
"static/js/7945.996e45d2.chunk.js": "./static/js/7945.996e45d2.chunk.js",
|
||||
"static/js/9619.a756233f.chunk.js": "./static/js/9619.a756233f.chunk.js",
|
||||
"static/js/8017.d5b163f3.chunk.js": "./static/js/8017.d5b163f3.chunk.js",
|
||||
"static/js/3323.f86a698b.chunk.js": "./static/js/3323.f86a698b.chunk.js",
|
||||
@@ -119,7 +119,7 @@
|
||||
"static/media/placeholderimage.png": "./static/media/placeholderimage.077ea48bd1ef1f4a883f.png",
|
||||
"index.html": "./index.html",
|
||||
"main.e60e4760.css.map": "./static/css/main.e60e4760.css.map",
|
||||
"main.3bcbce18.js.map": "./static/js/main.3bcbce18.js.map",
|
||||
"main.ea59eadd.js.map": "./static/js/main.ea59eadd.js.map",
|
||||
"5301.2c626a41.chunk.js.map": "./static/js/5301.2c626a41.chunk.js.map",
|
||||
"9361.ce3b326c.chunk.js.map": "./static/js/9361.ce3b326c.chunk.js.map",
|
||||
"843.454ac75f.chunk.js.map": "./static/js/843.454ac75f.chunk.js.map",
|
||||
@@ -158,7 +158,7 @@
|
||||
"4103.926c44ef.chunk.js.map": "./static/js/4103.926c44ef.chunk.js.map",
|
||||
"1702.851e407f.chunk.js.map": "./static/js/1702.851e407f.chunk.js.map",
|
||||
"7601.4e033e78.chunk.js.map": "./static/js/7601.4e033e78.chunk.js.map",
|
||||
"7945.24a46b62.chunk.js.map": "./static/js/7945.24a46b62.chunk.js.map",
|
||||
"7945.996e45d2.chunk.js.map": "./static/js/7945.996e45d2.chunk.js.map",
|
||||
"9619.a756233f.chunk.js.map": "./static/js/9619.a756233f.chunk.js.map",
|
||||
"8017.d5b163f3.chunk.js.map": "./static/js/8017.d5b163f3.chunk.js.map",
|
||||
"3323.f86a698b.chunk.js.map": "./static/js/3323.f86a698b.chunk.js.map",
|
||||
@@ -217,6 +217,6 @@
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/css/main.e60e4760.css",
|
||||
"static/js/main.3bcbce18.js"
|
||||
"static/js/main.ea59eadd.js"
|
||||
]
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><base href="/"/><meta content="width=device-width,initial-scale=1" name="viewport"/><meta content="#081C42" media="(prefers-color-scheme: light)" name="theme-color"/><meta content="#081C42" media="(prefers-color-scheme: dark)" name="theme-color"/><meta content="MinIO Console" name="description"/><meta name="minio-license" content="agpl"/><link href="./styles/root-styles.css" rel="stylesheet"/><link href="./apple-icon-180x180.png" rel="apple-touch-icon" sizes="180x180"/><link href="./favicon-32x32.png" rel="icon" sizes="32x32" type="image/png"/><link href="./favicon-96x96.png" rel="icon" sizes="96x96" type="image/png"/><link href="./favicon-16x16.png" rel="icon" sizes="16x16" type="image/png"/><link href="./manifest.json" rel="manifest"/><link color="#3a4e54" href="./safari-pinned-tab.svg" rel="mask-icon"/><title>MinIO Console</title><script defer="defer" src="./static/js/main.3bcbce18.js"></script><link href="./static/css/main.e60e4760.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"><div id="preload"><img src="./images/background.svg"/> <img src="./images/background-wave-orig2.svg"/></div><div id="loader-block"><img src="./Loader.svg"/></div></div></body></html>
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><base href="/"/><meta content="width=device-width,initial-scale=1" name="viewport"/><meta content="#081C42" media="(prefers-color-scheme: light)" name="theme-color"/><meta content="#081C42" media="(prefers-color-scheme: dark)" name="theme-color"/><meta content="MinIO Console" name="description"/><meta name="minio-license" content="agpl"/><link href="./styles/root-styles.css" rel="stylesheet"/><link href="./apple-icon-180x180.png" rel="apple-touch-icon" sizes="180x180"/><link href="./favicon-32x32.png" rel="icon" sizes="32x32" type="image/png"/><link href="./favicon-96x96.png" rel="icon" sizes="96x96" type="image/png"/><link href="./favicon-16x16.png" rel="icon" sizes="16x16" type="image/png"/><link href="./manifest.json" rel="manifest"/><link color="#3a4e54" href="./safari-pinned-tab.svg" rel="mask-icon"/><title>MinIO Console</title><script defer="defer" src="./static/js/main.ea59eadd.js"></script><link href="./static/css/main.e60e4760.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"><div id="preload"><img src="./images/background.svg"/> <img src="./images/background-wave-orig2.svg"/></div><div id="loader-block"><img src="./Loader.svg"/></div></div></body></html>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
web-app/build/static/js/7945.996e45d2.chunk.js
Normal file
2
web-app/build/static/js/7945.996e45d2.chunk.js
Normal file
File diff suppressed because one or more lines are too long
1
web-app/build/static/js/7945.996e45d2.chunk.js.map
Normal file
1
web-app/build/static/js/7945.996e45d2.chunk.js.map
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -99,7 +99,7 @@ const SetLegalHoldModal = ({
|
||||
>
|
||||
<FormLayout withBorders={false} containerPadding={false}>
|
||||
<Box className={"inputItem"}>
|
||||
<strong>Object</strong>: {bucketName}
|
||||
<strong>Object</strong>: {bucketName + "/" + objectName}
|
||||
</Box>
|
||||
<Switch
|
||||
value="legalhold"
|
||||
|
||||
@@ -40,6 +40,7 @@ import { api } from "api";
|
||||
import { errorToHandler } from "api/errors";
|
||||
import { getMaxShareLinkExpTime } from "screens/Console/ObjectBrowser/objectBrowserThunks";
|
||||
import { maxShareLinkExpTime } from "screens/Console/ObjectBrowser/objectBrowserSlice";
|
||||
import debounce from "lodash/debounce";
|
||||
|
||||
interface IShareFileProps {
|
||||
open: boolean;
|
||||
@@ -56,7 +57,7 @@ const ShareFile = ({
|
||||
}: IShareFileProps) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const distributedSetup = useSelector(selDistSet);
|
||||
const maxshareLinkExpTimeVal = useSelector(maxShareLinkExpTime);
|
||||
const maxShareLinkExpTimeVal = useSelector(maxShareLinkExpTime);
|
||||
const [shareURL, setShareURL] = useState<string>("");
|
||||
const [isLoadingVersion, setIsLoadingVersion] = useState<boolean>(true);
|
||||
const [isLoadingFile, setIsLoadingFile] = useState<boolean>(false);
|
||||
@@ -64,9 +65,7 @@ const ShareFile = ({
|
||||
const [dateValid, setDateValid] = useState<boolean>(true);
|
||||
const [versionID, setVersionID] = useState<string>("null");
|
||||
|
||||
const initialDate = new Date();
|
||||
|
||||
const dateChanged = (newDate: string, isValid: boolean) => {
|
||||
const debouncedDateChange = debounce((newDate: string, isValid: boolean) => {
|
||||
setDateValid(isValid);
|
||||
if (isValid) {
|
||||
setSelectedDate(newDate);
|
||||
@@ -74,7 +73,7 @@ const ShareFile = ({
|
||||
}
|
||||
setSelectedDate("");
|
||||
setShareURL("");
|
||||
};
|
||||
}, 300);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(getMaxShareLinkExpTime());
|
||||
@@ -205,7 +204,7 @@ const ShareFile = ({
|
||||
The following URL lets you share this object without requiring
|
||||
a login. <br />
|
||||
The URL expires automatically at the earlier of your
|
||||
configured time ({niceTimeFromSeconds(maxshareLinkExpTimeVal)}
|
||||
configured time ({niceTimeFromSeconds(maxShareLinkExpTimeVal)}
|
||||
) or the expiration of your current web session.
|
||||
</span>
|
||||
</Tooltip>
|
||||
@@ -213,11 +212,10 @@ const ShareFile = ({
|
||||
<br />
|
||||
<Grid item xs={12}>
|
||||
<DaysSelector
|
||||
initialDate={initialDate}
|
||||
id="date"
|
||||
label="Active for"
|
||||
maxSeconds={maxshareLinkExpTimeVal}
|
||||
onChange={dateChanged}
|
||||
maxSeconds={maxShareLinkExpTimeVal}
|
||||
onChange={debouncedDateChange}
|
||||
entity="Link"
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
@@ -24,28 +24,23 @@ const HOUR_MINUTES = 60;
|
||||
|
||||
interface IDaysSelector {
|
||||
id: string;
|
||||
initialDate: Date;
|
||||
maxSeconds: number;
|
||||
label: string;
|
||||
entity: string;
|
||||
onChange: (newDate: string, isValid: boolean) => void;
|
||||
}
|
||||
|
||||
const calculateNewTime = (
|
||||
initialDate: Date,
|
||||
days: number,
|
||||
hours: number,
|
||||
minutes: number,
|
||||
) => {
|
||||
return DateTime.fromJSDate(initialDate).plus({
|
||||
hours: hours + days * 24,
|
||||
minutes,
|
||||
}); // Lump days into hours to avoid daylight savings causing issues
|
||||
const calculateNewTime = (days: number, hours: number, minutes: number) => {
|
||||
return DateTime.now()
|
||||
.plus({
|
||||
hours: hours + days * 24,
|
||||
minutes,
|
||||
})
|
||||
.toISO(); // Lump days into hours to avoid daylight savings causing issues
|
||||
};
|
||||
|
||||
const DaysSelector = ({
|
||||
id,
|
||||
initialDate,
|
||||
label,
|
||||
maxSeconds,
|
||||
entity,
|
||||
@@ -59,7 +54,7 @@ const DaysSelector = ({
|
||||
const [selectedHours, setSelectedHours] = useState<number>(0);
|
||||
const [selectedMinutes, setSelectedMinutes] = useState<number>(0);
|
||||
const [validDate, setValidDate] = useState<boolean>(true);
|
||||
const [dateSelected, setDateSelected] = useState<DateTime>(DateTime.now());
|
||||
const [dateSelected, setDateSelected] = useState<string | null>(null);
|
||||
|
||||
// Set initial values
|
||||
useEffect(() => {
|
||||
@@ -75,19 +70,16 @@ const DaysSelector = ({
|
||||
!isNaN(selectedMinutes)
|
||||
) {
|
||||
setDateSelected(
|
||||
calculateNewTime(
|
||||
initialDate,
|
||||
selectedDays,
|
||||
selectedHours,
|
||||
selectedMinutes,
|
||||
),
|
||||
calculateNewTime(selectedDays, selectedHours, selectedMinutes),
|
||||
);
|
||||
}
|
||||
}, [initialDate, selectedDays, selectedHours, selectedMinutes]);
|
||||
}, [selectedDays, selectedHours, selectedMinutes]);
|
||||
|
||||
useEffect(() => {
|
||||
if (validDate) {
|
||||
const formattedDate = dateSelected.toFormat("yyyy-MM-dd HH:mm:ss");
|
||||
if (validDate && dateSelected) {
|
||||
const formattedDate = DateTime.fromISO(dateSelected).toFormat(
|
||||
"yyyy-MM-dd HH:mm:ss",
|
||||
);
|
||||
onChange(formattedDate.split(" ").join("T"), true);
|
||||
} else {
|
||||
onChange("0000-00-00", false);
|
||||
@@ -270,12 +262,14 @@ const DaysSelector = ({
|
||||
},
|
||||
}}
|
||||
>
|
||||
{validDate ? (
|
||||
{validDate && dateSelected ? (
|
||||
<div className={"validityText"}>
|
||||
<LinkIcon />
|
||||
<div>{entity} will be available until:</div>{" "}
|
||||
<div className={"validTill"}>
|
||||
{dateSelected.toFormat("MM/dd/yyyy HH:mm:ss ZZZZ")}
|
||||
{DateTime.fromISO(dateSelected).toFormat(
|
||||
"MM/dd/yyyy HH:mm:ss ZZZZ",
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
@@ -18748,8 +18748,8 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"ws@npm:^7.2.0, ws@npm:^7.4.6":
|
||||
version: 7.5.9
|
||||
resolution: "ws@npm:7.5.9"
|
||||
version: 7.5.10
|
||||
resolution: "ws@npm:7.5.10"
|
||||
peerDependencies:
|
||||
bufferutil: ^4.0.1
|
||||
utf-8-validate: ^5.0.2
|
||||
@@ -18758,7 +18758,7 @@ __metadata:
|
||||
optional: true
|
||||
utf-8-validate:
|
||||
optional: true
|
||||
checksum: 10c0/aec4ef4eb65821a7dde7b44790f8699cfafb7978c9b080f6d7a98a7f8fc0ce674c027073a78574c94786ba7112cc90fa2cc94fc224ceba4d4b1030cff9662494
|
||||
checksum: 10c0/bd7d5f4aaf04fae7960c23dcb6c6375d525e00f795dd20b9385902bd008c40a94d3db3ce97d878acc7573df852056ca546328b27b39f47609f80fb22a0a9b61d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Reference in New Issue
Block a user