Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
IMiddlewareError, Err, Next, Request, Response,
OverrideMiddleware, GlobalErrorHandlerMiddleware
} from 'ts-express-decorators';
import { ValidatorError } from 'typescript-param-validator';
import { API_ERRORS } from '../types/app.errors';
import { ApiError } from '../utils/error';
export interface IApiErrorResponse {
code: number;
status: number;
message: string;
stack?: string;
reasons?: string[];
}
@OverrideMiddleware(GlobalErrorHandlerMiddleware)
export class ServerErrorMiddleware implements IMiddlewareError {
constructor() {}
public use(
@Err() error: ApiError | ValidatorError,
@Request() request: ExpressRequest,
@Response() res: ExpressResponse,
@Next() next: ExpressNext
) {
// tslint:disable-next-line
let { status, code, message } = error as ApiError;
const response: IApiErrorResponse = {
message: message || 'Error occurred',
code: code,
status
lastName: string;
@prop()
@JsonProperty()
password?: string;
@prop()
@JsonProperty()
picture?: string;
// Providers data
@prop() facebook?: string;
@arrayProp({ items: AuthToken }) tokens?: AuthToken[];
@prop()
@JsonProperty({
use: String
})
get fullName() {
return `${this.firstName} ${this.lastName}`;
}
@instanceMethod
matchPassword(candidatePassword: string) {
return new Promise((resolve) => {
bcrypt.compare(String(candidatePassword), this.password, (err, isMatch) => {
if (err || !isMatch) return resolve(false);
resolve(true);
});
});
}
import * as passport from 'passport';
import * as FacebookTokenStrategy from 'passport-facebook-token';
import { Strategy as LocalStrategy } from 'passport-local';
import { ExpressApplication, Inject, Service } from 'ts-express-decorators';
import { AuthProviderEnum } from '../../../dal/User';
import { IAppRequest } from '../../../types/app.types';
import { IAuthProviderProfileDto } from '../auth.dto';
import { AuthService } from '../auth.service';
export enum AUTH_STRATEGY {
FACEBOOK_TOKEN_STRATEGY = 'facebook-token',
LOCAL_STRATEGY = 'local'
}
@Service()
export class PassportService {
constructor(
private authService: AuthService,
@Inject(ExpressApplication) private expressApplication: ExpressApplication
) {
}
$beforeRoutesInit() {
this.expressApplication.use(passport.initialize());
passport.use(AUTH_STRATEGY.LOCAL_STRATEGY, this.passportLocalStrategy);
passport.use(AUTH_STRATEGY.FACEBOOK_TOKEN_STRATEGY, this.facebookTokenStrategy);
}
private passportLocalStrategy = new LocalStrategy({
usernameField: 'email',
passReqToCallback: true
import { Inject, Service } from 'ts-express-decorators';
import { UserRepositoryToken } from '../../dal/token-constants';
import { UserRepository } from '../../dal/User';
@Service()
export class UserService {
constructor(
@Inject(UserRepositoryToken) private userRepository: UserRepository
) {
}
async getUserById(id: string) {
return await this.userRepository.findById(id, 'firstName lastName email fullName picture');
}
}
import * as mongoose from 'mongoose';
import { Service } from 'ts-express-decorators';
(mongoose as any).Promise = global.Promise;
@Service()
export class MongooseService {
static resource: mongoose.Connection;
static async connect(): Promise {
const mongoUrl = process.env.MONGODB_URI;
if (MongooseService.resource) {
return MongooseService.resource;
}
const db = await mongoose.connect(mongoUrl, {
useMongoClient: true
});
MongooseService.resource = db;
return db;
import * as _ from "lodash";
import { instrumented } from "monkit";
import { Service } from "ts-express-decorators";
import { authorized } from "../auth/decorators";
import { Query } from "../schema/decorators";
import { Context } from "../server/server";
import { tracer } from "../server/tracing";
import { FeatureStore } from "./feature_store";
import { Feature } from "../generated/types";
@Service()
export class FeatureResolvers {
constructor(
private readonly featureStore: FeatureStore,
) {}
@Query("ship-cloud")
@authorized()
@instrumented({ tags: ["tier:resolver"] })
async userFeatures(root: any, args: any, context: Context): Promise {
const span = tracer().startSpan("query.listUserFeatures");
span.setTag("userId", context.userId);
const features = await this.featureStore.listUserFeatures(span.context(), context.userId);
const result = features.map(feature => this.toSchemaFeature(feature, root, context));
span.finish();
} from "../generated/types";
import { ShipNotification } from "../notification/resolver";
import { NotificationStore } from "../notification/store";
import { Mutation, Query } from "../schema/decorators";
import { ReplicatedError } from "../server/errors";
import { logger } from "../server/logger";
import { Context } from "../server/server";
import { tracer } from "../server/tracing";
import { storeTransaction } from "../util/persistence/db";
import { schema } from "./schema";
import { WatchStore } from "./watch_store";
import { FeatureResolvers } from "../feature/resolver";
import { ClusterStore } from "../cluster/cluster_store";
import { WatchDownload } from "./download";
@Service()
export class Watch {
constructor(
private readonly watchStore: WatchStore,
private readonly userStore: UserStore,
private readonly clusterStore: ClusterStore,
private readonly notificationStore: NotificationStore,
private readonly shipNotificationResolver: ShipNotification,
private readonly featureResolver: FeatureResolvers,
private readonly downloadService: WatchDownload,
) {}
@Mutation("ship-cloud")
@authorized()
async deployWatchVersion(root: any, args: DeployWatchVersionMutationArgs, context: Context): Promise {
const span = tracer().startSpan("mutation.deployShipOpsClusterVersion")
import { UserRepositoryToken } from '../../dal/token-constants';
import { AuthProviderEnum, UserInstance, UserRepository } from '../../dal/User';
import { API_ERRORS } from '../../types/app.errors';
import { MongoErrorCode } from '../../types/mongo';
import { ApiError } from '../../utils/error';
import { UnexpectedError } from '../../utils/error/UnexpectedError';
import { validateEmail } from '../../utils/helper.service';
import { AuthDto, IAuthProviderProfileDto } from './auth.dto';
import { Request, Response, NextFunction } from 'express';
import { PassportAuthService } from './passport/passport-auth.service';
import { AUTH_STRATEGY } from './passport/passport.service';
const DAY = 60000 * 60 * 24;
export const TOKEN_EXP = DAY * 7;
@Service()
export class AuthService {
private USER_TOKEN_FIELDS = '_id email lastName firstName picture fullName';
constructor(
@Inject(UserRepositoryToken) public userRepository: UserRepository,
private passportAuthService: PassportAuthService
) {
}
/**
* Used to fetch user based on its id.
*
* There are multiple approaches with working with jwt,
* You can skip the hydration process and use only the jwt token as the user data.
* But if you need to invalidate user token dynamically a db/redis query should be made.
import { instrumented } from "monkit";
import { Service } from "ts-express-decorators";
import { authorized } from "../auth/decorators";
import { CreateUpdateSessionMutationArgs, UpdateSession } from "../generated/types";
import { Mutation } from "../schema/decorators";
import { Context } from "../server/server";
import { tracer } from "../server/tracing";
import { UpdateStore } from "./store";
@Service()
export class Update {
constructor(private readonly updateStore: UpdateStore) {}
@Mutation("ship-cloud")
@authorized()
@instrumented({ tags: ["tier:resolver"] })
async createUpdateSession(root: any, { watchId }: CreateUpdateSessionMutationArgs, context: Context): Promise {
const span = tracer().startSpan("mutation.createUpdateSession");
const updateSession = await this.updateStore.createUpdateSession(span.context(), context.userId, watchId);
const deployedUpdateSession = await this.updateStore.deployUpdateSession(span.context(), updateSession.id!);
span.finish();
return deployedUpdateSession;
}
import { ClusterStore } from "./cluster_store";
import { SessionStore } from "../session/store";
import { Service } from "ts-express-decorators";
import { Query, Mutation } from "../schema/decorators";
import { authorized } from "../auth/decorators";
import { ClusterItem } from "../generated/types";
import { tracer } from "../server/tracing";
import { Context } from "../server/server";
import { WatchStore } from "../watch/watch_store";
@Service()
export class Cluster {
constructor(
private readonly clusterStore: ClusterStore,
private readonly watchStore: WatchStore,
private readonly sessionStore: SessionStore,
) {}
@Query("ship-cloud")
@authorized()
async listClusters(root: any, args: any, context: Context): Promise {
const span = tracer().startSpan("query.listClusters");
span.setTag("userId", context.userId);
const clusters = await this.clusterStore.listClusters(span.context(), context.userId);
const result = clusters.map(cluster => this.toSchemaCluster(cluster, root, context));