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

Feature token refresh #7

Merged
merged 6 commits into from
Feb 10, 2022
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
110 changes: 57 additions & 53 deletions server/auth/google-strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
*/

import { Strategy } from 'passport-google-oauth20';
import { log } from '@iftta/util';
import { log, date } from '@iftta/util'
import { PassportStatic } from 'passport';
import { Request } from 'express';
import Repository from '../services/repository-service';
Expand Down Expand Up @@ -41,64 +41,68 @@ class GoogleStrategy {
`Set oauth callback URL to ${process.env.OAUTH_CALLBACK_URL}, adjust Authorized URLs in GCP client settings accordingly`,
);

//TODO: we ask for all scopes here,
// we should perhaps add scopes when user decide to use a specific agent requiring
// extra scopes to be added.
_passport.use(
new Strategy(
{
clientID: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
callbackURL: process.env.OAUTH_CALLBACK_URL,
passReqToCallback: true,
scope: [
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/display-video',
'https://www.googleapis.com/auth/adwords',
],
},
async (
req: Request,
accessToken: string,
refreshToken: string,
profile: any,
done: any,
) => {
// this is the callback method called after
// successful authentication
log.debug(`Profile : ${JSON.stringify(profile, null, 2)}`);
const googleStrategy = new Strategy({
clientID: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
callbackURL: process.env.OAUTH_CALLBACK_URL,
passReqToCallback: true,
scope: ['https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile',
'https://www.googleapis.com/auth/display-video',
'https://www.googleapis.com/auth/adwords'],
},
async (
req: Request,
accessToken: string,
refreshToken: string,
profile: any,
done: any
) => {
// this is the callback method called after
// successful authentication
log.debug(`Profile : ${JSON.stringify(profile, null, 2)}`)

const jsonProfile = JSON.parse(profile._raw);
const jsonProfile = JSON.parse(profile._raw);

const userData: User = {
profileId: profile.id,
displayName: profile.displayName,
givenName: profile.name.givenName,
familyName: profile.name.familyName,
email: jsonProfile.email,
verified: jsonProfile.email_verified,
gender: profile.gender,
profilePhoto: jsonProfile.picture,
authToken: accessToken,
refreshToken: refreshToken,
locale: jsonProfile.locale,
tokenProvider: profile.provider,
};
const userData: User = {
profileId: profile.id,
displayName: profile.displayName,
givenName: profile.name.givenName,
familyName: profile.name.familyName,
email: jsonProfile.email,
verified: jsonProfile.email_verified,
gender: profile.gender,
profilePhoto: jsonProfile.picture,
locale: jsonProfile.locale,
token: {
access: accessToken,
expiry: date.add(Date.now(), { seconds: 3599 }), // expire access Tokens after 3599 sec.
refresh: refreshToken,
provider: profile.provider,
type: 'Bearer'
}
};

log.debug(`User : ${JSON.stringify(userData, null, 4)}`);
log.debug(`User : ${JSON.stringify(userData, null, 2)}`);

// check if the user exists in db
const userResults = await userRepo.getBy('profileId', profile.id);
// check if the user exists in db
const userResults = await userRepo.getBy(
'profileId',
profile.id
);

if (userResults.length == 0) {
await userRepo.save(userData);
}
if (userResults.length == 0) {
await userRepo.save(userData);
}

return done(null, userData, true);
},
),
);
return done(null, userData, true);
}
)
//TODO: we ask for all scopes here,
// we should perhaps add scopes when user decide to use a specific agent requiring
// extra scopes to be added.

_passport.use(googleStrategy);
}
}

Expand Down
61 changes: 27 additions & 34 deletions server/job-runner/job-runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,14 @@ import { AgentResult } from '../agents/source-agents/open-weather-map/interfaces
import { Job, ExecutionTime, _Timestamp } from './interfaces';
import Repository from '../services/repository-service';
import Collections from '../services/collection-factory';
import { Collection } from '../models/fire-store-entity';
import { log } from '@iftta/util';

