Merge branch 'main' into dev

pull/31/head
leonnicolas 4 years ago committed by GitHub
commit b0ccfbf1c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

1134
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -15,17 +15,17 @@
"devDependencies": {
"@types/crc": "^3.4.0",
"@types/mocha-steps": "^1.3.0",
"@types/node": "^14.10.0",
"@typescript-eslint/eslint-plugin": "^4.1.0",
"@typescript-eslint/parser": "^4.1.0",
"@types/node": "^14.14.10",
"@typescript-eslint/eslint-plugin": "^4.9.0",
"@typescript-eslint/parser": "^4.9.0",
"chai": "^4.2.0",
"delete": "^1.1.0",
"eslint": "^7.8.1",
"eslint": "^7.14.0",
"eslint-config-standard": "^14.1.1",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.1",
"eslint-plugin-standard": "^4.1.0",
"gulp": "^4.0.2",
"gulp-eslint": "^6.0.0",
"gulp-nodemon": "^2.5.0",
@ -33,14 +33,14 @@
"mocha": "^8.2.1",
"mocha-steps": "^1.3.0",
"nyc": "^15.1.0",
"ts-node": "^9.0.0",
"typescript": "^4.0.2"
"ts-node": "^9.1.0",
"typescript": "^4.1.2"
},
"dependencies": {
"@types/chai": "^4.2.14",
"@types/chai-http": "^4.2.0",
"@types/mocha": "^8.0.4",
"apollo-server-express": "^2.17.0",
"apollo-server-express": "^2.19.0",
"body-parser": "^1.19.0",
"chai-http": "^4.3.0",
"cors": "^2.8.5",
@ -48,11 +48,11 @@
"dotenv": "^8.2.0",
"express": "^4.17.1",
"express-cors": "0.0.3",
"graphql": "^15.3.0",
"graphql": "^15.4.0",
"messagepack": "^1.1.12",
"pg": "^8.3.3",
"pg": "^8.5.1",
"promise-socket": "^7.0.0",
"reflect-metadata": "^0.1.13",
"typeorm": "^0.2.26"
"typeorm": "^0.2.29"
}
}

