Skip to content

Commit 4ae0db4

Browse files
author
Eric Koleda
committed
Wrap all of hasAccess, otherwise you could still get race conditions.
1 parent 821bd97 commit 4ae0db4

File tree

2 files changed

+36
-48
lines changed

2 files changed

+36
-48
lines changed

src/Service.gs

Lines changed: 35 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,6 @@ var Service_ = function(serviceName) {
4545
*/
4646
Service_.EXPIRATION_BUFFER_SECONDS_ = 60;
4747

48-
/**
49-
* The number of seconds that a token should remain in the cache.
50-
* @type {number}
51-
* @private
52-
*/
53-
Service_.CACHE_EXPIRATION_SECONDS_ = 6 * 60 * 60;
54-
5548
/**
5649
* The number of seconds that a token should remain in the cache.
5750
* @type {number}
@@ -381,28 +374,29 @@ Service_.prototype.handleCallback = function(callbackRequest) {
381374
* otherwise.
382375
*/
383376
Service_.prototype.hasAccess = function() {
384-
var result = true;
385-
var token = this.getToken();
386-
if (!token || this.isExpired_(token)) {
387-
if (token && token.refresh_token) {
388-
try {
389-
this.refresh();
390-
} catch (e) {
391-
this.lastError_ = e;
392-
result = false;
377+
return this.lockable_(function() {
378+
var token = this.getToken();
379+
if (!token || this.isExpired_(token)) {
380+
if (token && token.refresh_token) {
381+
try {
382+
this.refresh();
383+
} catch (e) {
384+
this.lastError_ = e;
385+
return false;
386+
}
387+
} else if (this.privateKey_) {
388+
try {
389+
this.exchangeJwt_();
390+
} catch (e) {
391+
this.lastError_ = e;
392+
return false;
393+
}
394+
} else {
395+
return false;
393396
}
394-
} else if (this.privateKey_) {
395-
try {
396-
this.exchangeJwt_();
397-
} catch (e) {
398-
this.lastError_ = e;
399-
result = false;
400-
}
401-
} else {
402-
result = false;
403397
}
404-
}
405-
return result;
398+
return true;
399+
});
406400
};
407401

408402
/**
@@ -510,12 +504,6 @@ Service_.prototype.refresh = function() {
510504
'Token URL': this.tokenUrl_
511505
});
512506

513-
// If using locking, lock the service while refreshing.
514-
if (this.lock_ && !this.lock_.hasLock()) {
515-
this.lock_.waitLock(Service_.LOCK_EXPIRATION_MILLISECONDS_);
516-
var releaseLock = true;
517-
}
518-
519507
var token = this.getToken();
520508
if (!token.refresh_token) {
521509
throw new Error('Offline access is required.');
@@ -548,10 +536,6 @@ Service_.prototype.refresh = function() {
548536
newToken.refresh_token = token.refresh_token;
549537
}
550538
this.saveToken_(newToken);
551-
552-
if (this.lock_ && releaseLock) {
553-
this.lock_.releaseLock();
554-
}
555539
};
556540

557541
/**
@@ -586,16 +570,7 @@ Service_.prototype.saveToken_ = function(token) {
586570
* @return {Object} The token, or null if no token was found.
587571
*/
588572
Service_.prototype.getToken = function() {
589-
// If using locking, lock the service while retrieving the token.
590-
if (this.lock_ && !this.lock_.hasLock()) {
591-
this.lock_.waitLock(Service_.LOCK_EXPIRATION_MILLISECONDS_);
592-
var releaseLock = true;
593-
}
594-
var token = this.getStorage().getValue(null);
595-
if (this.lock_ && releaseLock) {
596-
this.lock_.releaseLock();
597-
}
598-
return token;
573+
return this.getStorage().getValue(null);
599574
};
600575

601576
/**
@@ -682,3 +657,16 @@ Service_.prototype.createJwt_ = function() {
682657
var signature = Utilities.base64EncodeWebSafe(signatureBytes);
683658
return toSign + '.' + signature;
684659
};
660+
661+
Service_.prototype.lockable_ = function(func) {
662+
var releaseLock = false;
663+
if (this.lock_ && !this.lock_.hasLock()) {
664+
this.lock_.waitLock(Service_.LOCK_EXPIRATION_MILLISECONDS_);
665+
releaseLock = true;
666+
}
667+
var result = func.apply(this);
668+
if (this.lock_ && releaseLock) {
669+
this.lock_.releaseLock();
670+
}
671+
return result;
672+
}

test/test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ describe('Service', function() {
138138
});
139139

140140
describe('#hasAccess()', function() {
141-
it('should use the lock to prevent concurrend access', function(done) {
141+
it('should use the lock to prevent concurrent access', function(done) {
142142
var token = {
143143
granted_time: 100,
144144
expires_in: 100,

0 commit comments

Comments
 (0)