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: Add PlaybackGrant. #700

Merged
merged 1 commit into from
Oct 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions lib/jwt/AccessToken.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,22 @@ declare namespace AccessToken {
endpointId?: string;
}

export interface PlaybackGrantOptions {
grant?: object;
Copy link
Contributor

@stern-shawn stern-shawn Oct 14, 2021

Choose a reason for hiding this comment

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

Based on this sample from the test, I think we should look into typing grant more specifically since object is a very loose definition.

var playbackGrant = {
  requestCredentials: null,
  playbackUrl: 'https://000.us-east-1.playback.live-video.net/api/video/v1/us-east-000.channel.000?token=xxxxx',
  playerStreamerSid: 'VJXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
};

var grant = new twilio.jwt.AccessToken.PlaybackGrant();
grant.grant = playbackGrant;

Maybe a new interface to DRY things up?:

export interface PlaybackGrantResponse {
  requestCredentials: string | null;
  playbackUrl: string;
  playerStreamerSid: string;
}

Copy link
Contributor

Choose a reason for hiding this comment

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

+1. Also need to do the same in other languages.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks so much for the suggestion -- we chatted and are planning to do this step in a separate PR, to speed up getting these into the helper libraries. But definitely going to make a new PR to clean this up.

Choose a reason for hiding this comment

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

The playback grant is supposed to be an opaque object returned by a Live API, none of these fields have to be provided by the developer. While adding typing seems like a good idea in principle, this is going to break if/when the Twilio Live team decide to make changes to the format of the grant, like maybe add a new field. I'm not really sure what the best option is, just wanted to point out that there are downsides to adding typing about private attributes of the grant.

}

export interface PlaybackGrantPayload {
grant?: object;
}

export class PlaybackGrant extends Grant<
PlaybackGrantOptions,
PlaybackGrantPayload,
'player'
> implements PlaybackGrantOptions {
grant?: object
}

export interface AccessTokenOptions {
/**
* Time to live in seconds
Expand Down
20 changes: 20 additions & 0 deletions lib/jwt/AccessToken.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,25 @@ _.extend(VoiceGrant.prototype, {
}
});

/**
* @constructor
* @param {object} options - ...
* @param {string} options.grant - The PlaybackGrant retrieved from Twilio's API
*/
function PlaybackGrant(options) {
options = options || {};
this.grant = options.grant;
}

_.extend(PlaybackGrant.prototype, {
key: 'player',
toPayload: function() {
var grant = {};
if (this.grant) { grant = this.grant; }
return grant;
}
});

/**
* @constructor
* @param {string} accountSid - The account's unique ID to which access is scoped
Expand Down Expand Up @@ -234,6 +253,7 @@ AccessToken.SyncGrant = SyncGrant;
AccessToken.VideoGrant = VideoGrant;
AccessToken.ConversationsGrant = util.deprecate(ConversationsGrant, 'ConversationsGrant is deprecated, use VideoGrant instead.');
AccessToken.TaskRouterGrant = TaskRouterGrant;
AccessToken.PlaybackGrant = PlaybackGrant;
AccessToken.DEFAULT_ALGORITHM = 'HS256';
AccessToken.ALGORITHMS = [
'HS256',
Expand Down
37 changes: 37 additions & 0 deletions spec/unit/jwt/AccessToken.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,27 @@ describe('AccessToken', function() {
});
});

it('should create token with playback grant', function() {
var token = new twilio.jwt.AccessToken(accountSid, keySid, 'secret');
token.identity = 'ID@example.com';

var playbackGrant = {
'requestCredentials': null,
'playbackUrl': 'https://000.us-east-1.playback.live-video.net/api/video/v1/us-east-000.channel.000?token=xxxxx',
'playerStreamerSid': 'VJXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
}

var grant = new twilio.jwt.AccessToken.PlaybackGrant();
grant.grant = playbackGrant;
token.addGrant(grant);

var decoded = jwt.verify(token.toJwt(), 'secret');
expect(decoded.grants).toEqual({
identity: 'ID@example.com',
player: playbackGrant
});
});

it('should create token with multiple grants', function() {
var token = new twilio.jwt.AccessToken(accountSid, keySid, 'secret');
token.identity = 'ID@example.com';
Expand Down Expand Up @@ -518,6 +539,22 @@ describe('AccessToken', function() {
});
});
});

describe('PlaybackGrant', function() {
it('should only populate set properties', function() {
var grant = new twilio.jwt.AccessToken.PlaybackGrant();
expect(grant.toPayload()).toEqual({});

var playbackGrant = {
'requestCredentials': null,
'playbackUrl': 'https://000.us-east-1.playback.live-video.net/api/video/v1/us-east-000.channel.000?token=xxxxx',
'playerStreamerSid': 'VJXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
}

grant.grant = playbackGrant;
expect(grant.toPayload()).toEqual(playbackGrant);
});
});
});

});