Skip to content

Commit

Permalink
Add v2 authentication
Browse files Browse the repository at this point in the history
Connection to firebase
Firebae user creation / update / deletion
User verification by phone number

Updated nominations model to use firebase id
Added http strategy to verify user token
Comment out v1 authentication
  • Loading branch information
chimon2000 committed May 16, 2018
1 parent bea9ed7 commit 0d6f7ac
Show file tree
Hide file tree
Showing 41 changed files with 1,067 additions and 850 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ yarn-error.log*
/server-notypes
nodemon.sh
.cache
dist/
dist/
service-account-key.json
6 changes: 3 additions & 3 deletions backend/common/src/entities/attachment.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn, BaseEntity } from 'typeorm';
import { Household } from './household';
import { User } from './user';
import { Nominator } from './nominator';

@Entity('household_attachments')
export class Attachment extends BaseEntity {
Expand All @@ -21,9 +21,9 @@ export class Attachment extends BaseEntity {
@JoinColumn({ name: 'household_id' })
household: Household;

@ManyToOne(() => User)
@ManyToOne(() => Nominator)
@JoinColumn({ name: 'owner_id' })
user: User;
user: Nominator;

static fromJSON(props) {
const entity = new Attachment(props);
Expand Down
4 changes: 2 additions & 2 deletions backend/common/src/entities/household.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ export class Household extends BaseEntity {

@PrimaryGeneratedColumn() id: number;

@Column('int', { name: 'nominator_id' })
nominatorId: number;
@Column('text', { name: 'nominator_id' })
nominatorId: string;

@Column('varchar', <ExtendedColumnOptions>{
name: 'name_first',
Expand Down
1 change: 0 additions & 1 deletion backend/common/src/entities/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
export { Address } from './address';
export { Affiliation } from './affiliation';
export { User } from './user';
export { Household } from './household';
export { PhoneNumber } from './phone-number';
export { Child } from './child';
Expand Down
40 changes: 30 additions & 10 deletions backend/common/src/entities/nominator.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,52 @@
import { Affiliation } from './affiliation';
import { Entity, Column, OneToMany, OneToOne, JoinColumn } from 'typeorm';
import { Household } from './household';
import AbstractUser from './abstract/user';
import { Affiliation, Household } from 'cmpd-common-api';
import { BaseEntity, Column, Entity, JoinColumn, OneToMany, OneToOne, PrimaryColumn } from 'typeorm';

@Entity('users')
export class Nominator extends AbstractUser {
@Entity('nominators')
export class Nominator extends BaseEntity {
private constructor(props) {
super();

Object.assign(this, props);
}

@PrimaryColumn('text') id: string;

@Column('text') name: string;

@Column('text') email: string;

@Column('text', { nullable: true })
rank: string;

@Column('text', { nullable: true })
role: string;

@Column('text', { nullable: true })
phone: string;

@Column('boolean', { default: true })
disabled: boolean;

@Column('boolean', { name: 'email_verified', default: false })
emailVerified: boolean;

@Column('text') phoneNumber: string;

@Column('int', { name: 'nomination_limit', default: 5 })
nominationLimit: number;

@Column('int', { name: 'affiliation_id', nullable: true })
affiliationId: number;

@OneToOne(() => Affiliation)
@JoinColumn({ name: 'affiliation_id' })
affiliation: Affiliation;

@Column('int', { name: 'nomination_limit', default: 5 })
nominationLimit: number;

@OneToMany(() => Household, household => household.nominator)
households: Household[];

static fromJSON(props) {
const entity = new Nominator(props);

return entity;
}
}
6 changes: 3 additions & 3 deletions backend/common/src/entities/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
CreateDateColumn,
UpdateDateColumn
} from 'typeorm';
import { User } from './user';
import { Nominator } from '.';

@Entity('sessions')
export class Session extends BaseEntity {
Expand All @@ -25,7 +25,7 @@ export class Session extends BaseEntity {
@Column('int', { name: 'user_id' })
userId: number;

@OneToOne(() => User, { eager: true })
@OneToOne(() => Nominator, { eager: true })
@JoinColumn({ name: 'user_id' })
user: User;
user: Nominator;
}
80 changes: 0 additions & 80 deletions backend/common/src/entities/user.ts

This file was deleted.

3 changes: 2 additions & 1 deletion backend/common/src/error/application-error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ export const handleErrors = errorMap => (error: Error) => {

if (error instanceof ApplicationError) {
const { code = 'default' } = error;

const ErrorToThrow = errorMap[code];

throw new ErrorToThrow();
throw ErrorToThrow ? new ErrorToThrow() : error;
}

throw error;
Expand Down
Binary file removed backend/nominations-api/run/db.development.sqlite
Binary file not shown.
10 changes: 10 additions & 0 deletions backend/nominations-api/src/app.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Get, Controller, Render } from '@nestjs/common';

@Controller()
export class AppController {
@Get()
@Render('index')
root() {
return { message: 'Hello world!' };
}
}
59 changes: 28 additions & 31 deletions backend/nominations-api/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,48 @@
import { MiddlewaresConsumer, Module, RequestMethod } from '@nestjs/common';
import { GraphQLFactory, GraphQLModule } from '@nestjs/graphql';
// import { graphqlExpress } from 'apollo-server-express';
// import { mergeSchemas } from 'graphql-tools';
import { UploadMiddleware } from './common/middlewares/upload.middleware';
import config from './config';
import { MiddlewareConsumer, Module } from '@nestjs/common';
import { GraphQLModule } from '@nestjs/graphql';
// import { typeDefs } from './modules/affiliations';
import { AffiliationsModule } from './modules/affiliations';
import { AuthModule } from './modules/auth';
import auth from './modules/lib/auth';
import { CmpdModule } from './modules/cmpd/cmpd.module';
import { HouseholdsModule } from './modules/households';
import { TrackingModule } from './modules/tracking';
import { UsersModule } from './modules/users/users.module';
import { CmpdModule } from './modules/cmpd/cmpd.module';
import { AppController } from './app.controller';

const allRoutes = {
path: '*',
method: RequestMethod.ALL
};
// const allRoutes = {
// path: '*',
// method: RequestMethod.ALL
// };

const nominationRoutes = {
path: 'api/nominations/*',
method: RequestMethod.ALL
};
// const nominationRoutes = {
// path: 'api/nominations/*',
// method: RequestMethod.ALL
// };

const authRoutes = {
path: 'api/auth/*',
method: RequestMethod.ALL
};
// const authRoutes = {
// path: 'api/auth/*',
// method: RequestMethod.ALL
// };

@Module({
modules: [GraphQLModule, AuthModule, HouseholdsModule, AffiliationsModule, TrackingModule, UsersModule, CmpdModule]
modules: [GraphQLModule, AuthModule, HouseholdsModule, AffiliationsModule, TrackingModule, UsersModule, CmpdModule],
controllers: [AppController]
})
export class AppModule {
constructor(private readonly graphQLFactory: GraphQLFactory) {}
constructor() {}

configure(consumer: MiddlewaresConsumer): void {
consumer.apply(auth.authMiddleware(config.jwtSecrets.auth)).forRoutes(authRoutes);
consumer.apply(auth.authMiddleware(config.jwtSecrets.nominations)).forRoutes(nominationRoutes);
consumer.apply(auth.sessionMiddleware).forRoutes(allRoutes);
consumer.apply(UploadMiddleware).forRoutes({
path: '/api/nominations/:id/upload',
method: RequestMethod.PUT
});
configure(consumer: MiddlewareConsumer): void {
// consumer.apply(auth.authMiddleware(config.jwtSecrets.auth)).forRoutes(authRoutes);
// consumer.apply(auth.authMiddleware(config.jwtSecrets.nominations)).forRoutes(nominationRoutes);
// consumer.apply(auth.sessionMiddleware).forRoutes(allRoutes);
// consumer.apply(UploadMiddleware).forRoutes({
// path: '/api/nominations/:id/upload',
// method: RequestMethod.PUT
// });
this.setupGraphQl(consumer);
}

setupGraphQl(consumer: MiddlewaresConsumer) {
setupGraphQl(_: MiddlewareConsumer) {
// const localSchema = this.graphQLFactory.createSchema({ typeDefs });
// const delegates = this.graphQLFactory.createDelegates();
// const schema = mergeSchemas({
Expand Down
2 changes: 2 additions & 0 deletions backend/nominations-api/src/common/guards/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './auth.guard';
export * from './roles.guard';
8 changes: 4 additions & 4 deletions backend/nominations-api/src/common/guards/roles.guard.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Guard, CanActivate, ExecutionContext } from '@nestjs/common';
import { CanActivate, ExecutionContext, Guard } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { pathOr } from 'ramda';

@Guard()
export class RolesGuard implements CanActivate {
constructor(private readonly reflector: Reflector) {}

canActivate(req, context: ExecutionContext): boolean {
const { handler } = context;
canActivate(context: ExecutionContext): boolean {
const handler = context.getHandler();
const [req] = context.getArgs();
const roles = this.reflector.get<string[]>('roles', handler);
if (!roles) {
return true;
Expand Down
9 changes: 9 additions & 0 deletions backend/nominations-api/src/common/services/firebase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import * as admin from 'firebase-admin';
var serviceAccount = require('../../../service-account-key.json');

admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: 'https://passwordless-auth-a5939.firebaseio.com'
});

export default admin;
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const handleErrors = errorMap => (error: Error) => {

if (error instanceof ApplicationError) {
const { code = 'default' } = error;
console.log(code);
const ErrorToThrow = errorMap[code];

throw new ErrorToThrow();
Expand Down
2 changes: 1 addition & 1 deletion backend/nominations-api/src/config/env.default.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ if (process.env.NODE_ENV === 'production') {
}

// Web app settings
config.port = 3001;
config.port = 3002;
config.useCompression = true;

// Verbosity
Expand Down
14 changes: 2 additions & 12 deletions backend/nominations-api/src/instances/database.providers.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,4 @@
import {
Address,
Affiliation,
Attachment,
Child,
Household,
Nominator,
PhoneNumber,
Session,
User
} from 'cmpd-common-api';
import { Address, Affiliation, Attachment, Child, Household, Nominator, PhoneNumber, Session } from 'cmpd-common-api';
import { createConnection } from 'typeorm';
import { AutoEncryptSubscriber } from 'typeorm-encrypted';
import config from '../config';
Expand All @@ -22,7 +12,7 @@ export const databaseProviders = [
await createConnection({
type,
database,
entities: [Affiliation, Nominator, User, Session, Attachment, Household, PhoneNumber, Address, Child],
entities: [Affiliation, Nominator, Session, Attachment, Household, PhoneNumber, Address, Child],
subscribers: [AutoEncryptSubscriber]
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export class AffiliationsResolver {
constructor(private readonly affiliationService: AffiliationService) {}

@Query('affiliation')
async getAffiliation(obj, args, context, info) {
async getAffiliation(obj, args) {
const affiliation = await this.affiliationService.getAffiliation(args.id);

return affiliation;
Expand Down
Loading

0 comments on commit 0d6f7ac

Please sign in to comment.