Skip to content

Commit

Permalink
Merge pull request #742 from jetstreamapp/poc/generic-salesforce-api
Browse files Browse the repository at this point in the history
Remove reliance on JSForce
  • Loading branch information
paustint authored Mar 23, 2024
2 parents 8b466a7 + ed9b8a8 commit eb055a3
Show file tree
Hide file tree
Showing 216 changed files with 7,193 additions and 3,519 deletions.
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ JETSTREAM_SERVER_DOMAIN='localhost:3333'
JETSTREAM_SERVER_URL='http://localhost:3333'
JETSTREAM_POSTGRES_DBURI='postgres://postgres@localhost:5432/postgres'

# trace, debug (default), info, warn, error, fatal, silent - determines how much server logging is done
LOG_LEVEL='trace'

# PLAYWRIGHT INTEGRATION TEST LOGIN
E2E_LOGIN_USERNAME='[email protected]'
E2E_LOGIN_PASSWORD='TODO'
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ This project was generated using [Nx](https://nx.dev) - This repository is consi
├── electron-scripts
├── libs (CORE LIBRARIES SHARED ACROSS ALL APPLICATIONS)
│ ├── api-config
│ ├── api-interfaces
│ ├── connected (FRONTEND DATA LIBRARY)
│ ├── icon-factory (SFDC ICONS)
│ ├── monaco-configuration
Expand Down
3 changes: 2 additions & 1 deletion app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"license": "PRIVATE",
"repository": "https://github.com/jetstreamapp/jetstream",
"engines": {
"node": ">=16 <17"
"node": ">= 20",
"yarn": "1.22.21"
},
"private": true,
"dependencies": {
Expand Down
47 changes: 26 additions & 21 deletions apps/api/src/app/controllers/auth.controller.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { ENV, logger } from '@jetstream/api-config';
import { ENV, getExceptionLog } from '@jetstream/api-config';
import { UserProfileServer } from '@jetstream/types';
import { NextFunction, Request, Response } from 'express';
import { NextFunction } from 'express';
import { isString } from 'lodash';
import * as passport from 'passport';
import { URL } from 'url';
import { hardDeleteUserAndOrgs } from '../db/transactions.db';
import { createOrUpdateUser } from '../db/user.db';
import { checkAuth } from '../routes/route.middleware';
// import { sendWelcomeEmail } from '../services/worker-jobs';
import { linkIdentity } from '../services/auth0';
import { Request, Response } from '../types/types';
import { AuthenticationError } from '../utils/error-handler';
// import { sendWelcomeEmail } from '../services/worker-jobs';

export interface OauthLinkParams {
type: 'auth' | 'salesforce';
Expand All @@ -30,17 +31,17 @@ export async function login(req: Request, res: Response) {
const user = req.user as UserProfileServer;
req.logIn(user, async (err) => {
if (err) {
logger.warn('[AUTH][ERROR] Error logging in %o', err, { requestId: res.locals.requestId });
req.log.warn({ ...getExceptionLog(err) }, '[AUTH][ERROR] Error logging in %o', err);
return res.redirect('/');
}

createOrUpdateUser(user)
.then(async ({ user: _user }) => {
logger.info('[AUTH][SUCCESS] Logged in %s', _user.email, { userId: user.id, requestId: res.locals.requestId });
req.log.info('[AUTH][SUCCESS] Logged in %s', _user.email);
res.redirect(ENV.JETSTREAM_CLIENT_URL!);
})
.catch((err) => {
logger.error('[AUTH][DB][ERROR] Error creating or sending welcome email %o', err, { requestId: res.locals.requestId });
req.log.error({ ...getExceptionLog(err) }, '[AUTH][DB][ERROR] Error creating or sending welcome email %o', err);
res.redirect('/');
});
});
Expand All @@ -59,28 +60,28 @@ export async function callback(req: Request, res: Response, next: NextFunction)
},
(err, user, info) => {
if (err) {
logger.warn('[AUTH][ERROR] Error with authentication %o', err, { requestId: res.locals.requestId });
req.log.warn({ ...getExceptionLog(err) }, '[AUTH][ERROR] Error with authentication %o', err);
return next(new AuthenticationError(err));
}
if (!user) {
logger.warn('[AUTH][ERROR] no user', { requestId: res.locals.requestId });
logger.warn('[AUTH][ERROR] no info %o', info, { requestId: res.locals.requestId });
req.log.warn('[AUTH][ERROR] no user');
req.log.warn('[AUTH][ERROR] no info %o', info);
return res.redirect('/oauth/login');
}
req.logIn(user, async (err) => {
if (err) {
logger.warn('[AUTH][ERROR] Error logging in %o', err, { requestId: res.locals.requestId });
req.log.warn('[AUTH][ERROR] Error logging in %o', err);
return next(new AuthenticationError(err));
}

createOrUpdateUser(user).catch((err) => {
logger.error('[AUTH][DB][ERROR] Error creating or sending welcome email %o', err, { requestId: res.locals.requestId });
req.log.error({ ...getExceptionLog(err) }, '[AUTH][DB][ERROR] Error creating or sending welcome email %o', err);
});

// TODO: confirm returnTo 0 it suddenly was reported as bad
const returnTo = (req.session as any).returnTo;
delete (req.session as any).returnTo;
logger.info('[AUTH][SUCCESS] Logged in %s', user.email, { userId: user.id, requestId: res.locals.requestId });
req.log.info('[AUTH][SUCCESS] Logged in %s', user.email);
res.redirect(returnTo || ENV.JETSTREAM_CLIENT_URL);
});
}
Expand Down Expand Up @@ -115,14 +116,13 @@ export async function linkCallback(req: Request, res: Response, next: NextFuncti
clientUrl: new URL(ENV.JETSTREAM_CLIENT_URL!).origin,
};
if (err) {
logger.warn('[AUTH][LINK][ERROR] Error with authentication %o', err, { requestId: res.locals.requestId });
req.log.warn({ ...getExceptionLog(err) }, '[AUTH][LINK][ERROR] Error with authentication %o', err);
params.error = isString(err) ? err : err.message || 'Unknown Error';
params.message = (req.query.error_description as string) || undefined;
return res.redirect(`/oauth-link/?${new URLSearchParams(params as any).toString()}`);
}
if (!userProfile) {
logger.warn('[AUTH][LINK][ERROR] no user', { requestId: res.locals.requestId });
logger.warn('[AUTH][LINK][ERROR] no info %o', info, { requestId: res.locals.requestId });
req.log.warn('[AUTH][LINK][ERROR] no user');
params.error = 'Authentication Error';
params.message = (req.query.error_description as string) || undefined;
return res.redirect(`/oauth-link/?${new URLSearchParams(params as any).toString()}`);
Expand All @@ -137,16 +137,21 @@ export async function linkCallback(req: Request, res: Response, next: NextFuncti
try {
await hardDeleteUserAndOrgs(userProfile.user_id);
} catch (ex) {
logger.warn('[AUTH0][IDENTITY][LINK][ERROR] Failed to delete the secondary user orgs %s', userProfile.user_id, {
userId: user.id,
secondaryUserId: userProfile.user_id,
requestId: res.locals.requestId,
});
req.log.warn(
{
userId: user.id,
secondaryUserId: userProfile.user_id,

...getExceptionLog(ex),
},
'[AUTH0][IDENTITY][LINK][ERROR] Failed to delete the secondary user orgs %s',
userProfile.user_id
);
}

return res.redirect(`/oauth-link/?${new URLSearchParams(params as any).toString()}`);
} catch (ex) {
logger.warn('[AUTH][LINK][ERROR] Error linking account %o', err, { requestId: res.locals.requestId });
req.log.warn({ ...getExceptionLog(ex) }, '[AUTH][LINK][ERROR] Error linking account %s', ex);
params.error = 'Unexpected Error';
return res.redirect(`/oauth-link/?${new URLSearchParams(params as any).toString()}&clientUrl=${ENV.JETSTREAM_CLIENT_URL}`);
}
Expand Down
22 changes: 12 additions & 10 deletions apps/api/src/app/controllers/image.controller.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
import { ENV } from '@jetstream/api-config';
import { UserProfileServer } from '@jetstream/types';
import { v2 as cloudinary } from 'cloudinary';
import { NextFunction, Request, Response } from 'express';
import { UserFacingError } from '../utils/error-handler';
import { sendJson } from '../utils/response.handlers';
import { createRoute } from '../utils/route.utils';

cloudinary.config({ secure: true });

export const routeValidators = {
getUploadSignature: [],
export const routeDefinition = {
getUploadSignature: {
controllerFn: () => getUploadSignature,
validators: {
hasSourceOrg: false,
},
},
};

export async function getUploadSignature(req: Request, res: Response, next: NextFunction) {
const getUploadSignature = createRoute(routeDefinition.getUploadSignature.validators, async ({ user }, req, res, next) => {
try {
const user = req.user as UserProfileServer;
const timestamp = Math.round(new Date().getTime() / 1000);
const cloudName = cloudinary.config().cloud_name;
const apiKey = cloudinary.config().api_key;
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const apiSecret = cloudinary.config().api_secret!;
const context = `caption=${user.id.replace('|', '\\|')}|environment=${ENV.JETSTREAM_SERVER_URL}`;

const signature = cloudinary.utils.api_sign_request({ timestamp: timestamp, upload_preset: 'jetstream-issues', context }, apiSecret);
const signature = cloudinary.utils.api_sign_request({ timestamp, upload_preset: 'jetstream-issues', context }, apiSecret);

sendJson(res, { signature: signature, timestamp: timestamp, cloudName: cloudName, apiKey: apiKey, context }, 200);
sendJson(res, { signature: signature, timestamp, cloudName: cloudName, apiKey: apiKey, context }, 200);
} catch (ex) {
next(new UserFacingError(ex.message));
}
}
});
Loading

0 comments on commit eb055a3

Please sign in to comment.