Feature/4 pilots add (#20)

* changing api url to env variable

* updating env variables

* updating env variables

* updating env variables

* updating env variables

* updating env variables

* updating env variables

* feature/4-pilots---add

* feature/4-pilots---add

* feature/4-pilots---add

* feature/4-pilots---add

* ad pilot

* add pilot

* add pilot

* add pilot

* add pilot

* add pilot

* adding pilots

* add pilot

* add pilot

* add pilots

* add pilot

* add pilot

* adding pilots

* adding pilots

* adding pilots

* adding pilots

* adding pilots

* adding pilots

* adding pilots

* adding pilots

* adding pilots

* adding pilots

* adding pilots

* adding pilot

* adding pilot

* adding pilot

* adding pilot

* adding pilot

* adding pilot

* adding pilot

* adding pilot

* adding pilot

* adding pilot

* adding pilot

* adding pilot

* adding pilot

* adding pilot

* adding pilot

* adding pilot

* adding pilot

* adding pilot

* adding pilot

* adding pilot

* Testing menu button

* Testing menu button

* Testing menu button

* Testing menu button

* adding pilot

* adding pilot

* adding pilot

* adding pilot

* adding pilot

* adding pilot

---------

Co-authored-by: Noah Spannbauer <nspannbauer@sensonix.com>
This commit was merged in pull request #20.
This commit is contained in:
2024-09-23 20:52:59 -05:00
committed by GitHub
parent 80b4fb8c1d
commit 071e211525
53 changed files with 4184 additions and 13161 deletions

View File

@@ -1,4 +1,11 @@
import { Controller, Get, Query } from '@nestjs/common';
import {
Controller,
Get,
Headers,
Query,
Res,
StreamableFile
} from '@nestjs/common';
import {
AppConfigService,
MsGraphService,
@@ -6,10 +13,17 @@ import {
} from '@noahspan/noahspan-modules';
import { FeatureFlagValue } from '@azure/app-configuration';
import { Public } from '@noahspan/noahspan-modules';
import { Person } from '@microsoft/microsoft-graph-types';
import { AppService } from './app.service';
import { createReadStream } from 'fs';
import { join } from 'path';
import { arrayBuffer } from 'stream/consumers';
import type { Response } from 'express';
@Controller()
export class AppController {
constructor(
private readonly appService: AppService,
private readonly appConfigService: AppConfigService,
private readonly msGraphService: MsGraphService
) {}
@@ -37,21 +51,58 @@ export class AppController {
}
}
@Public()
@Get('profilePhoto')
async getProfilePhoto(@Query() query: any): Promise<any> {}
@Get('userPhoto')
async getProfilePhoto(@Headers() headers: any): Promise<StreamableFile> {
try {
const graphToken: string = await this.msGraphService.getMsGraphAuth(
headers.authorization.replace('Bearer ', ''),
['user.read']
);
const client: MsGraphClient =
await this.msGraphService.getMsGraphClientDelegated(graphToken);
const blob: Blob = await client.api(`me/photos('48x48')/$value`).get();
const arrayBuffer: ArrayBuffer = await blob.arrayBuffer();
const buffer: Buffer = Buffer.from(arrayBuffer);
return new StreamableFile(buffer, {
type: 'application/json',
disposition: `attachment; filename="user_photo.png"`
});
} catch (error) {
return error;
}
}
@Get('userProfile')
async getUserProfile(@Query() query: any) {
async getUserProfile(@Headers() headers: any) {
try {
const username: string = query.username;
const graphToken: string = await this.msGraphService.getMsGraphAuth(
headers.authorization.replace('Bearer ', ''),
['user.read']
);
const client: MsGraphClient =
await this.msGraphService.getMsGraphClient();
const userProfile = await client.api(`users/${username}`).get();
await this.msGraphService.getMsGraphClientDelegated(graphToken);
const userProfile = await client.api(`me`).get();
return userProfile;
} catch (error) {
return error;
}
}
@Get('personSearch')
async searchUsers(
@Headers() headers: any,
@Query('search') search: any
): Promise<Person[]> {
try {
const accessToken: string = headers.authorization.replace('Bearer ', '');
const personSearchResults: Person[] =
await this.appService.getPersonSearchResults(accessToken, search);
console.log(personSearchResults);
return personSearchResults;
} catch (error) {
return error;
}
}
}

View File

@@ -9,6 +9,9 @@ import {
} from '@noahspan/noahspan-modules';
import { ConfigModule } from '@nestjs/config';
import { APP_GUARD } from '@nestjs/core';
import { PilotModule } from './pilot/pilot.module';
import { APP_FILTER } from '@nestjs/core';
import { HttpExceptionFilter } from './filters/http-exception.filter';
@Module({
imports: [
@@ -28,7 +31,8 @@ import { APP_GUARD } from '@nestjs/core';
tenantId: process.env.TENANT_ID,
clientId: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET
})
}),
PilotModule
],
controllers: [AppController],
providers: [
@@ -36,6 +40,10 @@ import { APP_GUARD } from '@nestjs/core';
provide: APP_GUARD,
useClass: AuthGuard
},
{
provide: APP_FILTER,
useClass: HttpExceptionFilter
},
AppService
]
})