@ -20,7 +20,6 @@ This file is part of fLotte-API-Server.
import { DataSource } from 'apollo-datasource';
import { Connection, EntityManager, getConnection } from 'typeorm';
import { CargoBike } from '../../model/CargoBike';
import { GraphQLError } from 'graphql';
import { BikeEvent } from '../../model/BikeEvent';
import { Equipment } from '../../model/Equipment';
import { Engagement } from '../../model/Engagement';
@ -29,8 +28,9 @@ import { TimeFrame } from '../../model/TimeFrame';
import { ActionLogger, DBUtils, genBoxDimensions, LockUtils } from './utils';
import { EquipmentType } from '../../model/EquipmentType';
import { BikeEventType } from '../../model/BikeEventType';
import { UserInputError } from 'apollo-server-express';
import { Actions } from '../../model/ActionLog';
import { ResourceLockedError } from '../../errors/ResourceLockedError';
import { NotFoundError } from '../../errors/NotFoundError';
/**
* extended datasource to feed resolvers with data about cargoBikes
@ -83,10 +83,16 @@ export class CargoBikeAPI extends DataSource {
}
async lockCargoBike (id: number, userId: number) {
if (!await this.connection.getRepository(CargoBike).findOne(id)) {
throw new NotFoundError('CargoBike', 'id', id);
}
return await LockUtils.lockEntity(this.connection, CargoBike, 'cb', id, userId);
}
async unlockCargoBike (id: number, userId: number) {
if (!await this.connection.getRepository(CargoBike).findOne(id)) {
throw new NotFoundError('CargoBike', 'id', id);
}
return await LockUtils.unlockEntity(this.connection, CargoBike, 'cb', id, userId);
}
@ -107,7 +113,7 @@ export class CargoBikeAPI extends DataSource {
await this.connection.transaction(async (entityManager: EntityManager) => {
if (await LockUtils.isLocked(entityManager, CargoBike, 'cb', cargoBike.id, userId)) {
throw new GraphQLError('CargoBike locked by other user');
throw new ResourceLockedError('CargoBike');
}
await ActionLogger.log(entityManager, CargoBike, 'cb', cargoBike, userId);
await entityManager.getRepository(CargoBike)
@ -116,11 +122,13 @@ export class CargoBikeAPI extends DataSource {
.set({ ...cargoBike })
.where('id = :id', { id: cargoBike.id })
.execute();
equipmentTypeIds && await entityManager.getRepository(CargoBike)
.createQueryBuilder('cb')
.relation(CargoBike, 'equipmentTypeIds')
.of(cargoBike.id)
.addAndRemove(equipmentTypeIds, await this.equipmentTypeByCargoBikeId(cargoBike.id));
equipmentIds && await entityManager.getRepository(CargoBike)
.createQueryBuilder('cb')
.relation(CargoBike, 'equipmentIds')
@ -134,7 +142,7 @@ export class CargoBikeAPI extends DataSource {
async deleteCargoBike (id: number, userId: number) {
return await this.connection.transaction(async (entityManager: EntityManager) => {
if (await LockUtils.isLocked(entityManager, CargoBike, 'cb', id, userId)) {
throw new UserInputError('Attempting to soft delete locked resource');
throw new ResourceLockedError('CargoBike', 'Attempting to soft delete locked resource');
}
await ActionLogger.log(entityManager, CargoBike, 'bg', { id: id }, userId, Actions.SOFT_DELETE);
return await entityManager.getRepository(CargoBike)
@ -189,7 +197,7 @@ export class CargoBikeAPI extends DataSource {
delete bikeEvent.keepLock;
await this.connection.transaction(async (entityManager: EntityManager) => {
if (await LockUtils.isLocked(entityManager, BikeEvent, 'be', bikeEvent.id, userId)) {
throw new GraphQLError('BikeEvent locked by other user');
throw new ResourceLockedError('BikeEvents');
}
await ActionLogger.log(entityManager, BikeEvent, 'be', bikeEvent, userId);
await entityManager.getRepository(BikeEvent)
@ -267,7 +275,7 @@ export class CargoBikeAPI extends DataSource {
delete bikeEventType.keepLock;
await this.connection.transaction(async (entityManager: EntityManager) => {
if (await LockUtils.isLocked(entityManager, BikeEventType, 'bet', bikeEventType.id, userId)) {
throw new GraphQLError('BikeEventType locked by other user');
throw new ResourceLockedError('BikeEventType');
}
await ActionLogger.log(entityManager, BikeEventType, 'bet', bikeEventType, userId);
await entityManager.getRepository(BikeEventType)
@ -405,7 +413,7 @@ export class CargoBikeAPI extends DataSource {
delete equipment.keepLock;
await this.connection.transaction(async (entityManager: EntityManager) => {
if (await LockUtils.isLocked(entityManager, Equipment, 'equipment', equipment.id, userId)) {
return new GraphQLError('Equipment is locked by other user');
throw new ResourceLockedError('Equipment');
}
await ActionLogger.log(entityManager, Equipment, 'e', equipment, userId);
await entityManager.getRepository(Equipment)
@ -453,7 +461,7 @@ export class CargoBikeAPI extends DataSource {
delete equipmentType.keepLock;
await this.connection.transaction(async (entityManager: EntityManager) => {
if (await LockUtils.isLocked(entityManager, EquipmentType, 'et', equipmentType.id, userId)) {
throw new GraphQLError('EquipmentType is locked by other user');
throw new ResourceLockedError('EquipmentType');
}
await ActionLogger.log(entityManager, EquipmentType, 'et', equipmentType, userId);
await entityManager.getRepository(EquipmentType)

@ -22,8 +22,9 @@ import { Connection, EntityManager, getConnection } from 'typeorm';
import { ContactInformation } from '../../model/ContactInformation';
import { Person } from '../../model/Person';
import { ActionLogger, DBUtils, LockUtils } from './utils';
import { GraphQLError } from 'graphql';
import { LendingStation } from '../../model/LendingStation';
import { ResourceLockedError } from '../../errors/ResourceLockedError';
import { NotFoundError } from '../../errors/NotFoundError';
export class ContactInformationAPI extends DataSource {
connection : Connection
@ -68,7 +69,7 @@ export class ContactInformationAPI extends DataSource {
delete person.keepLock;
await this.connection.transaction(async (entityManger: EntityManager) => {
if (await LockUtils.isLocked(entityManger, Person, 'p', person.id, userId)) {
throw new GraphQLError('Person is locker by another user');
throw new ResourceLockedError('Person');
}
await ActionLogger.log(entityManger, Person, 'p', person, userId);
await entityManger.getRepository(Person)
@ -76,7 +77,11 @@ export class ContactInformationAPI extends DataSource {
.update()
.set({ ...person })
.where('id = :id', { id: person.id })
.execute().then(value => { if (value.affected !== 1) { throw new GraphQLError('Id not found'); } });
.execute().then(value => {
if (value.affected !== 1) {
throw new NotFoundError('Person', 'id', person.id);
}
});
});
!keepLock && await this.unlockPerson(person.id, userId);
return this.personById(person.id);
@ -146,7 +151,7 @@ export class ContactInformationAPI extends DataSource {
delete contactInformation.keepLock;
await this.connection.transaction(async (entityManager: EntityManager) => {
if (await LockUtils.isLocked(entityManager, ContactInformation, 'ci', contactInformation.id, userId)) {
throw new GraphQLError('ContactInformation is locked by other user');
throw new ResourceLockedError('ContactInformation');
}
await ActionLogger.log(entityManager, ContactInformation, 'ci', contactInformation, userId);
await entityManager.getRepository(ContactInformation)

@ -24,6 +24,8 @@ import { CargoBike } from '../../model/CargoBike';
import { LendingStation } from '../../model/LendingStation';
import { TimeFrame } from '../../model/TimeFrame';
import { ActionLogger, genDateRange, DBUtils, LockUtils } from './utils';
import { ResourceLockedError } from '../../errors/ResourceLockedError';
import { NotFoundError } from '../../errors/NotFoundError';
export class LendingStationAPI extends DataSource {
connection : Connection
@ -163,7 +165,7 @@ export class LendingStationAPI extends DataSource {
delete lendingStation.keepLock;
await this.connection.transaction(async (entityManager: EntityManager) => {
if (await LockUtils.isLocked(entityManager, LendingStation, 'ls', lendingStation.id, userId)) {
throw new UserInputError('Attempting to update locked resource');
throw new ResourceLockedError('LendingStation', 'Attempting to update locked resource');
}
await ActionLogger.log(entityManager, LendingStation, 'ls', lendingStation, userId);
await entityManager.getRepository(LendingStation)
@ -222,7 +224,7 @@ export class LendingStationAPI extends DataSource {
delete timeFrame.keepLock;
await this.connection.transaction(async (entityManager: EntityManager) => {
if (await LockUtils.isLocked(entityManager, TimeFrame, 'tf', timeFrame.id, userId)) {
throw new UserInputError('Attempting to update locked resource');
throw new ResourceLockedError('TimeFrame', 'Attempting to update locked resource');
}
genDateRange(timeFrame);
await ActionLogger.log(entityManager, TimeFrame, 'tf', timeFrame, userId);
@ -246,7 +248,7 @@ export class LendingStationAPI extends DataSource {
.set({ ...timeFrame })
.where('id = :id', { id: timeFrame.id })
.execute()
.then(value => { if (value.affected !== 1) { throw new UserInputError('ID not found'); } });
.then(value => { if (value.affected !== 1) { throw new NotFoundError('TimeFrame', 'id', timeFrame.id); } });
});
!keepLock && await this.unlockTimeFrame(timeFrame.id, userId);
return this.timeFrameById(timeFrame.id);

@ -26,6 +26,7 @@ import { EngagementType } from '../../model/EngagementType';
import { ActionLogger, DBUtils, genDateRange, LockUtils } from './utils';
import { UserInputError } from 'apollo-server-express';
import { GraphQLError } from 'graphql';
import { ResourceLockedError } from '../../errors/ResourceLockedError';
export class ParticipantAPI extends DataSource {
connection : Connection
@ -202,7 +203,7 @@ export class ParticipantAPI extends DataSource {
delete participant.keepLock;
await this.connection.transaction(async (entityManager: EntityManager) => {
if (await LockUtils.isLocked(entityManager, Participant, 'p', participant.id, userId)) {
throw new UserInputError('Attempting to update locked resource');
throw new ResourceLockedError('Participant', 'Attempting to update locked resource');
}
genDateRange(participant);
const workshops = participant.workshopIds;
@ -288,7 +289,7 @@ export class ParticipantAPI extends DataSource {
genDateRange(engagement);
await this.connection.transaction(async (entityManager: EntityManager) => {
if (await LockUtils.isLocked(entityManager, Engagement, 'e', engagement.id, userId)) {
throw new GraphQLError('Engagement is locked by other user');
throw new ResourceLockedError('Engagement');
}
await ActionLogger.log(entityManager, Engagement, 'e', engagement, userId);
// check for overlapping engagements
@ -356,7 +357,7 @@ export class ParticipantAPI extends DataSource {
delete engagementType.keepLock;
await this.connection.transaction(async (entityManager: EntityManager) => {
if (await LockUtils.isLocked(entityManager, EngagementType, 'et', engagementType.id, userId)) {
throw new GraphQLError('EngagementType is locked by other user');
throw new ResourceLockedError('EngagementType');
}
await ActionLogger.log(entityManager, EngagementType, 'et', engagementType, userId);
await entityManager.getRepository(EngagementType)

@ -25,7 +25,8 @@ import { UserInputError } from 'apollo-server-express';
import { CargoBike } from '../../model/CargoBike';
import { LendingStation } from '../../model/LendingStation';
import { ActionLogger, DBUtils, LockUtils } from './utils';
import { GraphQLError } from 'graphql';
import { ResourceLockedError } from '../../errors/ResourceLockedError';
import { NotFoundError } from '../../errors/NotFoundError';
export class ProviderAPI extends DataSource {
connection : Connection
@ -150,7 +151,7 @@ export class ProviderAPI extends DataSource {
delete provider.cargoBikeIds;
await this.connection.transaction(async (entityManager: EntityManager) => {
if (await LockUtils.isLocked(entityManager, Provider, 'p', provider.id, userId)) {
throw new GraphQLError('Provider is locked by another user');
throw new ResourceLockedError('Provider');
}
await ActionLogger.log(entityManager, Provider, 'p', provider, userId);
await entityManager.getRepository(Provider)
@ -158,7 +159,11 @@ export class ProviderAPI extends DataSource {
.update()
.set({ ...provider })
.where('id = :id', { id: provider.id })
.execute().then(value => { if (value.affected !== 1) { throw new GraphQLError('ID not found'); } });
.execute().then(value => {
if (value.affected !== 1) {
throw new NotFoundError('Provider', 'id', provider.id);
}
});
await entityManager.getRepository(Provider)
.createQueryBuilder('p')
.relation(Provider, 'cargoBikeIds')
@ -174,15 +179,17 @@ export class ProviderAPI extends DataSource {
}
async createOrganisation (organisation: any) {
let inserts: any = null;
let createdOrganisation: any = null;
await this.connection.transaction(async (entityManager: EntityManager) => {
inserts = await entityManager.getRepository(Organisation)
const result = await entityManager.getRepository(Organisation)
.createQueryBuilder('o')
.insert()
.values([organisation])
.execute();
createdOrganisation = await entityManager.getRepository(Organisation).findOne(result.identifiers[0].id);
});
return inserts.generatedMaps[0];
return createdOrganisation;
}
async lockOrganisation (id: number, userId: number) {
@ -198,7 +205,7 @@ export class ProviderAPI extends DataSource {
delete organisation.keepLock;
await this.connection.transaction(async (entityManager: EntityManager) => {
if (await LockUtils.isLocked(entityManager, Organisation, 'o', organisation.id, userId)) {
throw new GraphQLError('Organisation is locked by another user');
throw new ResourceLockedError('Organisation');
}
await ActionLogger.log(entityManager, Organisation, 'o', organisation, userId);
await entityManager.getRepository(Organisation)

@ -21,6 +21,8 @@ import { Connection, EntityManager, ObjectType } from 'typeorm';
import { Lockable } from '../../model/CargoBike';
import { ActionLog, Actions } from '../../model/ActionLog';
import { UserInputError } from 'apollo-server-express';
import { ResourceLockedError } from '../../errors/ResourceLockedError';
import { NotFoundError } from '../../errors/NotFoundError';
export function genDateRange (struct: any) {
if (!struct.dateRange || !struct.dateRange.from) {
@ -100,7 +102,7 @@ export class DBUtils {
static async deleteEntity (connection: Connection, target: ObjectType<Lockable>, alias: string, id: number, userId: number): Promise<Boolean> {
return await connection.transaction(async (entityManger: EntityManager) => {
if (await LockUtils.isLocked(entityManger, target, alias, id, userId)) {
throw new UserInputError('Attempting to delete locked resource');
throw new ResourceLockedError('Connection', 'Attempting to delete locked resource');
}
await ActionLogger.log(entityManger, target, alias, { id: id }, userId, Actions.DELETE);
return await entityManger.getRepository(target)
@ -158,7 +160,7 @@ export class LockUtils {
.select()
.where(alias + '.id = :id', { id: id })
.getOne().catch(() => {
throw new UserInputError('ID not found');
throw new NotFoundError(target.name, 'id', id);
});
}
@ -301,7 +303,7 @@ export class ActionLogger {
.where('id = :id', { id: updates.id })
.getRawOne().then(value => {
if (value === undefined) {
throw new UserInputError('Id not found');
throw new NotFoundError(target.name, 'id', updates.id);
}
return value;
}); // use getRawOne to also get ids of related entities

@ -22,9 +22,9 @@ import { Connection, EntityManager, getConnection } from 'typeorm';
import { WorkshopType } from '../../model/WorkshopType';
import { Workshop } from '../../model/Workshop';
import { ActionLogger, DBUtils, LockUtils } from './utils';
import { UserInputError } from 'apollo-server-express';
import { GraphQLError } from 'graphql';
import { Participant } from '../../model/Participant';
import { ResourceLockedError } from '../../errors/ResourceLockedError';
import { NotFoundError } from '../../errors/NotFoundError';
export class WorkshopAPI extends DataSource {
connection: Connection
@ -57,7 +57,7 @@ export class WorkshopAPI extends DataSource {
delete workshop.keepLock;
await this.connection.transaction(async (entityManger: EntityManager) => {
if (await LockUtils.isLocked(entityManger, Workshop, 'w', workshop.id, userId)) {
throw new UserInputError('Attempting to update locked resource');
throw new ResourceLockedError('Workshop', 'Attempting to update locked resource');
}
await ActionLogger.log(entityManger, Workshop, 'w', workshop, userId);
await entityManger.getRepository(Workshop)
@ -66,7 +66,11 @@ export class WorkshopAPI extends DataSource {
.set({ ...workshop })
.where('id = :id', { id: workshop.id })
.execute()
.then(value => { if (value.affected !== 1) { throw new GraphQLError('ID not found'); } });
.then(value => {
if (value.affected !== 1) {
throw new NotFoundError('Workshop', 'id', workshop.id);
}
});
});
!keepLock && await this.unlockWorkshop(workshop.id, userId);
return await this.workshopById(workshop.id);
@ -99,7 +103,7 @@ export class WorkshopAPI extends DataSource {
delete workshopType.keepLock;
await this.connection.transaction(async (entityManager: EntityManager) => {
if (await LockUtils.isLocked(entityManager, WorkshopType, 'wt', workshopType.id, userId)) {
throw new UserInputError('Attempting to update locked resource');
throw new ResourceLockedError('WorkshopType', 'Attempting to update locked resource');
}
await ActionLogger.log(entityManager, WorkshopType, 'wt', workshopType, userId);
await entityManager.getRepository(WorkshopType)
@ -108,7 +112,11 @@ export class WorkshopAPI extends DataSource {
.set({ ...workshopType })
.where('id = :id', { id: workshopType.id })
.execute()
.then(value => { if (value.affected !== 1) { throw new GraphQLError('ID not found'); } });
.then(value => {
if (value.affected !== 1) {
throw new NotFoundError('WorkshopType', 'id', workshopType.id);
}
});
});
!keepLock && await this.unlockWorkshopType(workshopType.id, userId);
return await this.workshopTypeById(workshopType.id);

@ -0,0 +1,7 @@
import { ApolloError } from 'apollo-server-express';
export class NotFoundError extends ApolloError {
constructor (type: string, identifierParam: string, identifierValue: any) {
super(`${type} with ${identifierParam} = '${identifierValue}' not found.`, 'ENTITY_NOT_FOUND');
}
}

@ -0,0 +1,11 @@
import { ApolloError } from 'apollo-server-express';
export class ResourceLockedError extends ApolloError {
constructor (resourceName: String, additionalContext?: string) {
if (additionalContext) {
super(`The Resource ${resourceName} is currently locked: ${additionalContext}`, 'LOCKED_ERROR');
} else {
super(`The Resource ${resourceName} is currently locked`, 'LOCKED_ERROR');
}
}
}

@ -839,7 +839,7 @@ export default gql`
address: AddressCreateInput!
name: String!
"registration number of association"
associationNo: String!
associationNo: String
"If Club, at what court registered"
registeredAt: String
contactInformationId: ID

@ -20,9 +20,15 @@ export const CREATE_CARGO_BIKE = gql`
dimensionsAndLoad: {
hasCoverBox: true
lockable:false
boxLength: 0.1
boxWidth: 0.2
boxHeight:0.3
boxLengthRange: {
min: 0,
}
boxWidthRange: {
min: 0.2
}
boxHeightRange: {
min: 0.3
}
maxWeightBox: 1.1
maxWeightLuggageRack: 1.2
maxWeightTotal: 1.3

Loading…
Cancel
Save