Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: accessibleAt v4 signed urls #1328

Merged
merged 20 commits into from
Nov 3, 2020

Conversation

shaffeeullah
Copy link
Contributor

@shaffeeullah shaffeeullah commented Oct 28, 2020

Resolves merge conflicts from #1079

Fixes #1041 🦕

@google-cla google-cla bot added the cla: yes This human has signed the Contributor License Agreement. label Oct 28, 2020
@codecov
Copy link

codecov bot commented Oct 29, 2020

Codecov Report

Merging #1328 into master will increase coverage by 0.00%.
The diff coverage is 100.00%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #1328   +/-   ##
=======================================
  Coverage   99.00%   99.00%           
=======================================
  Files          14       14           
  Lines       11719    11775   +56     
  Branches      513      593   +80     
=======================================
+ Hits        11602    11658   +56     
  Misses        117      117           
Impacted Files Coverage Δ
src/file.ts 99.94% <100.00%> (+<0.01%) ⬆️
src/signer.ts 99.77% <100.00%> (+0.01%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 7f3bb25...a989dce. Read the comment docs.

@shaffeeullah shaffeeullah marked this pull request as ready for review October 30, 2020 21:42
@shaffeeullah shaffeeullah requested a review from a team as a code owner October 30, 2020 21:42
src/file.ts Outdated
@@ -2723,6 +2724,10 @@ class File extends ServiceObject<File> {
* @param {string} [config.responseDisposition] The
* [response-content-disposition parameter](http://goo.gl/yMWxQV) of the
* signed url.
* @param {*} [config.usableFrom=Date.now()] A timestamp when this link became usable. Any value
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the name usableFrom readable to you or do you have recommendations for changing it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes sense to me. The URL is usable from the date specified forward. I've been thinking about alternative names and haven't really come up with anything. I am open to suggestions though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@frankyn what do you think of accessibleAt? (thanks @bcoe for the suggestion!)

expires: expiresDate.setMinutes(expiresMinutes + 90),
});
const res = await fetch(signedReadUrl);
const body = await res.text();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of validating the text. Validate the res status code which is less brittle.

test/signer.ts Outdated
it('should accept strings', async () => {
const usableFrom = '12-12-2099';
const usableFromDate = new Date(usableFrom);
const expectedUsableFrom = '20991212T000000Z';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you update this to be provided from the Date object instead?

test/signer.ts Outdated
version: 'v4',
method: 'GET',
usableFrom,
expires: usableFromDate.valueOf() + 5000,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use .valueOf() here instead of setX()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setX modifies and returns the original object

test/signer.ts Outdated
[string],
Promise<string>
> = sandbox.stub(authClient, 'sign').resolves('signature');
const usableFrom = new Date(1581984000000);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Make int constants named variables in a before() call so it can be reused.

test/signer.ts Outdated
});

it('should throw if an expiration date from the before usableFrom date is given', () => {
const expires = Date.now() + 5;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on our pairing:

+ 5 is may not work as expected, could you update the line to increment based on the unit? e.g. second, minute, hour.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have updated it to be 1 day difference. I am not incrementing by unit as to avoid converting to a date and then back to milliseconds. Do you think I should perform this conversion?

src/signer.ts Outdated
@@ -408,6 +419,16 @@ export class URLSigner {

return Math.round(expiresInMSeconds / 1000); // The API expects seconds.
}

parseUsableFrom(usableFrom?: string | number | Date): number {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you try refactoring parseUsableFrom() into parseExpires() they look really similar?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parseExpires is ensuring that the expiration date is not in the past, while parseUsableFrom does not require this check. I could refactor the code so that it takes in a boolean parameter to determine whether this check is necessary (ie: is it being called for usableFrom or expires?). Do you think this makes sense? Further, the check on line 424 would have to be included in the joint function, as usableFrom is an optional parameter. While the false case will never trigger, it might be confusing to see that expires will default to the current date.

src/signer.ts Outdated
@@ -140,6 +147,7 @@ export class URLSigner {
const config: GetSignedUrlConfigInternal = Object.assign({}, cfg, {
method,
expiration: expiresInSeconds,
usableFrom: new Date(1000 * usableFromInSeconds),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: not sure I understand 1000 * in this case, is it needed? (Comparing to expiration and it's not used in this way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expiration field is expecting number. usableFrom is expecting Date and the Date constructor accepts a number argument in milliseconds. The 1000 multiplier is to perform this conversion.

@sofisl
Copy link
Contributor

sofisl commented Nov 2, 2020

@shaffeeullah, I reviewed this for readability, but will refer to @frankyn for library-specific code review.

Copy link
Member

@frankyn frankyn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw you decided on accessibleAt sounds good and acking.

You have a linter issue and added a nit for the added example.

src/file.ts Outdated
@@ -2747,7 +2746,8 @@ class File extends ServiceObject<File> {
*
* const config = {
* action: 'read',
* expires: '03-17-2025'
* expires: '03-17-2025',
* accessibleAt: ''03-13-2025'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Double '.

Recommend adding another example separate from the simple Signed URL example.

@shaffeeullah shaffeeullah changed the title feat: usableFrom v4 signed urls feat: accessibleAt v4 signed urls Nov 3, 2020
* const config = {
* action: 'read',
* expires: '03-17-2025',
* accessibleAt: '03-13-2025'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One potential issue with accessibleAt is that it may not fit well with using a Signed URL to upload data only downloading data.

WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From how I read it, 'accessible' refers to the link and not the file. The link to upload is only accessible from the date specified. I think it works.

@product-auto-label product-auto-label bot added the api: storage Issues related to the googleapis/nodejs-storage API. label Nov 3, 2020
@shaffeeullah shaffeeullah merged commit 1e0295e into master Nov 3, 2020
@shaffeeullah shaffeeullah deleted the shaffeeullah/usableFromV4SignedURLs branch November 3, 2020 22:23
gcf-owl-bot bot added a commit that referenced this pull request Jan 18, 2022
Source-Link: googleapis/synthtool@89dd35d
Post-Processor: gcr.io/cloud-devrel-public-resources/owlbot-nodejs:latest@sha256:89c5b2f3decec8ad64febbebea671076c119d1ab43700da380846a315600de8a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: storage Issues related to the googleapis/nodejs-storage API. cla: yes This human has signed the Contributor License Agreement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add option to specify date in getSignedUrl
3 participants