View File

@@ -1,8 +1,44 @@
import { Injectable } from '@nestjs/common';
import { MsGraphService, MsGraphClient } from '@noahspan/noahspan-modules';
import { Person } from '@microsoft/microsoft-graph-types';
@Injectable()
export class AppService {
constructor(private readonly msGraphService: MsGraphService) {}
getHello(): string {
return 'Hello World!';
}
async getPersonSearchResults(
accessToken: string,
search: string
): Promise<Person[]> {
try {
const graphToken: string = await this.msGraphService.getMsGraphAuth(
accessToken,
['user.read']
);
const client: MsGraphClient =
await this.msGraphService.getMsGraphClientDelegated(graphToken);
const results: any = await client
.api(`me/people/?$search=${search}`)
.get();
let personResults: Person[];
if (results.value) {
personResults = results.value.filter((result: Person) => {
if (result.userPrincipalName !== null) {
return result;
}
});
} else {
personResults = [];
}
return personResults;
} catch (error) {
throw new Error(error);
}
}
}

View File

@@ -0,0 +1,9 @@
export class CustomError extends Error {
statusCode: number;
constructor(message, name, statusCode) {
super(message);
this.name = name;
this.statusCode = statusCode;
}
}

View File

@@ -0,0 +1,26 @@
import {
ExceptionFilter,
Catch,
ArgumentsHost,
HttpException
} from '@nestjs/common';
import { Request, Response } from 'express';
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
catch(excpetion: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
const status = excpetion.getStatus();
console.log(excpetion.cause);
response.status(status).json({
name: excpetion.cause,
message: excpetion.message,
statusCode: status,
timestamp: new Date().toISOString(),
path: request.url
});
}
}

View File

@@ -1,8 +1,25 @@
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { HttpService } from '@nestjs/axios';
import { HttpExceptionFilter } from './filters/http-exception.filter';
import { InternalServerErrorException } from '@nestjs/common';
async function bootstrap() {
const httpService = new HttpService();
const app = await NestFactory.create(AppModule);
app.useGlobalFilters(new HttpExceptionFilter());
httpService.axiosRef.interceptors.response.use(
(response) => {
return response;
},
(error) => {
console.error('Internal server error exception', error);
throw new InternalServerErrorException();
}
);
await app.listen(3000);
}
bootstrap();

View File

@@ -0,0 +1,7 @@
export class Certificate {
partitionKey: string;
rowKey: string;
type: string;
issueDate: Date;
number?: string;
}

View File

