diff --git a/integration/user_api_bucket_test.go b/integration/user_api_bucket_test.go
index 54444849a9..37976eab41 100644
--- a/integration/user_api_bucket_test.go
+++ b/integration/user_api_bucket_test.go
@@ -461,24 +461,12 @@ func ListObjects(bucketName, prefix, withVersions string) (*http.Response, error
return response, err
}
-func SharesAnObjectOnAUrl(bucketName, prefix, versionID, expires, accessKey, secretKey string) (*http.Response, error) {
- // Helper function to share an object on an url
-
- requestDataAdd := map[string]interface{}{
- "prefix": prefix,
- "version_id": versionID,
- "expires": expires,
- "access_key": accessKey,
- "secret_key": secretKey,
- }
-
- requestDataJSON, _ := json.Marshal(requestDataAdd)
- requestDataBody := bytes.NewReader(requestDataJSON)
-
+func SharesAnObjectOnAUrl(bucketName, prefix, versionID, expires string) (*http.Response, error) {
+ // Helper function to share an object on a url
request, err := http.NewRequest(
- "POST",
- "http://localhost:9090/api/v1/buckets/"+bucketName+"/objects/share",
- requestDataBody,
+ "GET",
+ "http://localhost:9090/api/v1/buckets/"+bucketName+"/objects/share?prefix="+prefix+"&version_id="+versionID+"&expires="+expires,
+ nil,
)
if err != nil {
log.Println(err)
@@ -755,39 +743,6 @@ func PutObjectsLegalholdStatus(bucketName, prefix, status, versionID string) (*h
return response, err
}
-func PostServiceAccountCredentials(accessKey, secretKey, policy string) (*http.Response, error) {
- /*
- Helper function to create a service account
- POST: {{baseUrl}}/service-account-credentials
- {
- "accessKey":"testsa",
- "secretKey":"secretsa",
- "policy":""
- }
- */
- requestDataAdd := map[string]interface{}{
- "accessKey": accessKey,
- "secretKey": secretKey,
- "policy": policy,
- }
- requestDataJSON, _ := json.Marshal(requestDataAdd)
- requestDataBody := bytes.NewReader(requestDataJSON)
-
- request, err := http.NewRequest("POST",
- "http://localhost:9090/api/v1/service-account-credentials",
- requestDataBody)
- if err != nil {
- log.Println(err)
- }
- request.Header.Add("Cookie", fmt.Sprintf("token=%s", token))
- request.Header.Add("Content-Type", "application/json")
- client := &http.Client{
- Timeout: 2 * time.Second,
- }
- response, err := client.Do(request)
- return response, err
-}
-
func TestPutObjectsLegalholdStatus(t *testing.T) {
// Variables
assert := assert.New(t)
@@ -1559,8 +1514,6 @@ func TestShareObjectOnURL(t *testing.T) {
tags := make(map[string]string)
tags["tag"] = "testputobjecttagbucketonetagone"
versionID := "null"
- accessKey := "testaccesskey"
- secretKey := "secretAccessKey"
// 1. Create the bucket
if !setupBucket(bucketName, false, false, nil, nil, assert, 200) {
@@ -1581,21 +1534,6 @@ func TestShareObjectOnURL(t *testing.T) {
inspectHTTPResponse(uploadResponse),
)
}
- // 2. Create Access Key
- accKeyRsp, createError := PostServiceAccountCredentials(accessKey, secretKey, "")
-
- if createError != nil {
- log.Println(createError)
- return
- }
-
- if accKeyRsp != nil {
- assert.Equal(
- 201,
- accKeyRsp.StatusCode,
- inspectHTTPResponse(accKeyRsp),
- )
- }
type args struct {
prefix string
@@ -1623,7 +1561,7 @@ func TestShareObjectOnURL(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// 3. Share the object on a URL
- shareResponse, shareError := SharesAnObjectOnAUrl(bucketName, tt.args.prefix, versionID, "604800s", accessKey, secretKey)
+ shareResponse, shareError := SharesAnObjectOnAUrl(bucketName, tt.args.prefix, versionID, "604800s")
assert.Nil(shareError)
if shareError != nil {
log.Println(shareError)
diff --git a/models/share_request.go b/models/share_request.go
deleted file mode 100644
index b12a7f041e..0000000000
--- a/models/share_request.go
+++ /dev/null
@@ -1,142 +0,0 @@
-// Code generated by go-swagger; DO NOT EDIT.
-
-// This file is part of MinIO Console Server
-// Copyright (c) 2023 MinIO, Inc.
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see .
-//
-
-package models
-
-// This file was generated by the swagger tool.
-// Editing this file might prove futile when you re-run the swagger generate command
-
-import (
- "context"
-
- "github.com/go-openapi/errors"
- "github.com/go-openapi/strfmt"
- "github.com/go-openapi/swag"
- "github.com/go-openapi/validate"
-)
-
-// ShareRequest share request
-//
-// swagger:model shareRequest
-type ShareRequest struct {
-
- // access key
- // Required: true
- AccessKey *string `json:"access_key"`
-
- // expires
- Expires string `json:"expires,omitempty"`
-
- // prefix
- // Required: true
- Prefix *string `json:"prefix"`
-
- // secret key
- // Required: true
- SecretKey *string `json:"secret_key"`
-
- // version id
- // Required: true
- VersionID *string `json:"version_id"`
-}
-
-// Validate validates this share request
-func (m *ShareRequest) Validate(formats strfmt.Registry) error {
- var res []error
-
- if err := m.validateAccessKey(formats); err != nil {
- res = append(res, err)
- }
-
- if err := m.validatePrefix(formats); err != nil {
- res = append(res, err)
- }
-
- if err := m.validateSecretKey(formats); err != nil {
- res = append(res, err)
- }
-
- if err := m.validateVersionID(formats); err != nil {
- res = append(res, err)
- }
-
- if len(res) > 0 {
- return errors.CompositeValidationError(res...)
- }
- return nil
-}
-
-func (m *ShareRequest) validateAccessKey(formats strfmt.Registry) error {
-
- if err := validate.Required("access_key", "body", m.AccessKey); err != nil {
- return err
- }
-
- return nil
-}
-
-func (m *ShareRequest) validatePrefix(formats strfmt.Registry) error {
-
- if err := validate.Required("prefix", "body", m.Prefix); err != nil {
- return err
- }
-
- return nil
-}
-
-func (m *ShareRequest) validateSecretKey(formats strfmt.Registry) error {
-
- if err := validate.Required("secret_key", "body", m.SecretKey); err != nil {
- return err
- }
-
- return nil
-}
-
-func (m *ShareRequest) validateVersionID(formats strfmt.Registry) error {
-
- if err := validate.Required("version_id", "body", m.VersionID); err != nil {
- return err
- }
-
- return nil
-}
-
-// ContextValidate validates this share request based on context it is used
-func (m *ShareRequest) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
- return nil
-}
-
-// MarshalBinary interface implementation
-func (m *ShareRequest) MarshalBinary() ([]byte, error) {
- if m == nil {
- return nil, nil
- }
- return swag.WriteJSON(m)
-}
-
-// UnmarshalBinary interface implementation
-func (m *ShareRequest) UnmarshalBinary(b []byte) error {
- var res ShareRequest
- if err := swag.ReadJSON(b, &res); err != nil {
- return err
- }
- *m = res
- return nil
-}
diff --git a/portal-ui/src/api/consoleApi.ts b/portal-ui/src/api/consoleApi.ts
index cc4896ef0a..390bd9db75 100644
--- a/portal-ui/src/api/consoleApi.ts
+++ b/portal-ui/src/api/consoleApi.ts
@@ -1494,14 +1494,6 @@ export interface LdapPolicyEntity {
groups?: string[];
}
-export interface ShareRequest {
- prefix: string;
- version_id: string;
- expires?: string;
- access_key: string;
- secret_key: string;
-}
-
export type QueryParamsType = Record;
export type ResponseFormat = keyof Omit;
@@ -2179,20 +2171,23 @@ export class Api<
* @tags Object
* @name ShareObject
* @summary Shares an Object on a url
- * @request POST:/buckets/{bucket_name}/objects/share
+ * @request GET:/buckets/{bucket_name}/objects/share
* @secure
*/
shareObject: (
bucketName: string,
- body: ShareRequest,
+ query: {
+ prefix: string;
+ version_id: string;
+ expires?: string;
+ },
params: RequestParams = {}
) =>
this.request({
path: `/buckets/${bucketName}/objects/share`,
- method: "POST",
- body: body,
+ method: "GET",
+ query: query,
secure: true,
- type: ContentType.Json,
format: "json",
...params,
}),
diff --git a/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/ObjectDetails/ShareFile.tsx b/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/ObjectDetails/ShareFile.tsx
index 291c284e22..053ff00494 100644
--- a/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/ObjectDetails/ShareFile.tsx
+++ b/portal-ui/src/screens/Console/Buckets/ListBuckets/Objects/ObjectDetails/ShareFile.tsx
@@ -16,26 +16,9 @@
import React, { Fragment, useEffect, useState } from "react";
import { useSelector } from "react-redux";
-import { Theme } from "@mui/material/styles";
-import {
- Button,
- CopyIcon,
- FormLayout,
- Grid,
- InputBox,
- RadioGroup,
- ReadBox,
- Select,
- ShareIcon,
-} from "mds";
-import createStyles from "@mui/styles/createStyles";
-import withStyles from "@mui/styles/withStyles";
+import { Button, CopyIcon, ReadBox, ShareIcon, Grid } from "mds";
import CopyToClipboard from "react-copy-to-clipboard";
import LinearProgress from "@mui/material/LinearProgress";
-import {
- formFieldStyles,
- modalStyleUtils,
-} from "../../../../Common/FormComponents/common/styleLibrary";
import { IFileInfo } from "./types";
import { ErrorResponseHandler } from "../../../../../../common/types";
@@ -45,42 +28,12 @@ import DaysSelector from "../../../../Common/FormComponents/DaysSelector/DaysSel
import { encodeURLString } from "../../../../../../common/utils";
import {
selDistSet,
- setErrorSnackMessage,
setModalErrorSnackMessage,
setModalSnackMessage,
} from "../../../../../../systemSlice";
import { useAppDispatch } from "../../../../../../store";
-import { DateTime } from "luxon";
-import { stringSort } from "../../../../../../utils/sortFunctions";
-
-const styles = (theme: Theme) =>
- createStyles({
- shareLinkInfo: {
- fontSize: 14,
- fontWeight: 400,
- },
- copyShareLink: {
- display: "flex",
- "@media (max-width: 900px)": {
- flexFlow: "column",
- alignItems: "center",
- justifyContent: "center",
- },
- },
- copyShareLinkInput: {
- "& div:first-child": {
- marginTop: 0,
- },
- "@media (max-width: 900px)": {
- minWidth: 250,
- },
- },
- ...modalStyleUtils,
- ...formFieldStyles,
- });
interface IShareFileProps {
- classes: any;
open: boolean;
bucketName: string;
dataObject: IFileInfo;
@@ -88,7 +41,6 @@ interface IShareFileProps {
}
const ShareFile = ({
- classes,
open,
closeModalAndRefresh,
bucketName,
@@ -97,17 +49,11 @@ const ShareFile = ({
const dispatch = useAppDispatch();
const distributedSetup = useSelector(selDistSet);
const [shareURL, setShareURL] = useState("");
- const [isLoadingURL, setIsLoadingURL] = useState(false);
- const [isLoadingAccessKeys, setLoadingAccessKeys] = useState(true);
+ const [isLoadingVersion, setIsLoadingVersion] = useState(true);
+ const [isLoadingFile, setIsLoadingFile] = useState(false);
const [selectedDate, setSelectedDate] = useState("");
const [dateValid, setDateValid] = useState(true);
const [versionID, setVersionID] = useState("null");
- const [displayURL, setDisplayURL] = useState(false);
- const [accessKeys, setAccessKeys] = useState([]);
- const [selectedAccessKey, setSelectedAccessKey] = useState("");
- const [secretKey, setSecretKey] = useState("");
- const [authType, setAuthType] = useState("acc-list");
- const [otherAK, setOtherAK] = useState("");
const initialDate = new Date();
@@ -152,19 +98,20 @@ const ShareFile = ({
dispatch(setModalErrorSnackMessage(error));
});
- setIsLoadingURL(false);
+ setIsLoadingVersion(false);
return;
}
setVersionID("null");
- setIsLoadingURL(false);
+ setIsLoadingVersion(false);
return;
}
setVersionID(dataObject.version_id || "null");
- setIsLoadingURL(false);
+ setIsLoadingVersion(false);
}, [bucketName, dataObject, distributedSetup, dispatch]);
useEffect(() => {
- if (dateValid && isLoadingURL) {
+ if (dateValid && !isLoadingVersion) {
+ setIsLoadingFile(true);
setShareURL("");
const slDate = new Date(`${selectedDate}`);
@@ -174,33 +121,28 @@ const ShareFile = ({
(slDate.getTime() - currDate.getTime()) / 1000
);
- const accKey = authType === "acc-list" ? selectedAccessKey : otherAK;
-
if (diffDate > 0) {
api
- .invoke("POST", `/api/v1/buckets/${bucketName}/objects/share`, {
- prefix: encodeURLString(dataObject.name),
- version_id: versionID,
- expires: selectedDate !== "" ? `${diffDate}s` : "",
- access_key: accKey,
- secret_key: secretKey,
- })
+ .invoke(
+ "GET",
+ `/api/v1/buckets/${bucketName}/objects/share?prefix=${encodeURLString(
+ dataObject.name
+ )}&version_id=${versionID}${
+ selectedDate !== "" ? `&expires=${diffDate}s` : ""
+ }`
+ )
.then((res: string) => {
setShareURL(res);
- setIsLoadingURL(false);
- setDisplayURL(true);
+ setIsLoadingFile(false);
})
.catch((error: ErrorResponseHandler) => {
dispatch(setModalErrorSnackMessage(error));
setShareURL("");
- setIsLoadingURL(false);
- setDisplayURL(false);
+ setIsLoadingFile(false);
});
}
}
}, [
- secretKey,
- selectedAccessKey,
dataObject,
selectedDate,
bucketName,
@@ -208,206 +150,89 @@ const ShareFile = ({
setShareURL,
dispatch,
distributedSetup,
+ isLoadingVersion,
versionID,
- isLoadingURL,
- authType,
- otherAK,
]);
- useEffect(() => {
- if (isLoadingAccessKeys) {
- const userLoggedIn = localStorage.getItem("userLoggedIn");
-
- api
- .invoke(
- "GET",
- `/api/v1/user/${encodeURLString(userLoggedIn)}/service-accounts`
- )
- .then((res: string[]) => {
- if (res.length === 0) {
- setAuthType("acc-other");
- }
-
- const serviceAccounts = res
- .sort(stringSort)
- .map((element) => ({ value: element, label: element }));
-
- setLoadingAccessKeys(false);
- setAccessKeys(serviceAccounts);
- setSelectedAccessKey(serviceAccounts[0].value);
- })
- .catch((err: ErrorResponseHandler) => {
- dispatch(setErrorSnackMessage(err));
- setLoadingAccessKeys(false);
- });
- }
- }, [isLoadingAccessKeys, dispatch]);
-
- const generateLink = () => {
- setIsLoadingURL(true);
- };
-
- const generateAnotherLink = () => {
- setIsLoadingURL(false);
- setDisplayURL(false);
- setSelectedDate("");
- setShareURL("");
- };
-
return (
- }
- modalOpen={open}
- onClose={() => {
- closeModalAndRefresh();
- }}
- >
- {displayURL ? (
-
-
- This is a temporary URL with integrated access credentials for
- sharing {dataObject.name} until{" "}
-
- {DateTime.fromISO(selectedDate).toFormat(
- "ccc, LLL dd yyyy HH:mm (ZZZZ)"
- )}
-
-
-
- This temporary URL will expiry after this time.
-
-
-
-
+
+ }
+ modalOpen={open}
+ onClose={() => {
+ closeModalAndRefresh();
+ }}
+ >
+ {isLoadingVersion && (
+
+
-
-
-
-
- ) : (
-
-
- To generate a temporary URL, please provide a set of credentials,
- this link can be valid up to 7 days.
-
+ This is a temporary URL with integrated access credentials for
+ sharing objects valid for up to 7 days.
+
+
+ The temporary URL expires after the configured time limit.
+
-
-
- {accessKeys.length > 0 && (
- {
- setAuthType(e.target.value);
- }}
- currentValue={authType}
- />
- )}
- {authType === "acc-other" ? (
- {
- setOtherAK(e.target.value);
- }}
- label={"Access Key"}
- />
- ) : (
-
-
-
-
-
- {isLoadingURL && (
-
+
- )}
-
-
-
-
- )}
-
+
+
+
+
+ )}
+
+
);
};
-export default withStyles(styles)(ShareFile);
+export default ShareFile;
diff --git a/restapi/client.go b/restapi/client.go
index d1f33b4f95..ebbf96362d 100644
--- a/restapi/client.go
+++ b/restapi/client.go
@@ -21,7 +21,6 @@ import (
"errors"
"fmt"
"io"
- "net/url"
"path"
"strings"
"time"
@@ -222,10 +221,6 @@ func (c minioClient) copyObject(ctx context.Context, dst minio.CopyDestOptions,
return c.client.CopyObject(ctx, dst, src)
}
-func (c minioClient) presignedGetObject(ctx context.Context, bucketName, objectName string, expiry time.Duration, reqParams url.Values) (*url.URL, error) {
- return c.client.PresignedGetObject(ctx, bucketName, objectName, expiry, reqParams)
-}
-
// MCClient interface with all functions to be implemented
// by mock when testing, it should include all mc/S3Client respective api calls
// that are used within this project.
diff --git a/restapi/embedded_spec.go b/restapi/embedded_spec.go
index b251dd66ff..5f77661af3 100644
--- a/restapi/embedded_spec.go
+++ b/restapi/embedded_spec.go
@@ -1858,7 +1858,7 @@ func init() {
}
},
"/buckets/{bucket_name}/objects/share": {
- "post": {
+ "get": {
"tags": [
"Object"
],
@@ -1872,12 +1872,21 @@ func init() {
"required": true
},
{
- "name": "body",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/shareRequest"
- }
+ "type": "string",
+ "name": "prefix",
+ "in": "query",
+ "required": true
+ },
+ {
+ "type": "string",
+ "name": "version_id",
+ "in": "query",
+ "required": true
+ },
+ {
+ "type": "string",
+ "name": "expires",
+ "in": "query"
}
],
"responses": {
@@ -8310,32 +8319,6 @@ func init() {
}
}
},
- "shareRequest": {
- "type": "object",
- "required": [
- "prefix",
- "version_id",
- "access_key",
- "secret_key"
- ],
- "properties": {
- "access_key": {
- "type": "string"
- },
- "expires": {
- "type": "string"
- },
- "prefix": {
- "type": "string"
- },
- "secret_key": {
- "type": "string"
- },
- "version_id": {
- "type": "string"
- }
- }
- },
"siteReplicationAddRequest": {
"type": "array",
"items": {
@@ -10877,7 +10860,7 @@ func init() {
}
},
"/buckets/{bucket_name}/objects/share": {
- "post": {
+ "get": {
"tags": [
"Object"
],
@@ -10891,12 +10874,21 @@ func init() {
"required": true
},
{
- "name": "body",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/shareRequest"
- }
+ "type": "string",
+ "name": "prefix",
+ "in": "query",
+ "required": true
+ },
+ {
+ "type": "string",
+ "name": "version_id",
+ "in": "query",
+ "required": true
+ },
+ {
+ "type": "string",
+ "name": "expires",
+ "in": "query"
}
],
"responses": {
@@ -17458,32 +17450,6 @@ func init() {
}
}
},
- "shareRequest": {
- "type": "object",
- "required": [
- "prefix",
- "version_id",
- "access_key",
- "secret_key"
- ],
- "properties": {
- "access_key": {
- "type": "string"
- },
- "expires": {
- "type": "string"
- },
- "prefix": {
- "type": "string"
- },
- "secret_key": {
- "type": "string"
- },
- "version_id": {
- "type": "string"
- }
- }
- },
"siteReplicationAddRequest": {
"type": "array",
"items": {
diff --git a/restapi/operations/console_api.go b/restapi/operations/console_api.go
index 022ff9da15..e3cf2d745c 100644
--- a/restapi/operations/console_api.go
+++ b/restapi/operations/console_api.go
@@ -2149,10 +2149,10 @@ func (o *ConsoleAPI) initHandlerCache() {
o.handlers["PUT"] = make(map[string]http.Handler)
}
o.handlers["PUT"]["/service-accounts/{access_key}/policy"] = service_account.NewSetServiceAccountPolicy(o.context, o.ServiceAccountSetServiceAccountPolicyHandler)
- if o.handlers["POST"] == nil {
- o.handlers["POST"] = make(map[string]http.Handler)
+ if o.handlers["GET"] == nil {
+ o.handlers["GET"] = make(map[string]http.Handler)
}
- o.handlers["POST"]["/buckets/{bucket_name}/objects/share"] = object.NewShareObject(o.context, o.ObjectShareObjectHandler)
+ o.handlers["GET"]["/buckets/{bucket_name}/objects/share"] = object.NewShareObject(o.context, o.ObjectShareObjectHandler)
if o.handlers["PUT"] == nil {
o.handlers["PUT"] = make(map[string]http.Handler)
}
diff --git a/restapi/operations/object/share_object.go b/restapi/operations/object/share_object.go
index 96f9ae23a4..834e992105 100644
--- a/restapi/operations/object/share_object.go
+++ b/restapi/operations/object/share_object.go
@@ -49,7 +49,7 @@ func NewShareObject(ctx *middleware.Context, handler ShareObjectHandler) *ShareO
}
/*
- ShareObject swagger:route POST /buckets/{bucket_name}/objects/share Object shareObject
+ ShareObject swagger:route GET /buckets/{bucket_name}/objects/share Object shareObject
Shares an Object on a url
*/
diff --git a/restapi/operations/object/share_object_parameters.go b/restapi/operations/object/share_object_parameters.go
index f4a3a6e2ab..e199afcfff 100644
--- a/restapi/operations/object/share_object_parameters.go
+++ b/restapi/operations/object/share_object_parameters.go
@@ -23,7 +23,6 @@ package object
// Editing this file might prove futile when you re-run the swagger generate command
import (
- "io"
"net/http"
"github.com/go-openapi/errors"
@@ -31,8 +30,6 @@ import (
"github.com/go-openapi/runtime/middleware"
"github.com/go-openapi/strfmt"
"github.com/go-openapi/validate"
-
- "github.com/minio/console/models"
)
// NewShareObjectParams creates a new ShareObjectParams object
@@ -54,14 +51,23 @@ type ShareObjectParams struct {
/*
Required: true
- In: body
+ In: path
+ */
+ BucketName string
+ /*
+ In: query
*/
- Body *models.ShareRequest
+ Expires *string
/*
Required: true
- In: path
+ In: query
*/
- BucketName string
+ Prefix string
+ /*
+ Required: true
+ In: query
+ */
+ VersionID string
}
// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface
@@ -73,38 +79,27 @@ func (o *ShareObjectParams) BindRequest(r *http.Request, route *middleware.Match
o.HTTPRequest = r
- if runtime.HasBody(r) {
- defer r.Body.Close()
- var body models.ShareRequest
- if err := route.Consumer.Consume(r.Body, &body); err != nil {
- if err == io.EOF {
- res = append(res, errors.Required("body", "body", ""))
- } else {
- res = append(res, errors.NewParseError("body", "body", "", err))
- }
- } else {
- // validate body object
- if err := body.Validate(route.Formats); err != nil {
- res = append(res, err)
- }
-
- ctx := validate.WithOperationRequest(r.Context())
- if err := body.ContextValidate(ctx, route.Formats); err != nil {
- res = append(res, err)
- }
-
- if len(res) == 0 {
- o.Body = &body
- }
- }
- } else {
- res = append(res, errors.Required("body", "body", ""))
- }
+ qs := runtime.Values(r.URL.Query())
rBucketName, rhkBucketName, _ := route.Params.GetOK("bucket_name")
if err := o.bindBucketName(rBucketName, rhkBucketName, route.Formats); err != nil {
res = append(res, err)
}
+
+ qExpires, qhkExpires, _ := qs.GetOK("expires")
+ if err := o.bindExpires(qExpires, qhkExpires, route.Formats); err != nil {
+ res = append(res, err)
+ }
+
+ qPrefix, qhkPrefix, _ := qs.GetOK("prefix")
+ if err := o.bindPrefix(qPrefix, qhkPrefix, route.Formats); err != nil {
+ res = append(res, err)
+ }
+
+ qVersionID, qhkVersionID, _ := qs.GetOK("version_id")
+ if err := o.bindVersionID(qVersionID, qhkVersionID, route.Formats); err != nil {
+ res = append(res, err)
+ }
if len(res) > 0 {
return errors.CompositeValidationError(res...)
}
@@ -124,3 +119,63 @@ func (o *ShareObjectParams) bindBucketName(rawData []string, hasKey bool, format
return nil
}
+
+// bindExpires binds and validates parameter Expires from query.
+func (o *ShareObjectParams) bindExpires(rawData []string, hasKey bool, formats strfmt.Registry) error {
+ var raw string
+ if len(rawData) > 0 {
+ raw = rawData[len(rawData)-1]
+ }
+
+ // Required: false
+ // AllowEmptyValue: false
+
+ if raw == "" { // empty values pass all other validations
+ return nil
+ }
+ o.Expires = &raw
+
+ return nil
+}
+
+// bindPrefix binds and validates parameter Prefix from query.
+func (o *ShareObjectParams) bindPrefix(rawData []string, hasKey bool, formats strfmt.Registry) error {
+ if !hasKey {
+ return errors.Required("prefix", "query", rawData)
+ }
+ var raw string
+ if len(rawData) > 0 {
+ raw = rawData[len(rawData)-1]
+ }
+
+ // Required: true
+ // AllowEmptyValue: false
+
+ if err := validate.RequiredString("prefix", "query", raw); err != nil {
+ return err
+ }
+ o.Prefix = raw
+
+ return nil
+}
+
+// bindVersionID binds and validates parameter VersionID from query.
+func (o *ShareObjectParams) bindVersionID(rawData []string, hasKey bool, formats strfmt.Registry) error {
+ if !hasKey {
+ return errors.Required("version_id", "query", rawData)
+ }
+ var raw string
+ if len(rawData) > 0 {
+ raw = rawData[len(rawData)-1]
+ }
+
+ // Required: true
+ // AllowEmptyValue: false
+
+ if err := validate.RequiredString("version_id", "query", raw); err != nil {
+ return err
+ }
+ o.VersionID = raw
+
+ return nil
+}
diff --git a/restapi/operations/object/share_object_urlbuilder.go b/restapi/operations/object/share_object_urlbuilder.go
index 64af1ab5b4..875a27811b 100644
--- a/restapi/operations/object/share_object_urlbuilder.go
+++ b/restapi/operations/object/share_object_urlbuilder.go
@@ -33,6 +33,10 @@ import (
type ShareObjectURL struct {
BucketName string
+ Expires *string
+ Prefix string
+ VersionID string
+
_basePath string
// avoid unkeyed usage
_ struct{}
@@ -72,6 +76,28 @@ func (o *ShareObjectURL) Build() (*url.URL, error) {
}
_result.Path = golangswaggerpaths.Join(_basePath, _path)
+ qs := make(url.Values)
+
+ var expiresQ string
+ if o.Expires != nil {
+ expiresQ = *o.Expires
+ }
+ if expiresQ != "" {
+ qs.Set("expires", expiresQ)
+ }
+
+ prefixQ := o.Prefix
+ if prefixQ != "" {
+ qs.Set("prefix", prefixQ)
+ }
+
+ versionIDQ := o.VersionID
+ if versionIDQ != "" {
+ qs.Set("version_id", versionIDQ)
+ }
+
+ _result.RawQuery = qs.Encode()
+
return &_result, nil
}
diff --git a/restapi/user_objects.go b/restapi/user_objects.go
index 7cdc6d14de..bc32008be2 100644
--- a/restapi/user_objects.go
+++ b/restapi/user_objects.go
@@ -31,8 +31,6 @@ import (
"strings"
"time"
- "github.com/minio/minio-go/v7/pkg/credentials"
-
"github.com/go-openapi/runtime"
"github.com/go-openapi/runtime/middleware"
"github.com/klauspost/compress/zip"
@@ -119,7 +117,7 @@ func registerObjectsHandlers(api *operations.ConsoleAPI) {
})
// get share object url
api.ObjectShareObjectHandler = objectApi.ShareObjectHandlerFunc(func(params objectApi.ShareObjectParams, session *models.Principal) middleware.Responder {
- resp, err := getShareObjectResponse(params)
+ resp, err := getShareObjectResponse(session, params)
if err != nil {
return objectApi.NewShareObjectDefault(int(err.Code)).WithPayload(err)
}
@@ -894,60 +892,34 @@ func uploadFiles(ctx context.Context, client MinioClient, params objectApi.PostB
return nil
}
-// getShareObjectResponse returns a share object url, Session is omitted as we will sign the URl with a new static token
-func getShareObjectResponse(params objectApi.ShareObjectParams) (*string, *models.Error) {
+// getShareObjectResponse returns a share object url
+func getShareObjectResponse(session *models.Principal, params objectApi.ShareObjectParams) (*string, *models.Error) {
ctx := params.HTTPRequest.Context()
- bodyPrefix := *params.Body.Prefix
-
- accessKey := *params.Body.AccessKey
- secretKey := *params.Body.SecretKey
-
- creds := credentials.NewStaticV4(accessKey, secretKey, "")
-
- mClient, err := minio.New(getMinIOEndpoint(), &minio.Options{
- Creds: creds,
- Secure: getMinIOEndpointIsSecure(),
- Transport: GetConsoleHTTPClient(getMinIOServer()).Transport,
- })
- if err != nil {
- return nil, ErrorWithContext(ctx, err)
- }
-
- minioClient := minioClient{client: mClient}
-
var prefix string
- if bodyPrefix != "" {
- encodedPrefix := SanitizeEncodedPrefix(bodyPrefix)
+ if params.Prefix != "" {
+ encodedPrefix := SanitizeEncodedPrefix(params.Prefix)
decodedPrefix, err := base64.StdEncoding.DecodeString(encodedPrefix)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
prefix = string(decodedPrefix)
}
-
- expireDuration := time.Duration(604800) * time.Second
-
- if params.Body.Expires != "" {
- expireDuration, err = time.ParseDuration(params.Body.Expires)
-
- if err != nil {
- return nil, ErrorWithContext(ctx, err)
- }
+ s3Client, err := newS3BucketClient(session, params.BucketName, prefix)
+ if err != nil {
+ return nil, ErrorWithContext(ctx, err)
}
-
- reqParams := make(url.Values)
- if *params.Body.VersionID != "" {
- reqParams.Set("versionId", *params.Body.VersionID)
+ // create a mc S3Client interface implementation
+ // defining the client to be used
+ mcClient := mcClient{client: s3Client}
+ var expireDuration string
+ if params.Expires != nil {
+ expireDuration = *params.Expires
}
-
- urlParams, err := minioClient.presignedGetObject(ctx, params.BucketName, prefix, expireDuration, reqParams)
+ url, err := getShareObjectURL(ctx, mcClient, params.VersionID, expireDuration)
if err != nil {
return nil, ErrorWithContext(ctx, err)
}
-
- stringURL := urlParams.String()
-
- return &stringURL, nil
+ return url, nil
}
func getShareObjectURL(ctx context.Context, client MCClient, versionID string, duration string) (url *string, err error) {
diff --git a/swagger.yml b/swagger.yml
index 91da6bf856..87f1e72663 100644
--- a/swagger.yml
+++ b/swagger.yml
@@ -484,7 +484,7 @@ paths:
- Object
/buckets/{bucket_name}/objects/share:
- post:
+ get:
summary: Shares an Object on a url
operationId: ShareObject
parameters:
@@ -492,11 +492,18 @@ paths:
in: path
required: true
type: string
- - name: body
- in: body
+ - name: prefix
+ in: query
required: true
- schema:
- $ref: "#/definitions/shareRequest"
+ type: string
+ - name: version_id
+ in: query
+ required: true
+ type: string
+ - name: expires
+ in: query
+ required: false
+ type: string
responses:
200:
description: A successful response.
@@ -6145,23 +6152,4 @@ definitions:
groups:
type: array
items:
- type: string
-
- shareRequest:
- type: object
- required:
- - prefix
- - version_id
- - access_key
- - secret_key
- properties:
- prefix:
- type: string
- version_id:
- type: string
- expires:
- type: string
- access_key:
- type: string
- secret_key:
- type: string
\ No newline at end of file
+ type: string
\ No newline at end of file