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

[3.x] Fix async OP behaviors on server (oauth packages) #13127

Merged
merged 7 commits into from
May 13, 2024
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
34 changes: 34 additions & 0 deletions packages/facebook-oauth/facebook-oauth_tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
Tinytest.addAsync(
'facebook-oauth - run service oauth with mocked flow as expected',
async function (test) {
const oauthMock = mockBehaviours(OAuth, {
_fetch: () => Promise.resolve({ json: () => ({ access_token: 'testToken' })}),
});

const service = 'facebook';
const serviceMockConfig = { service };
const mockConfig = { clientId: "test", secret: "test", loginStyle: "popup" };
if (Meteor.isServer) {
await ServiceConfiguration.configurations.upsertAsync(serviceMockConfig, { $set: mockConfig });
const result = await OAuthTest.registeredServices[service].handleOauthRequest({});
test.isTrue(!!result?.serviceData, 'should return mocked result');
test.equal(
oauthMock.mockedRuns.map(({ name }) => name),
['_redirectUri','openSecret','_fetch','openSecret','_fetch'],
'should run mock oauth behaviors',
);
} else if (Meteor.isClient) {
ServiceConfiguration.configurations.insert({ ...serviceMockConfig, ...mockConfig });
Facebook.requestCredential({});
test.equal(
oauthMock.mockedRuns.map(({ name }) => name),
['_loginStyle', '_redirectUri', '_stateParam', 'launchLogin'],
'should run mock oauth behaviors',
);
}

oauthMock.stop();

return Promise.resolve();
},
);
6 changes: 3 additions & 3 deletions packages/facebook-oauth/facebook_server.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ function getAbsoluteUrlOptions(query) {
* @returns {Promise<UserAccessToken>} - Promise with an Object containing the accessToken and expiresIn (lifetime of token in seconds)
*/
const getTokenResponse = async (query) => {
const config = ServiceConfiguration.configurations.findOne({
const config = await ServiceConfiguration.configurations.findOneAsync({
service: 'facebook',
});
if (!config) throw new ServiceConfiguration.ConfigError();
Expand All @@ -96,6 +96,7 @@ const getTokenResponse = async (query) => {
.then((res) => res.json())
.then(data => {
const fbAccessToken = data.access_token;
console.log("-> fbAccessToken", fbAccessToken);
const fbExpires = data.expires_in;
if (!fbAccessToken) {
throw new Error("Failed to complete OAuth handshake with facebook " +
Expand All @@ -117,7 +118,7 @@ const getTokenResponse = async (query) => {
};

const getIdentity = async (accessToken, fields) => {
const config = ServiceConfiguration.configurations.findOne({
const config = await ServiceConfiguration.configurations.findOneAsync({
service: 'facebook',
});
if (!config) throw new ServiceConfiguration.ConfigError();
Expand Down Expand Up @@ -145,4 +146,3 @@ const getIdentity = async (accessToken, fields) => {

Facebook.retrieveCredential = (credentialToken, credentialSecret) =>
OAuth.retrieveCredential(credentialToken, credentialSecret);

6 changes: 6 additions & 0 deletions packages/facebook-oauth/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,9 @@ Package.onUse(api => {

api.export('Facebook');
});

Package.onTest(function(api) {
api.use('facebook-oauth');
api.use(['tinytest', 'ecmascript', 'test-helpers', 'oauth', 'oauth2', 'service-configuration']);
api.addFiles('facebook-oauth_tests.js');
});
34 changes: 34 additions & 0 deletions packages/github-oauth/github-oauth_tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
Tinytest.addAsync(
'github-oauth - run service oauth with mocked flow as expected',
async function (test) {
const oauthMock = mockBehaviours(OAuth, {
_fetch: () => Promise.resolve({ json: () => ([{ access_token: 'testToken', email: { primary: 'email' } }])}),
});

const service = 'github';
const serviceMockConfig = { service };
const mockConfig = { clientId: "test", secret: "test", loginStyle: "popup" };
if (Meteor.isServer) {
await ServiceConfiguration.configurations.upsertAsync(serviceMockConfig, { $set: mockConfig });
const result = await OAuthTest.registeredServices[service].handleOauthRequest({});
test.isTrue(!!result?.serviceData, 'should return mocked result');
test.equal(
oauthMock.mockedRuns.map(({ name }) => name),
['_redirectUri','_fetch','_fetch','_fetch','sealSecret'],
'should run mock oauth behaviors',
);
} else if (Meteor.isClient) {
ServiceConfiguration.configurations.insert({ ...serviceMockConfig, ...mockConfig });
Github.requestCredential({});
test.equal(
oauthMock.mockedRuns.map(({ name }) => name),
['_loginStyle', '_redirectUri', '_stateParam', 'launchLogin'],
'should run mock oauth behaviors',
);
}

oauthMock.stop();

return Promise.resolve();
},
);
8 changes: 4 additions & 4 deletions packages/github-oauth/github_server.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ let userAgent = 'Meteor';
if (Meteor.release) userAgent += `/${Meteor.release}`;

const getAccessToken = async (query) => {
const config = ServiceConfiguration.configurations.findOne({
const config = await ServiceConfiguration.configurations.findOneAsync({
service: 'github'
});
if (!config) throw new ServiceConfiguration.ConfigError();
Expand All @@ -45,7 +45,7 @@ const getAccessToken = async (query) => {
config
)
});
const request = await fetch(
const request = await OAuth._fetch(
`https://github.com/login/oauth/access_token?${content.toString()}`,
{
method: 'POST',
Expand Down Expand Up @@ -76,7 +76,7 @@ const getAccessToken = async (query) => {

const getIdentity = async (accessToken) => {
try {
const request = await fetch('https://api.github.com/user', {
const request = await OAuth._fetch('https://api.github.com/user', {
method: 'GET',
headers: {
Accept: 'application/json',
Expand All @@ -95,7 +95,7 @@ const getIdentity = async (accessToken) => {

const getEmails = async (accessToken) => {
try {
const request = await fetch('https://api.github.com/user/emails', {
const request = await OAuth._fetch('https://api.github.com/user/emails', {
method: 'GET',
headers: {
'User-Agent': userAgent,
Expand Down
7 changes: 7 additions & 0 deletions packages/github-oauth/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,17 @@ Package.onUse(api => {
api.use('oauth', ['client', 'server']);
api.use('fetch', 'server');
api.use('random', 'client');
api.use('accounts-base', ['client', 'server']);
api.use('service-configuration', ['client', 'server']);

api.addFiles('github_client.js', 'client');
api.addFiles('github_server.js', 'server');

api.export('Github');
});

Package.onTest(function(api) {
api.use('github-oauth');
api.use(['tinytest', 'ecmascript', 'test-helpers', 'oauth', 'oauth2', 'service-configuration']);
api.addFiles('github-oauth_tests.js');
});
34 changes: 34 additions & 0 deletions packages/google-oauth/google-oauth_tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
Tinytest.addAsync(
'google-oauth - run service oauth with mocked flow as expected',
async function (test) {
const oauthMock = mockBehaviours(OAuth, {
_fetch: () => Promise.resolve({ json: () => ({ access_token: 'testToken', scope: '1 2 3' })}),
});

const service = 'google';
const serviceMockConfig = { service };
const mockConfig = { clientId: "test", secret: "test", loginStyle: "popup" };
if (Meteor.isServer) {
await ServiceConfiguration.configurations.upsertAsync(serviceMockConfig, { $set: mockConfig });
const result = await OAuthTest.registeredServices[service].handleOauthRequest({});
test.isTrue(!!result?.serviceData, 'should return mocked result');
test.equal(
oauthMock.mockedRuns.map(({ name }) => name),
['openSecret','_redirectUri','_fetch','_fetch','_fetch'],
'should run mock oauth behaviors',
);
} else if (Meteor.isClient) {
ServiceConfiguration.configurations.insert({ ...serviceMockConfig, ...mockConfig });
Google.requestCredential({});
test.equal(
oauthMock.mockedRuns.map(({ name }) => name),
['_loginStyle', '_redirectUri', '_stateParam', 'launchLogin'],
'should run mock oauth behaviors',
);
}

oauthMock.stop();

return Promise.resolve();
},
);
8 changes: 4 additions & 4 deletions packages/google-oauth/google_server.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ Accounts.registerLoginHandler(async (request) => {
// - expiresIn: lifetime of token in seconds
// - refreshToken, if this is the first authorization request
const getTokens = async (query, callback) => {
const config = ServiceConfiguration.configurations.findOne({
const config = await ServiceConfiguration.configurations.findOneAsync({
service: 'google',
});
if (!config) throw new ServiceConfiguration.ConfigError();
Expand All @@ -137,7 +137,7 @@ const getTokens = async (query, callback) => {
redirect_uri: OAuth._redirectUri('google', config),
grant_type: 'authorization_code',
});
const request = await fetch('https://accounts.google.com/o/oauth2/token', {
const request = await OAuth._fetch('https://accounts.google.com/o/oauth2/token', {
method: 'POST',
headers: {
Accept: 'application/json',
Expand Down Expand Up @@ -174,7 +174,7 @@ const getIdentity = async (accessToken, callback) => {
const content = new URLSearchParams({ access_token: accessToken });
let response;
try {
const request = await fetch(
const request = await OAuth._fetch(
`https://www.googleapis.com/oauth2/v1/userinfo?${content.toString()}`,
{
method: 'GET',
Expand All @@ -194,7 +194,7 @@ const getScopes = async (accessToken, callback) => {
const content = new URLSearchParams({ access_token: accessToken });
let response;
try {
const request = await fetch(
const request = await OAuth._fetch(
`https://www.googleapis.com/oauth2/v1/tokeninfo?${content.toString()}`,
{
method: 'GET',
Expand Down
6 changes: 6 additions & 0 deletions packages/google-oauth/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@ Package.onUse(api => {

api.export('Google');
});

Package.onTest(function(api) {
api.use('google-oauth');
api.use(['tinytest', 'ecmascript', 'test-helpers', 'oauth', 'oauth2', 'service-configuration']);
api.addFiles('google-oauth_tests.js');
});
34 changes: 34 additions & 0 deletions packages/meetup-oauth/meetup-oauth_tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
Tinytest.addAsync(
'meetup-oauth - run service oauth with mocked flow as expected',
async function (test) {
const oauthMock = mockBehaviours(OAuth, {
_fetch: () => Promise.resolve({ json: () => ({ access_token: 'testToken' })}),
});

const service = 'meetup';
const serviceMockConfig = { service };
const mockConfig = { clientId: "test", secret: "test", loginStyle: "popup" };
if (Meteor.isServer) {
await ServiceConfiguration.configurations.upsertAsync(serviceMockConfig, { $set: mockConfig });
const result = await OAuthTest.registeredServices[service].handleOauthRequest({});
test.isTrue(!!result?.serviceData, 'should return mocked result');
test.equal(
oauthMock.mockedRuns.map(({ name }) => name),
['openSecret','_redirectUri','_addValuesToQueryParams','_fetch','_addValuesToQueryParams','_fetch'],
'should run mock oauth behaviors',
);
} else if (Meteor.isClient) {
ServiceConfiguration.configurations.insert({ ...serviceMockConfig, ...mockConfig });
Meetup.requestCredential({});
test.equal(
oauthMock.mockedRuns.map(({ name }) => name),
['_loginStyle', '_redirectUri', '_stateParam', 'launchLogin'],
'should run mock oauth behaviors',
);
}

oauthMock.stop();

return Promise.resolve();
},
);
2 changes: 1 addition & 1 deletion packages/meetup-oauth/meetup_server.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ OAuth.registerService('meetup', 2, null, async query => {
});

const getAccessToken = async query => {
const config = ServiceConfiguration.configurations.findOne({service: 'meetup'});
const config = await ServiceConfiguration.configurations.findOneAsync({service: 'meetup'});
if (!config)
throw new ServiceConfiguration.ConfigError();

Expand Down
6 changes: 6 additions & 0 deletions packages/meetup-oauth/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,9 @@ Package.onUse(api => {

api.export('Meetup');
});

Package.onTest(function(api) {
api.use('meetup-oauth');
api.use(['tinytest', 'ecmascript', 'test-helpers', 'oauth', 'oauth2', 'service-configuration']);
api.addFiles('meetup-oauth_tests.js');
});
34 changes: 34 additions & 0 deletions packages/meteor-developer-oauth/meteor-developer-oauth_tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
Tinytest.addAsync(
'meteor-developer-oauth - run service oauth with mocked flow as expected',
async function (test) {
const oauthMock = mockBehaviours(OAuth, {
_fetch: () => Promise.resolve({ json: () => ({ access_token: 'testToken' })}),
});

const service = 'meteor-developer';
const serviceMockConfig = { service };
const mockConfig = { clientId: "test", secret: "test", loginStyle: "popup" };
if (Meteor.isServer) {
await ServiceConfiguration.configurations.upsertAsync(serviceMockConfig, { $set: mockConfig });
const result = await OAuthTest.registeredServices[service].handleOauthRequest({});
test.isTrue(!!result?.serviceData, 'should return mocked result');
test.equal(
oauthMock.mockedRuns.map(({ name }) => name),
['openSecret','_redirectUri','_addValuesToQueryParams','_fetch','_fetch','sealSecret'],
'should run mock oauth behaviors',
);
} else if (Meteor.isClient) {
ServiceConfiguration.configurations.insert({ ...serviceMockConfig, ...mockConfig });
MeteorDeveloperAccounts.requestCredential({});
test.equal(
oauthMock.mockedRuns.map(({ name }) => name),
['_loginStyle','_stateParam','_redirectUri','launchLogin'],
'should run mock oauth behaviors',
);
}

oauthMock.stop();

return Promise.resolve();
},
);
6 changes: 6 additions & 0 deletions packages/meteor-developer-oauth/package.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,9 @@ Package.onUse(api => {

api.export('MeteorDeveloperAccounts');
});

Package.onTest(function(api) {
api.use('meteor-developer-oauth');
api.use(['tinytest', 'ecmascript', 'test-helpers', 'oauth', 'oauth2', 'service-configuration']);
api.addFiles('meteor-developer-oauth_tests.js');
});