@@ -0,0 +1,37 @@
import { Injectable } from '@nestjs/common';
import { Repository, InjectRepository } from '@nestjs/azure-database';
import { Certificate } from './certificate.entity';
@Injectable()
export class CertificateService {
private readonly partitionKey: string = 'certificate';
constructor(
@InjectRepository(Certificate)
private readonly certificateRepository: Repository<Certificate>
) {}
async find(rowKey: string): Promise<Certificate> {
return await this.certificateRepository.find(this.partitionKey, rowKey);
}
async findAll(): Promise<Certificate[]> {
return await this.certificateRepository.findAll();
}
async create(certificate: Certificate): Promise<Certificate> {
return await this.certificateRepository.create(certificate);
}
async update(rowKey: string, certificate: Certificate): Promise<Certificate> {
return await this.certificateRepository.update(
this.partitionKey,
rowKey,
certificate
);
}
async delete(rowKey: string): Promise<void> {
await this.certificateRepository.delete(this.partitionKey, rowKey);
}
}

View File

@@ -0,0 +1,6 @@
export class Endorsement {
partitionkey: string;
rowKey: string;
type: string;
issueDate: Date;
}

View File

@@ -0,0 +1,37 @@
import { InjectRepository, Repository } from '@nestjs/azure-database';
import { Injectable } from '@nestjs/common';
import { Endorsement } from './endorsement.entity';
@Injectable()
export class EndosementService {
private readonly partitionKey: string = 'endorsement';
constructor(
@InjectRepository(Endorsement)
private readonly endorsementRepository: Repository<Endorsement>
) {}
async find(rowKey: string): Promise<Endorsement> {
return await this.endorsementRepository.find(this.partitionKey, rowKey);
}
async findAll(): Promise<Endorsement[]> {
return await this.endorsementRepository.findAll();
}
async create(endorsement: Endorsement): Promise<Endorsement> {
return await this.endorsementRepository.create(endorsement);
}
async update(rowKey: string, endorsement: Endorsement): Promise<Endorsement> {
return await this.endorsementRepository.update(
this.partitionKey,
rowKey,
endorsement
);
}
async delete(rowKey: string): Promise<void> {
await this.endorsementRepository.delete(this.partitionKey, rowKey);
}
}

View File

@@ -0,0 +1,10 @@
export class PilotInfoDto {
id: string;
name: string;
address: string;
city: string;
state: string;
postalCode: string;
email?: string;
phone?: string;
}

View File

@@ -0,0 +1,12 @@
export class PilotInfoEntity {
partitionKey: string;
rowKey: string;
id: string;
name: string;
address?: string;
city?: string;
state?: string;
postalCode?: string;
email?: string;
phone?: string;
}

View File

@@ -0,0 +1,83 @@
import { Injectable } from '@nestjs/common';
import { PilotInfoDto } from './pilot-info.dto';
import { PilotInfoEntity } from './pilot-info.entity';
import { TableClient, TableService } from '@noahspan/noahspan-modules';
import { odata, RestError, TableInsertEntityHeaders } from '@azure/data-tables';
import { CustomError } from '../../customError/CustomError';
@Injectable()
export class PilotInfoService {
private readonly partitionKey: string = 'info';
constructor(private readonly tableService: TableService) {}
// async find(rowKey: string): Promise<PilotInfo> {
// return await this.pilotInfoRepository.find(this.partitionKey, rowKey);
// }
async findAll(): Promise<PilotInfoEntity[]> {
try {
const client: TableClient =
await this.tableService.getTableClient('Pilots');
const entities = await client.listEntities({
queryOptions: { filter: odata`PartitionKey eq 'pilot'` }
});
const pilots: PilotInfoEntity[] = [];
for await (const entity of entities) {
const pilot: PilotInfoEntity = {
partitionKey: entity.partitionKey,
rowKey: entity.rowKey,
id: entity.id.toString(),
name: entity.name.toString()
};
pilots.push(pilot);
}
return pilots;
} catch (error) {
const restError: RestError = error as RestError;
throw new CustomError(
restError.details['odataError']['message']['value'],
restError.details['odataError']['code'],
restError.statusCode
);
}
}
async create(pilotInfoData: PilotInfoDto): Promise<TableInsertEntityHeaders> {
const client: TableClient =
await this.tableService.getTableClient('Pilots');
const pilotInfo: PilotInfoEntity = new PilotInfoEntity();
Object.assign(pilotInfo, pilotInfoData);
pilotInfo.partitionKey = 'pilot';
pilotInfo.rowKey = pilotInfo.id;
try {
return await client.createEntity(pilotInfo);
} catch (error) {
const restError: RestError = error as RestError;
throw new CustomError(
restError.details['odataError']['message']['value'],
restError.details['odataError']['code'],
restError.statusCode
);
}
}
// async update(rowKey: string, pilotInfo: PilotInfo): Promise<PilotInfo> {
// return await this.pilotInfoRepository.update(
// this.partitionKey,
// rowKey,
// pilotInfo
// );
// }
// async delete(rowKey: string): Promise<void> {
// await this.pilotInfoRepository.delete(this.partitionKey, rowKey);
// }
}