import { Collection } from "../models/fire-store-entity";
import { log, date } from '@iftta/util'
import BackgroundAuth from './refresh-tokens';
//TODO: deal with leaking firestore _Timestamp object

// setting up useful date manipulation functions
// wrapping them into date object to make it easier
// to remember what we are dealing with.
const date = {
add: require('date-fns/add'),
isAfter: require('date-fns/isAfter'),
isBefore: require('date-fns/isBefore'),
isValid: require('date-fns/isValid'),
};

//TODO: replace this with sending messages over pubsub.
//Temp coupling between packages/
import rulesEngine from '../packages/rule-engine';
//TODO: replace this with sending messages over pubsub.
//Temp coupling between packages/
import rulesEngine from '../packages/rule-engine'
import { RuleResult } from '../packages/rule-engine/src/interfaces';

const pubSubClient = new PubSub();
Expand Down Expand Up @@ -165,9 +155,7 @@ class JobRunner {
return true;
}

const nextRuntime = date.add(j.lastExecution?.toDate(), {
minutes: j.executionInterval,
});
const nextRuntime = date.add(j.lastExecution?.toDate()as Date, { minutes: j.executionInterval });
log.info(`Job: ${j.id} next execution : ${nextRuntime}`);

return date.isBefore(nextRuntime, nowUTC);
Expand All @@ -176,18 +164,11 @@ class JobRunner {
return jobs;
}

public async runAll() {
// Get a list of jobs to execute
log.info('Fetching job list to execute');
const allJobs: Job[] = await this.jobsRepo.list();

// Filter by execution interval
const now = Date.now();
const offsetSec = new Date().getTimezoneOffset() * 1000;
const nowUTC = new Date(now + offsetSec);

log.debug(`offset : ${offsetSec}`);
public async runAll() {

// Get a list of jobs to execute
log.info('Fetching job list to execute');
const jobs = await this.getEligibleJobs();
const jobCount = jobs.length;
log.debug('List of jobs to execute');
Expand All @@ -209,8 +190,9 @@ class JobRunner {

// Collect all actions that need to be performed
// on the target systems.
const targetActions: Array<RuleResult[]> = [];
const executionTimes: Array<ExecutionTime> = [];
const targetActions: Array<RuleResult[]> = []
const executionTimes:Array<ExecutionTime> = [];
const allResults:Array<Array<RuleResult>> = [[]];

while (!(await jobResult).done) {
log.debug('my jobResult');
Expand All @@ -227,18 +209,25 @@ class JobRunner {
executionTimes.push(execTime);

const results: Array<RuleResult> = await rulesEngine.processMessage(currentResult);
allResults.push(results);
log.debug('evaluation result');
log.debug(results);
// targetActions.push(results);
jobResult = jobResultIter.next();
}

log.info('Updating Last execution time of jobs');

log.info('Updating Last execution time of jobs')

// Update execution times in the jobs collection
await this.updateJobExecutionTimes(executionTimes);
await this.updateJobExecutionTimes(executionTimes);

// TODO: obtain user ID from the Rule object
// obtain freshTokens before running the jobs
const userId = 'YkHryPCUuAbwgBG3Zdle';
const token = await BackgroundAuth.refreshTokensForUser(userId);

// call target-agents to execute individual actions
// call target-agents to execute individual actions

// publish results to pubsub.
// while (!(await jobResult).done) {
Expand All @@ -251,6 +240,10 @@ class JobRunner {
// jobResult = jobResultIter.next();
// }
}

public async processTargets(results: Array<RuleResult>){

}
}

export default new JobRunner(pubSubClient, repo);
53 changes: 38 additions & 15 deletions server/job-runner/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion server/job-runner/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@
"author": "",
"license": "ISC",
"dependencies": {
"date-fns": "^2.28.0"
"axios": "^0.25.0"
}
}
Loading