View File

@@ -0,0 +1,6 @@
export class Medical {
partitionKey: string;
rowKey: string;
certificateClass: string;
certificateExpiration: Date;
}

View File

@@ -0,0 +1,33 @@
import { Injectable } from '@nestjs/common';
import { Repository, InjectRepository } from '@nestjs/azure-database';
import { Medical } from './medical.entity';
@Injectable()
export class MedicalService {
private readonly partitionKey: string = 'medical';
constructor(
@InjectRepository(Medical)
private readonly profileRepository: Repository<Medical>
) {}
async find(rowKey: string): Promise<Medical> {
return this.profileRepository.find(this.partitionKey, rowKey);
}
async findAll(): Promise<Medical[]> {
return this.profileRepository.findAll();
}
async create(profile: Medical): Promise<Medical> {
return this.profileRepository.create(profile);
}
async update(rowKey: string, profile: Medical): Promise<Medical> {
return this.profileRepository.update(this.partitionKey, rowKey, profile);
}
async delete(rowKey: string) {
return this.profileRepository.delete(this.partitionKey, rowKey);
}
}

View File

@@ -0,0 +1,40 @@
import { Body, Controller, Get, HttpException, Post } from '@nestjs/common';
import { PilotInfoService } from './info/pilot-info.service';
import { PilotInfoDto } from './info/pilot-info.dto';
import { TableInsertEntityHeaders } from '@azure/data-tables';
import { CustomError } from '../customError/CustomError';
import { PilotInfoEntity } from './info/pilot-info.entity';
@Controller('pilots')
export class PilotController {
constructor(private readonly pilotInfoService: PilotInfoService) {}
@Get()
async findAll(): Promise<PilotInfoEntity[]> {
try {
const pilots: PilotInfoEntity[] = await this.pilotInfoService.findAll();
return pilots;
} catch (error) {
const customError = error as CustomError;
throw new HttpException(customError.message, customError.statusCode, {
cause: customError.name
});
}
}
@Post()
async create(@Body() pilotInfoData: PilotInfoDto): Promise<void> {
try {
const response: TableInsertEntityHeaders =
await this.pilotInfoService.create(pilotInfoData);
} catch (error) {
const customError = error as CustomError;
throw new HttpException(customError.message, customError.statusCode, {
cause: customError.name
});
}
}
}

View File

@@ -0,0 +1,16 @@
import { Module } from '@nestjs/common';
import { PilotController } from './pilot.controller';
import { TableModule } from '@noahspan/noahspan-modules';
import { PilotInfoService } from './info/pilot-info.service';
@Module({
imports: [
TableModule.register({
accountName: process.env.AZURE_STORAGE_ACCOUNT_NAME,
accountKey: process.env.AZURE_STORAGE_ACCOUNT_KEY
})
],
controllers: [PilotController],
providers: [PilotInfoService]
})
export class PilotModule {}