src/*: implemented update and action log on overwrites

pull/14/head
leonnicolas 4 years ago
parent b593465bc3
commit 1b9030c85e
No known key found for this signature in database
GPG Key ID: 088D0743E2B65C07

@ -1,14 +1,14 @@
const { src, dest, watch, series, task } = require('gulp') const { src, dest, watch, series, task } = require('gulp');
const ts = require('gulp-typescript') const ts = require('gulp-typescript');
const del = require('delete') const del = require('delete');
const eslint = require('gulp-eslint') const eslint = require('gulp-eslint');
const nodemon = require('gulp-nodemon') const nodemon = require('gulp-nodemon');
/** /**
* Clears the dist folder by deleting all files inside. * Clears the dist folder by deleting all files inside.
* @param cb * @param cb
*/ */
function clearDist (cb) { function clearDist (cb) {
del('dist/*', cb) del('dist/*', cb);
} }
/** /**
@ -16,11 +16,11 @@ function clearDist (cb) {
* @returns {*} * @returns {*}
*/ */
function compileTypescript () { function compileTypescript () {
const tsProject = ts.createProject('tsconfig.json') const tsProject = ts.createProject('tsconfig.json');
const tsResult = tsProject.src().pipe(tsProject()) const tsResult = tsProject.src().pipe(tsProject());
return tsResult return tsResult
// .pipe(minify()) // .pipe(minify())
.pipe(dest('dist')) .pipe(dest('dist'));
} }
/** /**
@ -29,7 +29,7 @@ function compileTypescript () {
*/ */
function moveRemaining () { function moveRemaining () {
return src(['src/**/*', '!src/**/*.ts']) return src(['src/**/*', '!src/**/*.ts'])
.pipe(dest('dist')) .pipe(dest('dist'));
} }
function runEslint () { function runEslint () {
@ -42,7 +42,7 @@ function runEslint () {
.pipe(eslint.format()) .pipe(eslint.format())
// To have the process exit with an error code (1) on // To have the process exit with an error code (1) on
// lint error, return the stream and pipe to failAfterError last. // lint error, return the stream and pipe to failAfterError last.
.pipe(eslint.failAfterError()) .pipe(eslint.failAfterError());
} }
task('eslint', () => { task('eslint', () => {
return src(['src/**/*.ts']) return src(['src/**/*.ts'])
@ -54,30 +54,35 @@ task('eslint', () => {
.pipe(eslint.format()) .pipe(eslint.format())
// To have the process exit with an error code (1) on // To have the process exit with an error code (1) on
// lint error, return the stream and pipe to failAfterError last. // lint error, return the stream and pipe to failAfterError last.
.pipe(eslint.failAfterError()) .pipe(eslint.failAfterError());
}) });
task('default', series(clearDist, compileTypescript, moveRemaining)) task('default', series(clearDist, compileTypescript, moveRemaining));
task('watch', () => { task('watch', () => {
runEslint() runEslint();
compileTypescript() compileTypescript();
watch('**/*.ts', runEslint) watch('**/*.ts', runEslint);
watch('**/*.ts', compileTypescript) watch('**/*.ts', compileTypescript);
// watch(['src/**/*', '!src/**/*.ts'], moveRemaining()); // watch(['src/**/*', '!src/**/*.ts'], moveRemaining());
nodemon({ nodemon({
script: 'dist/index.js', script: 'dist/index.js',
watch: ['dist/**/*.js'], watch: ['dist/**/*.js'],
ext: 'js' ext: 'js'
}) });
}) });
task('watchTs', () => {
compileTypescript();
watch('**/*.ts', compileTypescript);
});
task('watchnolint', () => { task('watchnolint', () => {
watch('**/*.ts', compileTypescript) watch('**/*.ts', compileTypescript);
// watch(['src/**/*', '!src/**/*.ts'], moveRemaining()); // watch(['src/**/*', '!src/**/*.ts'], moveRemaining());
nodemon({ nodemon({
script: 'dist/index.js', script: 'dist/index.js',
watch: ['dist/**/*.js'], watch: ['dist/**/*.js'],
ext: 'js' ext: 'js'
}) });
}) });

@ -7,7 +7,7 @@ import { Equipment } from '../../model/Equipment';
import { Engagement } from '../../model/Engagement'; import { Engagement } from '../../model/Engagement';
import { Provider } from '../../model/Provider'; import { Provider } from '../../model/Provider';
import { TimeFrame } from '../../model/TimeFrame'; import { TimeFrame } from '../../model/TimeFrame';
import { LockUtils } from './utils'; import { ActionLogger, LockUtils } from './utils';
import { EquipmentType } from '../../model/EquipmentType'; import { EquipmentType } from '../../model/EquipmentType';
import { BikeEventType } from '../../model/BikeEventType'; import { BikeEventType } from '../../model/BikeEventType';
@ -54,7 +54,7 @@ export class CargoBikeAPI extends DataSource {
async cargoBikesByProviderId (id: number) { async cargoBikesByProviderId (id: number) {
return await this.connection return await this.connection
.createQueryBuilder() .createQueryBuilder()
.relation(Provider, 'cargoBikes') .relation(Provider, 'cargoBikeIds')
.of(id) .of(id)
.loadMany(); .loadMany();
} }
@ -62,7 +62,7 @@ export class CargoBikeAPI extends DataSource {
async cargoBikeByTimeFrameId (id: number) { async cargoBikeByTimeFrameId (id: number) {
return await this.connection.getRepository(TimeFrame) return await this.connection.getRepository(TimeFrame)
.createQueryBuilder('timeframe') .createQueryBuilder('timeframe')
.relation(TimeFrame, 'cargoBike') .relation(TimeFrame, 'cargoBikeId')
.of(id) .of(id)
.loadOne(); .loadOne();
} }
@ -72,13 +72,6 @@ export class CargoBikeAPI extends DataSource {
* @param param0 cargoBike to be updated * @param param0 cargoBike to be updated
*/ */
async updateCargoBike (cargoBike: any, userId:number) { async updateCargoBike (cargoBike: any, userId:number) {
// TODO lock cargoBike can return error to save one sql query, this will be a complex sql query
if (!await this.checkId(CargoBike, 'cargobike', cargoBike.id)) {
return new GraphQLError('ID not found');
}
if (!await LockUtils.lockEntity(this.connection, CargoBike, 'cb', cargoBike.id, userId)) {
return new GraphQLError('Bike locked by other user');
}
const keepLock = cargoBike?.keepLock; const keepLock = cargoBike?.keepLock;
delete cargoBike.keepLock; delete cargoBike.keepLock;
delete cargoBike.lendingStationId; delete cargoBike.lendingStationId;
@ -88,6 +81,10 @@ export class CargoBikeAPI extends DataSource {
delete cargoBike.equipmentTypeIds; delete cargoBike.equipmentTypeIds;
} }
await this.connection.transaction(async (entityManager: EntityManager) => { 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');
}
await ActionLogger.log(entityManager, CargoBike, 'cb', cargoBike, userId);
await entityManager.getRepository(CargoBike) await entityManager.getRepository(CargoBike)
.createQueryBuilder('cargobike') .createQueryBuilder('cargobike')
.update() .update()
@ -138,6 +135,25 @@ export class CargoBikeAPI extends DataSource {
.execute()).generatedMaps[0]; .execute()).generatedMaps[0];
} }
async updateBikeEvent (bikeEvent: any, userId: number) {
const keepLock = bikeEvent.keepLock;
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');
}
await ActionLogger.log(entityManager, BikeEvent, 'be', bikeEvent, userId);
await entityManager.getRepository(BikeEvent)
.createQueryBuilder('be')
.update()
.set({ ...bikeEvent })
.where('id = :id', { id: bikeEvent.id })
.execute();
});
!keepLock && await LockUtils.unlockEntity(this.connection, BikeEvent, 'be', bikeEvent.id, userId);
return await this.bikeEventById(bikeEvent.id);
}
async cargoBikeByEventId (id: number) { async cargoBikeByEventId (id: number) {
return await this.connection.getRepository(BikeEvent) return await this.connection.getRepository(BikeEvent)
.createQueryBuilder('be') .createQueryBuilder('be')
@ -173,6 +189,33 @@ export class CargoBikeAPI extends DataSource {
.execute())?.generatedMaps[0]; .execute())?.generatedMaps[0];
} }
async lockBikeEventType (id: number, userId: number) {
return await LockUtils.lockEntity(this.connection, BikeEventType, 'bet', id, userId);
}
async unlockBikeEventType (id: number, userId: number) {
return await LockUtils.unlockEntity(this.connection, BikeEventType, 'bet', id, userId);
}
async updateBikeEventType (bikeEventType: any, userId: number) {
const keepLock = bikeEventType.keepLock;
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');
}
await ActionLogger.log(entityManager, BikeEventType, 'bet', bikeEventType, userId);
await entityManager.getRepository(BikeEventType)
.createQueryBuilder('bet')
.update()
.set({ ...bikeEventType })
.where('id = :id', { id: bikeEventType.id })
.execute();
});
!keepLock && await LockUtils.unlockEntity(this.connection, BikeEventType, 'bet', bikeEventType.id, userId);
return await this.bikeEventTypeById(bikeEventType.id);
}
async bikeEventTypes (offset: number, limit: number) { async bikeEventTypes (offset: number, limit: number) {
return await this.connection.getRepository(BikeEventType) return await this.connection.getRepository(BikeEventType)
.createQueryBuilder('bet') .createQueryBuilder('bet')
@ -191,7 +234,7 @@ export class CargoBikeAPI extends DataSource {
.getMany(); .getMany();
} }
async findBikeEventTypeById (id: number) { async bikeEventTypeById (id: number) {
return await this.connection.getRepository(BikeEventType) return await this.connection.getRepository(BikeEventType)
.createQueryBuilder('bet') .createQueryBuilder('bet')
.select() .select()
@ -219,11 +262,11 @@ export class CargoBikeAPI extends DataSource {
* return bikeEvent including CargoBike * return bikeEvent including CargoBike
* @param id of event * @param id of event
*/ */
async findBikeEventById (id: number) { async bikeEventById (id: number) {
return await this.connection.getRepository(BikeEvent) return await this.connection.getRepository(BikeEvent)
.createQueryBuilder('bikeEvent') .createQueryBuilder('bikeEvent')
.leftJoinAndSelect('bikeEvent.cargoBike', 'cargoBike') .select()
.where('bikeEvent.id = :id', { id: id }) .where('id = :id', { id: id })
.getOne(); .getOne();
} }
@ -276,22 +319,15 @@ export class CargoBikeAPI extends DataSource {
.values([equipment]) .values([equipment])
.returning('*') .returning('*')
.execute(); .execute();
if (equipment.cargoBikeId) {
await this.connection
.createQueryBuilder()
.relation(Equipment, 'cargoBike')
.of(equipment.id)
.set(equipment.cargoBikeId);
}
return this.equipmentById(inserts.identifiers[0].id); return this.equipmentById(inserts.identifiers[0].id);
} }
async cargoBikeByEquipmentId (id: number) { async cargoBikeByEquipmentId (id: number) {
return (await this.connection.getRepository(Equipment) return await this.connection.getRepository(Equipment)
.createQueryBuilder('equipment') .createQueryBuilder('equipment')
.leftJoinAndSelect('equipment.cargoBike', 'cargoBike') .relation(Equipment, 'cargoBikeId')
.where('equipment.id = :id', { id: id }) .of(id)
.getOne())?.cargoBike; .loadOne();
} }
async lockEquipment (id: number, userId: number) { async lockEquipment (id: number, userId: number) {
@ -308,33 +344,33 @@ export class CargoBikeAPI extends DataSource {
* @param param0 struct with equipment properites * @param param0 struct with equipment properites
*/ */
async updateEquipment (equipment: any, userId: number) { async updateEquipment (equipment: any, userId: number) {
// TODO let lock cargoBike can return error to save one sql query, this will be a complex sql query
if (!await this.checkId(Equipment, 'alias', equipment.id)) {
return new GraphQLError('ID not found in DB');
}
if (!await LockUtils.lockEntity(this.connection, Equipment, 'equipment', equipment.id, userId)) {
return new GraphQLError('Equipment locked by other user');
}
const keepLock = equipment.keepLock; const keepLock = equipment.keepLock;
delete equipment.keepLock; delete equipment.keepLock;
const cargoBikeId = equipment.cargoBikeId; // const cargoBikeId = equipment.cargoBikeId;
delete equipment.cargoBikeId; // delete equipment.cargoBikeId;
await this.connection.getRepository(Equipment) await this.connection.transaction(async (entityManager: EntityManager) => {
.createQueryBuilder('equipment') if (await LockUtils.isLocked(entityManager, Equipment, 'equipment', equipment.id, userId)) {
.update() return new GraphQLError('Equipment is locked by other user');
.set({ ...equipment }) }
.where('id = :id', { id: equipment.id }) await ActionLogger.log(entityManager, Equipment, 'e', equipment, userId);
.returning('*') await entityManager.getRepository(Equipment)
.execute(); .createQueryBuilder('equipment')
if (cargoBikeId || cargoBikeId === null) { .update()
await this.connection.getRepository(Equipment) .set({ ...equipment })
.createQueryBuilder() .where('id = :id', { id: equipment.id })
.relation(Equipment, 'cargoBike') .execute();
.of(equipment.id) /* if (cargoBikeId || cargoBikeId === null) {
.set(cargoBikeId); await this.connection.getRepository(Equipment)
!keepLock && LockUtils.unlockEntity(this.connection, Equipment, 'e', equipment.id, userId); .createQueryBuilder()
return this.equipmentById(equipment.id); .relation(Equipment, 'cargoBike')
.of(equipment.id)
.set(cargoBikeId);
}
*/
} }
);
!keepLock && await LockUtils.unlockEntity(this.connection, Equipment, 'e', equipment.id, userId);
return this.equipmentById(equipment.id); return this.equipmentById(equipment.id);
} }
@ -359,6 +395,32 @@ export class CargoBikeAPI extends DataSource {
return inserts.generatedMaps[0]; return inserts.generatedMaps[0];
} }
async lockEquipmentType (id: number, userId : number) {
return await LockUtils.lockEntity(this.connection, EquipmentType, 'et', id, userId);
}
async unlockEquipmentType (id: number, userId : number) {
return await LockUtils.unlockEntity(this.connection, EquipmentType, 'et', id, userId);
}
async updateEquipmentType (equipmentType: any, userId: number) {
const keepLock = equipmentType.keepLock;
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');
}
await entityManager.getRepository(EquipmentType)
.createQueryBuilder('et')
.update()
.set({ ...equipmentType })
.where('id = :id', { id: equipmentType.id })
.execute();
});
!keepLock && await this.unlockEquipmentType(equipmentType.id, userId);
return await this.equipmentTypeById(equipmentType.id);
}
async equipmentTypeById (id: number) { async equipmentTypeById (id: number) {
return await this.connection.getRepository(EquipmentType) return await this.connection.getRepository(EquipmentType)
.createQueryBuilder('equipmentType') .createQueryBuilder('equipmentType')

@ -1,7 +1,10 @@
import { DataSource } from 'apollo-datasource'; import { DataSource } from 'apollo-datasource';
import { Connection, getConnection } from 'typeorm'; import { Connection, EntityManager, getConnection } from 'typeorm';
import { ContactInformation } from '../../model/ContactInformation'; import { ContactInformation } from '../../model/ContactInformation';
import { Person } from '../../model/Person'; import { Person } from '../../model/Person';
import { ActionLogger, LockUtils } from './utils';
import { GraphQLError } from 'graphql';
import { LendingStation } from '../../model/LendingStation';
export class ContactInformationAPI extends DataSource { export class ContactInformationAPI extends DataSource {
connection : Connection connection : Connection
@ -46,6 +49,33 @@ export class ContactInformationAPI extends DataSource {
return inserts.generatedMaps[0]; return inserts.generatedMaps[0];
} }
async lockPerson (id: number, userId: number) {
return await LockUtils.lockEntity(this.connection, Person, 'p', id, userId);
}
async unlockPerson (id: number, userId: number) {
return await LockUtils.unlockEntity(this.connection, Person, 'p', id, userId);
}
async updatePerson (person: any, userId: number) {
const keepLock = person.keepLock;
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');
}
await ActionLogger.log(entityManger, Person, 'p', person, userId);
await entityManger.getRepository(Person)
.createQueryBuilder('p')
.update()
.set({ ...person })
.where('id = :id', { id: person.id })
.execute().then(value => { if (value.affected !== 1) { throw new GraphQLError('Id not found'); } });
});
!keepLock && await this.unlockPerson(person.id, userId);
return this.personById(person.id);
}
async persons (offset: number, limit: number) { async persons (offset: number, limit: number) {
return await this.connection.getRepository(Person) return await this.connection.getRepository(Person)
.createQueryBuilder('person') .createQueryBuilder('person')
@ -71,6 +101,22 @@ export class ContactInformationAPI extends DataSource {
.loadOne(); .loadOne();
} }
async contactInternByLendingStationId (id: number) {
return this.connection.getRepository(LendingStation)
.createQueryBuilder('ls')
.relation(LendingStation, 'contactInformationInternId')
.of(id)
.loadOne();
}
async contactExternByLendingStationId (id: number) {
return this.connection.getRepository(LendingStation)
.createQueryBuilder('ls')
.relation(LendingStation, 'contactInformationExternId')
.of(id)
.loadOne();
}
async createContactInformation (contactInformation: any) { async createContactInformation (contactInformation: any) {
const inserts = await this.connection.getRepository(ContactInformation) const inserts = await this.connection.getRepository(ContactInformation)
.createQueryBuilder('contactInformation') .createQueryBuilder('contactInformation')
@ -82,6 +128,33 @@ export class ContactInformationAPI extends DataSource {
return inserts.generatedMaps[0]; return inserts.generatedMaps[0];
} }
async lockContactInformation (id: number, userId: number) {
return await LockUtils.lockEntity(this.connection, ContactInformation, 'ci', id, userId);
}
async unlockContactInformation (id: number, userId: number) {
return await LockUtils.unlockEntity(this.connection, ContactInformation, 'ci', id, userId);
}
async updateContactInformation (contactInformation: any, userId: number) {
const keepLock = contactInformation.keepLock;
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');
}
await ActionLogger.log(entityManager, ContactInformation, 'ci', contactInformation, userId);
await entityManager.getRepository(ContactInformation)
.createQueryBuilder('ci')
.update()
.set({ ...contactInformation })
.where('id = :id', { id: contactInformation.id })
.execute();
});
!keepLock && await LockUtils.unlockEntity(this.connection, ContactInformation, 'ci', contactInformation.id, userId);
return await this.contactInformationById(contactInformation.id);
}
async contactInformationByPersonId (id: number) { async contactInformationByPersonId (id: number) {
const res = await this.connection.getRepository(ContactInformation) const res = await this.connection.getRepository(ContactInformation)
.createQueryBuilder('ci') .createQueryBuilder('ci')

@ -5,7 +5,7 @@ import { Connection, EntityManager, getConnection, QueryFailedError } from 'type
import { CargoBike } from '../../model/CargoBike'; import { CargoBike } from '../../model/CargoBike';
import { LendingStation } from '../../model/LendingStation'; import { LendingStation } from '../../model/LendingStation';
import { TimeFrame } from '../../model/TimeFrame'; import { TimeFrame } from '../../model/TimeFrame';
import { LockUtils } from './utils'; import { ActionLogger, genDateRange, LockUtils } from './utils';
export class LendingStationAPI extends DataSource { export class LendingStationAPI extends DataSource {
connection : Connection connection : Connection
@ -14,12 +14,11 @@ export class LendingStationAPI extends DataSource {
this.connection = getConnection(); this.connection = getConnection();
} }
async lendingStationById ({ id }: { id: any }) { async lendingStationById (id:number) {
return await this.connection.manager return await this.connection.getRepository(LendingStation)
.createQueryBuilder() .createQueryBuilder('ls')
.select('lendingStation') .select()
.from(LendingStation, 'lendingStation') .where('id = :id', { id: id })
.where('lendingStation.id = :id', { id: id })
.getOne(); .getOne();
} }
@ -102,10 +101,6 @@ export class LendingStationAPI extends DataSource {
return LockUtils.unlockEntity(this.connection, LendingStation, 'ls', id, uId); return LockUtils.unlockEntity(this.connection, LendingStation, 'ls', id, uId);
} }
async lockTimeFrame (id: number, userId: number) {
return await LockUtils.lockEntity(this.connection, TimeFrame, 'tf', id, userId);
}
/** /**
* Counts all timeframes with one lendingStation that overlap with today's date * Counts all timeframes with one lendingStation that overlap with today's date
* @param id of lendingStation * @param id of lendingStation
@ -140,40 +135,38 @@ export class LendingStationAPI extends DataSource {
*/ */
async createLendingStation (lendingStation: any) { async createLendingStation (lendingStation: any) {
let inserts: any; let inserts: any;
await this.connection.transaction(async entiyManager => { await this.connection.transaction(async entityManager => {
inserts = await entiyManager.createQueryBuilder(LendingStation, 'lendingstation') inserts = await entityManager.createQueryBuilder(LendingStation, 'lendingstation')
.insert() .insert()
.values([lendingStation]) .values([lendingStation])
.returning('*') .returning('*')
.execute(); .execute();
}); });
// when using the return values, the simple array has a different format and must treated in another way, so this is the more expansive solution
const newLendingStaion = inserts.generatedMaps[0]; return await this.lendingStationById(inserts.generatedMaps[0].id);
newLendingStaion.id = inserts.identifiers[0].id;
return newLendingStaion;
} }
/** /**
* updates lendingStation and return updated lendingStation * updates lendingStation and return updated lendingStation
* @param param0 lendingStation to be updated * @param param0 lendingStation to be updated
*/ */
async updateLendingStation ({ lendingStation }:{ lendingStation: any }) { async updateLendingStation (lendingStation: any, userId: number) {
const oldLendingStation = await this.connection.manager.createQueryBuilder() const keepLock = lendingStation.keepLock;
.select('lendingStation') delete lendingStation.keepLock;
.from(LendingStation, 'lendingStation') await this.connection.transaction(async (entityManager: EntityManager) => {
.where('lendingStation.id = :id', { id: lendingStation.id }) if (await LockUtils.isLocked(entityManager, LendingStation, 'ls', lendingStation.id, userId)) {
.getOne(); throw new GraphQLError('LendingStation is locked by another user');
if (oldLendingStation) { }
await this.connection await ActionLogger.log(entityManager, LendingStation, 'ls', lendingStation, userId);
.createQueryBuilder() await entityManager.getRepository(LendingStation)
.update(LendingStation) .createQueryBuilder('ls')
.update()
.set({ ...lendingStation }) .set({ ...lendingStation })
.where('id = :id', { id: lendingStation.id }) .where('id = :id', { id: lendingStation.id })
.execute(); .execute();
return this.lendingStationById({ id: lendingStation.id }); });
} else { !keepLock && await LockUtils.unlockEntity(this.connection, LendingStation, 'ls', lendingStation.id, userId);
return new GraphQLError('ID not in database'); return await this.lendingStationById(lendingStation.id);
}
} }
async createTimeFrame (timeFrame: any) { async createTimeFrame (timeFrame: any) {
@ -202,17 +195,6 @@ export class LendingStationAPI extends DataSource {
.returning('*') .returning('*')
.values([timeFrame]) .values([timeFrame])
.execute(); .execute();
/* await entityManager.getRepository(TimeFrame)
.createQueryBuilder()
.relation(TimeFrame, 'cargoBike')
.of(inserts.identifiers[0].id)
.set(timeFrame.cargoBikeId);
await entityManager.getRepository(TimeFrame)
.createQueryBuilder()
.relation(TimeFrame, 'lendingStation')
.of(inserts.identifiers[0].id)
.set(timeFrame.lendingStationId);
*/
}); });
} catch (e) { } catch (e) {
if (e instanceof UserInputError) { if (e instanceof UserInputError) {
@ -226,55 +208,46 @@ export class LendingStationAPI extends DataSource {
return inserts.generatedMaps[0]; return inserts.generatedMaps[0];
} }
/* async updateTimeFrame (timeFrame: any) { async lockTimeFrame (id: number, userId: number) {
try { return await LockUtils.lockEntity(this.connection, TimeFrame, 'tf', id, userId);
await this.connection.transaction(async (entityManager: EntityManager) => { }
if (timeFrame.to === undefined) {
timeFrame.to = ''; async unlockTimeFrame (id: number, userId: number) {
} return await LockUtils.unlockEntity(this.connection, TimeFrame, 'tf', id, userId);
timeFrame.dateRange = '[' + timeFrame.from + ',' + timeFrame.to + ')'; }
// checking for overlapping time frames
const overlapping = await entityManager.getRepository(TimeFrame) async updateTimeFrame (timeFrame: any, userId: number) {
.createQueryBuilder('timeframe') const keepLock = timeFrame.keepLock;
.update() delete timeFrame.keepLock;
values([]) await this.connection.transaction(async (entityManager: EntityManager) => {
.select([ if (await LockUtils.isLocked(entityManager, TimeFrame, 'tf', timeFrame.id, userId)) {
'timeframe.id' throw new UserInputError('Attempting to update locked resource');
])
.where('timeframe."cargoBikeId" = :id', { id: timeFrame.cargoBikeId })
.andWhere('timeframe."dateRange" && :tr', { tr: timeFrame.dateRange })
.getMany();
console.log(overlapping);
if (overlapping.length !== 0) {
throw new UserInputError('TimeFrames with ids: ' + overlapping.map((e) => { return e.id + ', '; }) + 'are overlapping');
}
inserts = await entityManager.getRepository(TimeFrame)
.createQueryBuilder('timeframe')
.insert()
.returning('*')
.values([timeFrame])
.execute();
await entityManager.getRepository(TimeFrame)
.createQueryBuilder()
.relation(TimeFrame, 'cargoBike')
.of(inserts.identifiers[0].id)
.set(timeFrame.cargoBikeId);
await entityManager.getRepository(TimeFrame)
.createQueryBuilder()
.relation(TimeFrame, 'lendingStation')
.of(inserts.identifiers[0].id)
.set(timeFrame.lendingStationId);
});
} catch (e) {
console.log(e);
if (e instanceof UserInputError) {
return e;
} else if (e instanceof QueryFailedError) {
return e;
} }
return new ApolloError('Transaction could not be completed'); genDateRange(timeFrame);
} await ActionLogger.log(entityManager, TimeFrame, 'tf', timeFrame, userId);
inserts.generatedMaps[0].id = inserts.identifiers[0].id;
return inserts.generatedMaps[0]; await entityManager.getRepository(TimeFrame)
} */ .createQueryBuilder('timeframe')
.select([
'timeframe.id'
])
.where('timeframe."cargoBikeId" = :id', { id: timeFrame.cargoBikeId })
.andWhere('timeframe."dateRange" && :tr', { tr: timeFrame.dateRange })
.andWhere('timeFrame.id != :tid', { tid: timeFrame.id })
.getMany().then(overlapping => {
if (overlapping.length !== 0) {
throw new UserInputError('TimeFrames with ids: ' + overlapping.map((e) => { return e.id + ', '; }) + 'are overlapping');
}
});
await entityManager.getRepository(TimeFrame)
.createQueryBuilder('tf')
.update()
.set({ ...timeFrame })
.where('id = :id', { id: timeFrame.id })
.execute()
.then(value => { if (value.affected !== 1) { throw new GraphQLError('ID not found'); } });
});
!keepLock && await this.unlockTimeFrame(timeFrame.id, userId);
return this.timeFrameById(timeFrame.id);
}
} }

@ -4,8 +4,9 @@ import { ContactInformation } from '../../model/ContactInformation';
import { Engagement } from '../../model/Engagement'; import { Engagement } from '../../model/Engagement';
import { Participant } from '../../model/Participant'; import { Participant } from '../../model/Participant';
import { EngagementType } from '../../model/EngagementType'; import { EngagementType } from '../../model/EngagementType';
import { genDateRange } from './utils'; import { ActionLogger, genDateRange, LockUtils } from './utils';
import { UserInputError } from 'apollo-server'; import { UserInputError } from 'apollo-server';
import { GraphQLError } from 'graphql';
export class ParticipantAPI extends DataSource { export class ParticipantAPI extends DataSource {
connection : Connection connection : Connection
@ -14,11 +15,11 @@ export class ParticipantAPI extends DataSource {
this.connection = getConnection(); this.connection = getConnection();
} }
async getParticipantById (id: number) { async participantById (id: number) {
return await this.connection.getRepository(Participant) return await this.connection.getRepository(Participant)
.createQueryBuilder('participant') .createQueryBuilder('participant')
.select() .select()
.where('participant.id = :id', { id: id }) .where('id = :id', { id: id })
.getOne(); .getOne();
} }
@ -146,7 +147,34 @@ export class ParticipantAPI extends DataSource {
.returning('*') .returning('*')
.execute(); .execute();
}); });
return this.getParticipantById(inserts?.identifiers[0].id); return this.participantById(inserts?.identifiers[0].id);
}
async lockParticipant (id: number, userId: number) {
return await LockUtils.lockEntity(this.connection, Participant, 'p', id, userId);
}
async unlockParticipant (id: number, userId: number) {
return await LockUtils.unlockEntity(this.connection, Participant, 'p', id, userId);
}
async updateParticipant (participant: any, userId: number) {
const keepLock = participant.keepLock;
delete participant.keepLock;
await this.connection.transaction(async (entityManager: EntityManager) => {
if (await LockUtils.isLocked(entityManager, Participant, 'p', participant.id, userId)) {
throw new GraphQLError('Participant is locked by another user');
}
await ActionLogger.log(entityManager, Participant, 'p', participant, userId);
await entityManager.getRepository(Participant)
.createQueryBuilder('p')
.update()
.set({ ...participant })
.where('id = :id', { id: participant.id })
.execute().then(value => { if (value.affected !== 1) { throw new GraphQLError('ID not found'); } });
});
!keepLock && await this.unlockParticipant(participant.id, userId);
return await this.participantById(participant.id);
} }
async createEngagement (engagement: any) { async createEngagement (engagement: any) {
@ -174,6 +202,46 @@ export class ParticipantAPI extends DataSource {
return this.engagementById(inserts?.identifiers[0].id); return this.engagementById(inserts?.identifiers[0].id);
} }
async lockEngagement (id: number, userId: number) {
return await LockUtils.lockEntity(this.connection, Engagement, 'e', id, userId);
}
async unlockEngagement (id: number, userId: number) {
return await LockUtils.unlockEntity(this.connection, Engagement, 'e', id, userId);
}
async updateEngagement (engagement: any, userId: number) {
const keepLock = engagement.keepLock;
delete engagement.keepLock;
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');
}
await ActionLogger.log(entityManager, Engagement, 'e', engagement, userId);
// check for overlapping engagements
const overlapping = await entityManager.getRepository(Engagement)
.createQueryBuilder('e')
.select()
.where('e."cargoBikeId" = :id', { id: engagement.cargoBikeId })
.andWhere('e."dateRange" && :dr', { dr: engagement.dateRange })
.andWhere('e."engagementTypeId" = :etId', { etId: engagement.engagementTypeId })
.andWhere('e.id != :eid', { eid: engagement.id })
.getMany();
if (overlapping.length > 0) {
throw new UserInputError('Engagements with ids: ' + overlapping.map((e) => { return e.id + ', '; }) + 'are overlapping');
}
await entityManager.getRepository(Engagement)
.createQueryBuilder('engagement')
.update()
.set({ ...engagement })
.where('id = :id', { id: engagement.id })
.execute();
});
!keepLock && await LockUtils.unlockEntity(this.connection, Engagement, 'e', engagement.id, userId);
return await this.engagementById(engagement.id);
}
async createEngagementType (engagementType: any) { async createEngagementType (engagementType: any) {
const inserts = await this.connection.getRepository(EngagementType) const inserts = await this.connection.getRepository(EngagementType)
.createQueryBuilder('et') .createQueryBuilder('et')
@ -184,4 +252,31 @@ export class ParticipantAPI extends DataSource {
inserts.generatedMaps[0].id = inserts.identifiers[0].id; inserts.generatedMaps[0].id = inserts.identifiers[0].id;
return inserts.generatedMaps[0]; return inserts.generatedMaps[0];
} }
async lockEngagementType (id:number, userId: number) {
return await LockUtils.lockEntity(this.connection, EngagementType, 'e', id, userId);
}
async unlockEngagementType (id:number, userId: number) {
return await LockUtils.unlockEntity(this.connection, EngagementType, 'e', id, userId);
}
async updateEngagementType (engagementType: any, userId: number) {
const keepLock = engagementType.keepLock;
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');
}
await ActionLogger.log(entityManager, EngagementType, 'et', engagementType, userId);
await entityManager.getRepository(EngagementType)
.createQueryBuilder('et')
.update()
.set({ ...engagementType })
.where('id = :id', { id: engagementType.id })
.execute();
});
!keepLock && await LockUtils.unlockEntity(this.connection, EngagementType, 'et', engagementType.id, userId);
return await this.engagementTypeById(engagementType.id);
}
} }

@ -4,6 +4,9 @@ import { Provider } from '../../model/Provider';
import { Organisation } from '../../model/Organisation'; import { Organisation } from '../../model/Organisation';
import { UserInputError } from 'apollo-server'; import { UserInputError } from 'apollo-server';
import { CargoBike } from '../../model/CargoBike'; import { CargoBike } from '../../model/CargoBike';
import { LendingStation } from '../../model/LendingStation';
import { ActionLogger, LockUtils } from './utils';
import { GraphQLError } from 'graphql';
export class ProviderAPI extends DataSource { export class ProviderAPI extends DataSource {
connection : Connection connection : Connection
@ -13,19 +16,19 @@ export class ProviderAPI extends DataSource {
} }
async providerById (id: number) { async providerById (id: number) {
await this.connection.getRepository(Provider) return await this.connection.getRepository(Provider)
.createQueryBuilder('provider') .createQueryBuilder('provider')
.select() .select()
.where('provider.id = :id', { id: id }) .where('id = :id', { id: id })
.getOne().catch(() => { return null; }); .getOne();
} }
async provider (offset: number, limit: number) { async provider (offset: number, limit: number) {
return await this.connection.getRepository(Provider) return await this.connection.getRepository(Provider)
.createQueryBuilder('provider') .createQueryBuilder('provider')
.select() .select()
.offset(offset) .skip(offset)
.limit(limit) .take(limit)
.getMany(); .getMany();
} }
@ -70,6 +73,22 @@ export class ProviderAPI extends DataSource {
.getOne(); .getOne();
} }
async organisationByLendingStationId (id: number) {
return await this.connection.getRepository(LendingStation)
.createQueryBuilder('ls')
.relation(LendingStation, 'organisationId')
.of(id)
.loadOne();
}
async lendingStationByOrganisationId (id: number) {
return await this.connection.getRepository(Organisation)
.createQueryBuilder('o')
.relation(Organisation, 'lendingStations')
.of(id)
.loadMany();
}
async contactInformationByOrganisationId (id: number) { async contactInformationByOrganisationId (id: number) {
return await this.connection.getRepository(Organisation) return await this.connection.getRepository(Organisation)
.createQueryBuilder('o') .createQueryBuilder('o')
@ -107,6 +126,40 @@ export class ProviderAPI extends DataSource {
return ret; return ret;
} }
async lockProvider (id: number, userId: number) {
return await LockUtils.lockEntity(this.connection, Provider, 'p', id, userId);
}
async unlockProvider (id: number, userId: number) {
return await LockUtils.unlockEntity(this.connection, Provider, 'p', id, userId);
}
async updateProvider (provider: any, userId: number) {
const keepLock = provider.keepLock;
delete provider.keepLock;
const cargoBikes = provider.cargoBikeIds;
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');
}
await ActionLogger.log(entityManager, Provider, 'p', provider, userId);
await entityManager.getRepository(Provider)
.createQueryBuilder('p')
.update()
.set({ ...provider })
.where('id = :id', { id: provider.id })
.execute().then(value => { if (value.affected !== 1) { throw new GraphQLError('ID not found'); } });
await entityManager.getRepository(Provider)
.createQueryBuilder('p')
.relation(Provider, 'cargoBikeIds')
.of(provider.id)
.add(cargoBikes);
});
!keepLock && await this.unlockProvider(provider.id, userId);
return await this.providerById(provider.id);
}
async createOrganisation (organisation: any) { async createOrganisation (organisation: any) {
let inserts: any = null; let inserts: any = null;
await this.connection.transaction(async (entityManager: EntityManager) => { await this.connection.transaction(async (entityManager: EntityManager) => {
@ -115,11 +168,34 @@ export class ProviderAPI extends DataSource {
.insert() .insert()
.values([organisation]) .values([organisation])
.execute(); .execute();
await entityManager.getRepository(Organisation).createQueryBuilder()
.relation(Organisation, 'providerId')
.of(inserts.identifiers[0].id)
.set(organisation.providerId);
}); });
return inserts.generatedMaps[0]; return inserts.generatedMaps[0];
} }
async lockOrganisation (id: number, userId: number) {
return await LockUtils.lockEntity(this.connection, Organisation, 'o', id, userId);
}
async unlockOrganisation (id: number, userId: number) {
return await LockUtils.unlockEntity(this.connection, Organisation, 'o', id, userId);
}
async updateOrganisation (organisation: any, userId: number) {
const keepLock = organisation.keepLock;
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');
}
await ActionLogger.log(entityManager, Organisation, 'o', organisation, userId);
await entityManager.getRepository(Organisation)
.createQueryBuilder('o')
.update()
.set({ ...organisation })
.where('id = :id', { id: organisation.id })
.execute();
});
!keepLock && await LockUtils.unlockEntity(this.connection, Organisation, 'o', organisation.id, userId);
return this.organisationById(organisation.id);
}
} }

@ -1,11 +1,9 @@
import { Connection, ObjectType } from 'typeorm'; import { Connection, EntityManager, ObjectType } from 'typeorm';
import { CargoBike, Lockable } from '../../model/CargoBike'; import { Lockable } from '../../model/CargoBike';
import { GraphQLError } from 'graphql'; import { GraphQLError } from 'graphql';
import { ActionLog } from '../../model/ActionLog';
export function genDateRange (struct: any) { export function genDateRange (struct: any) {
if (struct.to === undefined) {
struct.to = '';
}
if (struct.to === undefined) { if (struct.to === undefined) {
struct.to = ''; struct.to = '';
} }
@ -13,6 +11,9 @@ export function genDateRange (struct: any) {
if (struct.from === undefined) { if (struct.from === undefined) {
delete struct.dateRange; delete struct.dateRange;
} }
// delete these keys, so the struct can be used to update the engagement entity
delete struct.from;
delete struct.to;
} }
/** /**
@ -115,8 +116,8 @@ export class LockUtils {
* @param req * @param req
* @param dataSources * @param dataSources
*/ */
static async isLocked (connection: Connection, target: ObjectType<Lockable>, alias: string, id: number, userId: number) { static async isLocked (connection: EntityManager, target: ObjectType<Lockable>, alias: string, id: number, userId: number) {
const lock = await connection.getRepository(CargoBike) const lock = await connection.getRepository(target)
.createQueryBuilder(alias) .createQueryBuilder(alias)
.select([ .select([
alias + '.lockedUntil', alias + '.lockedUntil',
@ -152,3 +153,61 @@ export class LockUtils {
return result === 1; return result === 1;
} }
} }
export class ActionLogger {
private static buildSelect (updates: any, alias: string) : string[] {
// this hacky shit makes it possible to select subfields like the address or insurance data. Only one layer at the moment
const ret :string[] = [];
Object.keys(updates).forEach(value => {
if (typeof updates[value] === 'object' && !Array.isArray(updates[value])) {
Object.keys(updates[value]).forEach(subValue => {
ret.push(alias + '."' + value + subValue[0].toUpperCase() + subValue.substr(1).toLowerCase() + '"');
});
} else {
ret.push(alias + '."' + value + '"');
}
});
return ret;
}
static async log (em: EntityManager, target: ObjectType<any>, alias: string, updates: any, userId: number) {
const oldValues = await em.getRepository(target).createQueryBuilder(alias)
.select(this.buildSelect(updates, alias))
.where('id = :id', { id: updates.id })
.getRawOne().then(value => {
if (value === undefined) {
throw new GraphQLError('Id not found');
}
return value;
}); // use getRawOne to also get ids of related entities
Object.keys(oldValues).forEach(value => {
if (value.match(alias + '_')) {
oldValues[value.replace(alias + '_', '')] = oldValues[value];
delete oldValues[value];
}
});
// TODO: check if new values are different from old note: the commented section will probably fail for nested objects.
/*
const newValues = { ...updates }; // copy updates to mimic call by value
Object.keys(updates).forEach((key, i) => {
// eslint-disable-next-line eqeqeq
if (newValues[key] == oldValues[key]) {
delete newValues[key];
delete oldValues[key];
}
});
*/
const logEntry : ActionLog = {
userId: userId,
entity: target.name,
entriesOld: JSON.stringify(oldValues),
entriesNew: JSON.stringify(updates)
};
await em.getRepository(ActionLog)
.createQueryBuilder('al')
.insert()
.values([logEntry])
.execute();
}
}

@ -1,7 +1,10 @@
import { DataSource } from 'apollo-datasource'; import { DataSource } from 'apollo-datasource';
import { Connection, getConnection } from 'typeorm'; import { Connection, EntityManager, getConnection } from 'typeorm';
import { WorkshopType } from '../../model/WorkshopType'; import { WorkshopType } from '../../model/WorkshopType';
import { Workshop } from '../../model/Workshop'; import { Workshop } from '../../model/Workshop';
import { ActionLogger, LockUtils } from './utils';
import { UserInputError } from 'apollo-server-express';
import { GraphQLError } from 'graphql';
export class WorkshopAPI extends DataSource { export class WorkshopAPI extends DataSource {
connection: Connection connection: Connection
@ -21,6 +24,34 @@ export class WorkshopAPI extends DataSource {
return inserts.generatedMaps[0]; return inserts.generatedMaps[0];
} }
async lockWorkshop (id: number, userId: number) {
return await LockUtils.lockEntity(this.connection, Workshop, 'w', id, userId);
}
async unlockWorkshop (id: number, userId: number) {
return await LockUtils.unlockEntity(this.connection, Workshop, 'w', id, userId);
}
async updateWorkshop (workshop: any, userId: number) {
const keepLock = workshop.keepLock;
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');
}
await ActionLogger.log(entityManger, Workshop, 'w', workshop, userId);
await entityManger.getRepository(Workshop)
.createQueryBuilder('w')
.update()
.set({ ...workshop })
.where('id = :id', { id: workshop.id })
.execute()
.then(value => { if (value.affected !== 1) { throw new GraphQLError('ID not found'); } });
});
!keepLock && await this.unlockWorkshop(workshop.id, userId);
return await this.workshopById(workshop.id);
}
async createWorkshopType (workshopType: any) { async createWorkshopType (workshopType: any) {
const inserts = await this.connection.getRepository(WorkshopType) const inserts = await this.connection.getRepository(WorkshopType)
.createQueryBuilder('wt') .createQueryBuilder('wt')
@ -31,6 +62,34 @@ export class WorkshopAPI extends DataSource {
return inserts.generatedMaps[0]; return inserts.generatedMaps[0];
} }
async lockWorkshopType (id: number, userId: number) {
return await LockUtils.lockEntity(this.connection, WorkshopType, 'wt', id, userId);
}
async unlockWorkshopType (id: number, userId: number) {
return await LockUtils.unlockEntity(this.connection, WorkshopType, 'wt', id, userId);
}
async updateWorkshopType (workshopType : any, userId: number) {
const keepLock = workshopType.keepLock;
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');
}
await ActionLogger.log(entityManager, WorkshopType, 'wt', workshopType, userId);
await entityManager.getRepository(WorkshopType)
.createQueryBuilder('wt')
.update()
.set({ ...workshopType })
.where('id = :id', { id: workshopType.id })
.execute()
.then(value => { if (value.affected !== 1) { throw new GraphQLError('ID not found'); } });
});
!keepLock && await this.unlockWorkshopType(workshopType.id, userId);
return await this.workshopTypeById(workshopType.id);
}
async workshopTypeById (id: number) { async workshopTypeById (id: number) {
return await this.connection.getRepository(WorkshopType) return await this.connection.getRepository(WorkshopType)
.createQueryBuilder('wt') .createQueryBuilder('wt')

@ -33,6 +33,7 @@ import { EquipmentType } from './model/EquipmentType';
import { BikeEventType } from './model/BikeEventType'; import { BikeEventType } from './model/BikeEventType';
import { WorkshopAPI } from './datasources/db/workshopAPI'; import { WorkshopAPI } from './datasources/db/workshopAPI';
import workshopResolvers from './resolvers/workshopResolvers'; import workshopResolvers from './resolvers/workshopResolvers';
import { ActionLog } from './model/ActionLog';
require('dotenv').config(); require('dotenv').config();
@ -84,7 +85,8 @@ createConnection({
EngagementType, EngagementType,
Workshop, Workshop,
Person, Person,
WorkshopType WorkshopType,
ActionLog
], ],
synchronize: true, synchronize: true,
logging: false logging: false

@ -0,0 +1,26 @@
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class ActionLog {
@PrimaryGeneratedColumn()
id?: number;
@CreateDateColumn()
date?: Date;
@Column()
userId: number;
@Column()
entity: string;
@Column({
type: 'text'
})
entriesOld: string;
@Column({
type: 'text'
})
entriesNew: string;
}

@ -154,7 +154,7 @@ export class CargoBike implements Lockable {
@Column() @Column()
name: string; name: string;
@OneToMany(type => Equipment, equipment => equipment.cargoBike, { @OneToMany(type => Equipment, equipment => equipment.cargoBikeId, {
nullable: true, nullable: true,
eager: true eager: true
}) })

@ -39,30 +39,6 @@ export class Engagement implements Lockable {
}) })
dateRange: Date[]; dateRange: Date[];
@Column({
type: 'boolean',
default: false
})
roleCoordinator: boolean;
@Column({
type: 'boolean',
default: false
})
roleMentor: boolean;
@Column({
type: 'boolean',
default: false
})
roleAmbulance: boolean;
@Column({
type: 'boolean',
default: false
})
roleBringer: boolean;
@Column({ @Column({
nullable: true, nullable: true,
type: 'timestamp' type: 'timestamp'

@ -23,7 +23,7 @@ export class Equipment implements Lockable {
@JoinColumn({ @JoinColumn({
name: 'cargoBikeId', referencedColumnName: 'id' name: 'cargoBikeId', referencedColumnName: 'id'
}) })
cargoBike: CargoBike; cargoBikeId: number;
@Column({ @Column({
type: 'timestamp', type: 'timestamp',

@ -25,7 +25,8 @@ export class LoanPeriod {
to: Date; to: Date;
@Column({ @Column({
type: 'simple-array' type: 'simple-array',
nullable: true
}) })
loanTimes: string[]; loanTimes: string[];
} }

@ -35,7 +35,7 @@ export class Organisation implements Lockable {
@Column({ @Column({
nullable: true nullable: true
}) })
registerNo: string; associationNo: string;
@Column(type => Address) @Column(type => Address)
address: Address; address: Address;

@ -15,7 +15,7 @@ export class TimeFrame implements Lockable {
}) })
dateRange: Date[]; dateRange: Date[];
@ManyToOne(type => LendingStation, lendingStation => lendingStation.timeFrames) @ManyToOne(type => LendingStation, lendingStation => lendingStation.timeFrames, { nullable: false })
@JoinColumn({ @JoinColumn({
name: 'lendingStationId' name: 'lendingStationId'
}) })
@ -26,7 +26,7 @@ export class TimeFrame implements Lockable {
}) })
note: string; note: string;
@ManyToOne(type => CargoBike, cargoBike => cargoBike.timeFrames) @ManyToOne(type => CargoBike, cargoBike => cargoBike.timeFrames, { nullable: false })
@JoinColumn({ @JoinColumn({
name: 'cargoBikeId' name: 'cargoBikeId'
}) })

@ -27,14 +27,14 @@ export default {
}, },
bikeEventById: (_:any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => { bikeEventById: (_:any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.ReadBikeEvent)) { if (req.permissions.includes(Permission.ReadBikeEvent)) {
return dataSources.cargoBikeAPI.findBikeEventById(id); return dataSources.cargoBikeAPI.bikeEventById(id);
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
}, },
bikeEventTypeByd: (_:any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => { bikeEventTypeByd: (_:any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.ReadBikeEvent)) { if (req.permissions.includes(Permission.ReadBikeEvent)) {
return dataSources.cargoBikeAPI.findBikeEventTypeById(id); return dataSources.cargoBikeAPI.bikeEventTypeById(id);
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
@ -229,6 +229,13 @@ export default {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
}, },
updateBikeEvent: (_: any, { bikeEvent }: { bikeEvent: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteBikeEvent)) {
return dataSources.cargoBikeAPI.updateBikeEvent(bikeEvent, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
createEquipment: (_: any, { equipment }: { equipment: any }, { dataSources, req }: { dataSources: any, req: any }) => { createEquipment: (_: any, { equipment }: { equipment: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteEquipment)) { if (req.permissions.includes(Permission.WriteEquipment)) {
return dataSources.cargoBikeAPI.createEquipment({ equipment }); return dataSources.cargoBikeAPI.createEquipment({ equipment });
@ -264,12 +271,54 @@ export default {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
}, },
lockEquipmentType: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteEquipmentType)) {
return dataSources.cargoBikeAPI.lockEquipmentType(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
unlockEquipmentType: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteEquipmentType)) {
return dataSources.cargoBikeAPI.unlockEquipmentType(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
updateEquipmentType: (_: any, { equipmentType }: { equipmentType: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteEquipmentType)) {
return dataSources.cargoBikeAPI.updateEquipmentType(equipmentType, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
createBikeEventType: (_: any, { name }: { name: any }, { dataSources, req }: { dataSources: any, req: any }) => { createBikeEventType: (_: any, { name }: { name: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteEventType)) { if (req.permissions.includes(Permission.WriteEventType)) {
return dataSources.cargoBikeAPI.createBikeEventType(name); return dataSources.cargoBikeAPI.createBikeEventType(name);
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
},
lockBikeEventType: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteEventType)) {
return dataSources.cargoBikeAPI.lockBikeEventType(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
unlockBikeEventType: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteEventType)) {
return dataSources.cargoBikeAPI.unlockBikeEventType(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
updateBikeEventType: (_: any, { bikeEventType }: { bikeEventType: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteEventType)) {
return dataSources.cargoBikeAPI.updateBikeEventType(bikeEventType, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
} }
} }
}; };

@ -68,6 +68,48 @@ export default {
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
},
lockPerson: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WritePerson)) {
return dataSources.contactInformationAPI.lockPerson(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
unlockPerson: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WritePerson)) {
return dataSources.contactInformationAPI.unlockPerson(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
updatePerson: (_: any, { person }: { person: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WritePerson)) {
return dataSources.contactInformationAPI.updatePerson(person, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
lockContactInformation: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WritePerson)) {
return dataSources.contactInformationAPI.lockContactInformation(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
unlockContactInformation: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WritePerson)) {
return dataSources.contactInformationAPI.unlockContactInformation(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
updateContactInformation: (_: any, { contactInformation }: { contactInformation: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WritePerson)) {
return dataSources.contactInformationAPI.updateContactInformation(contactInformation, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
} }
} }
}; };

@ -7,7 +7,7 @@ export default {
Query: { Query: {
lendingStationById: (_: any, { id }: { id: any }, { dataSources, req }: { dataSources: any, req: any }) => { lendingStationById: (_: any, { id }: { id: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.ReadLendingStation)) { if (req.permissions.includes(Permission.ReadLendingStation)) {
return dataSources.lendingStationAPI.lendingStationById({ id }); return dataSources.lendingStationAPI.lendingStationById(id);
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
@ -56,11 +56,32 @@ export default {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
}, },
contactInformationIntern (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) {
if (req.permissions.includes(Permission.ReadPerson)) {
return dataSources.contactInformationAPI.contactInternByLendingStationId(parent.id);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
contactInformationExtern (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) {
if (req.permissions.includes(Permission.ReadPerson)) {
return dataSources.contactInformationAPI.contactExternByLendingStationId(parent.id);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
organisation (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) {
if (req.permissions.includes(Permission.ReadOrganisation)) {
return dataSources.providerAPI.organisationByLendingStationId(parent.id);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
isLocked: (parent: any, __: any, { dataSources, req }: { dataSources: any; req: any }) => isLocked(parent, { dataSources, req }) isLocked: (parent: any, __: any, { dataSources, req }: { dataSources: any; req: any }) => isLocked(parent, { dataSources, req })
}, },
LoanPeriod: { LoanPeriod: {
loanTimes (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) { loanTimes (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) {
return parent.loanTimes.split(','); return parent.loanTimes ? parent.loanTimes : [];
} }
}, },
TimeFrame: { TimeFrame: {
@ -111,7 +132,7 @@ export default {
}, },
updateLendingStation: (_: any, { lendingStation }:{ lendingStation: LendingStation }, { dataSources, req }:{dataSources: any, req: any }) => { updateLendingStation: (_: any, { lendingStation }:{ lendingStation: LendingStation }, { dataSources, req }:{dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteLendingStation)) { if (req.permissions.includes(Permission.WriteLendingStation)) {
return dataSources.lendingStationAPI.updateLendingStation({ lendingStation }); return dataSources.lendingStationAPI.updateLendingStation(lendingStation, req.userId);
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
@ -129,6 +150,20 @@ export default {
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
},
unlockTimeFrame: (_: any, { id }:{ id: number }, { dataSources, req }:{dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteTimeFrame)) {
return dataSources.lendingStationAPI.unlockTimeFrame(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
updateTimeFrame: (_: any, { timeFrame }:{ timeFrame: LendingStation }, { dataSources, req }:{dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteTimeFrame)) {
return dataSources.lendingStationAPI.updateTimeFrame(timeFrame, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
} }
} }
}; };

@ -103,6 +103,27 @@ export default {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
}, },
lockParticipant: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteParticipant)) {
return dataSources.participantAPI.lockeParticipant(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
unlockParticipant: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteParticipant)) {
return dataSources.participantAPI.unlockeParticipant(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
updateParticipant: (_: any, { participant }: { participant: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteParticipant)) {
return dataSources.participantAPI.updateParticipant(participant, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
createEngagement: (_: any, { engagement }: { engagement: any }, { dataSources, req }: { dataSources: any, req: any }) => { createEngagement: (_: any, { engagement }: { engagement: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteEngagement)) { if (req.permissions.includes(Permission.WriteEngagement)) {
return dataSources.participantAPI.createEngagement(engagement); return dataSources.participantAPI.createEngagement(engagement);
@ -110,6 +131,48 @@ export default {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
}, },
lockEngagement: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteEngagement)) {
return dataSources.participantAPI.lockEngagement(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
unlockEngagement: (_: any, { id }: {id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteEngagement)) {
return dataSources.participantAPI.unlockngagement(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
updateEngagement: (_: any, { engagement }: { engagement: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteEngagement)) {
return dataSources.participantAPI.updateEngagement(engagement, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
lockEngagementType: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteEngagementType)) {
return dataSources.participantAPI.lockEngagementType(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
unlockEngagementType: (_: any, { id }: {id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteEngagementType)) {
return dataSources.participantAPI.unlockngagementType(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
updateEngagementType: (_: any, { engagementType }: { engagementType: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteEngagementType)) {
return dataSources.participantAPI.updateEngagementType(engagementType, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
createEngagementType: (_: any, { engagementType }: { engagementType: any }, { dataSources, req }: { dataSources: any, req: any }) => { createEngagementType: (_: any, { engagementType }: { engagementType: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteEngagementType)) { if (req.permissions.includes(Permission.WriteEngagementType)) {
return dataSources.participantAPI.createEngagementType(engagementType); return dataSources.participantAPI.createEngagementType(engagementType);

@ -72,22 +72,71 @@ export default {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
}, },
lendingStations: (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.ReadLendingStation)) {
return dataSources.providerAPI.lendingStationByOrganisationId(parent.id);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
isLocked: (parent: any, __: any, { dataSources, req }: { dataSources: any; req: any }) => isLocked(parent, { dataSources, req }) isLocked: (parent: any, __: any, { dataSources, req }: { dataSources: any; req: any }) => isLocked(parent, { dataSources, req })
}, },
Mutation: { Mutation: {
createProvider: (_: any, { provider }: { provider: number }, { dataSources, req }: { dataSources: any, req: any }) => { createProvider: (_: any, { provider }: { provider: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteProvider)) { if (req.permissions.includes(Permission.WriteProvider)) {
return dataSources.providerAPI.createProvider(provider); return dataSources.providerAPI.createProvider(provider);
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
}, },
lockProvider: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteProvider)) {
return dataSources.providerAPI.lockProvider(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
unlockProvider: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteProvider)) {
return dataSources.providerAPI.unlockProvider(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
updateProvider: (_: any, { provider }: { provider: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteProvider)) {
return dataSources.providerAPI.updateProvider(provider, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
createOrganisation: (_: any, { organisation }: { organisation: any }, { dataSources, req }: { dataSources: any, req: any }) => { createOrganisation: (_: any, { organisation }: { organisation: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteOrganisation)) { if (req.permissions.includes(Permission.WriteOrganisation)) {
return dataSources.providerAPI.createOrganisation(organisation); return dataSources.providerAPI.createOrganisation(organisation);
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
},
lockOrganisation: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteOrganisation)) {
return dataSources.providerAPI.lockOrganisation(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
unlockOrganisation: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteOrganisation)) {
return dataSources.providerAPI.unlockOrganisation(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
updateOrganisation: (_: any, { organisation }: { organisation: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteOrganisation)) {
return dataSources.providerAPI.updateOrganisation(organisation, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
} }
} }
}; };

@ -61,12 +61,54 @@ export default {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
}, },
createWorkshopType: (_: any, { workshopType }: { workshopType: number }, { dataSources, req }: { dataSources: any, req: any }) => { lockWorkshop: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteWorkshop)) {
return dataSources.workshopAPI.lockWorkshop(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
unlockWorkshop: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteWorkshop)) {
return dataSources.workshopAPI.unlockWorkshop(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
updateWorkshop: (_: any, { workshop }: { workshop: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteWorkshop)) {
return dataSources.workshopAPI.updateWorkshop(workshop, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
createWorkshopType: (_: any, { workshopType }: { workshopType: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteWorkshopType)) { if (req.permissions.includes(Permission.WriteWorkshopType)) {
return dataSources.workshopAPI.createWorkshopType(workshopType); return dataSources.workshopAPI.createWorkshopType(workshopType);
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
},
lockWorkshopType: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteWorkshopType)) {
return dataSources.workshopAPI.lockWorkshopType(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
unlockWorkshopType: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteWorkshopType)) {
return dataSources.workshopAPI.unlockWorkshopType(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
updateWorkshopType: (_: any, { workshopType }: { workshopType: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteWorkshopType)) {
return dataSources.workshopAPI.updateWorkshopType(workshopType, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
} }
} }
}; };

@ -344,6 +344,23 @@ input ParticipantCreateInput {
memberCoreTeam: Boolean memberCoreTeam: Boolean
} }
input ParticipantUpdateInput {
id: ID!
"if not set, CURRENT_DATE will be used"
start: Date
end: Date
"must create contactinformation first, if you want to use new"
contactInformationId: ID
usernamefLotte: String
usernameSlack: String
"default: false"
memberADFC: Boolean
locationZIPs: [String]
"default: false"
memberCoreTeam: Boolean
keepLock: Boolean
}
type Workshop { type Workshop {
id: ID! id: ID!
title: String! title: String!
@ -367,6 +384,17 @@ input WorkshopCreateInput {
trainer2Id: ID trainer2Id: ID
} }
input WorkshopUpdateInput {
id: ID!
title: String
description: String
date: Date!
workshopTypeId: ID
trainer1Id: ID
trainer2Id: ID
keepLock: Boolean
}
type WorkshopType { type WorkshopType {
id: ID! id: ID!
name: String! name: String!
@ -380,6 +408,11 @@ input WorkshopTypeCreateInput {
name: String! name: String!
} }
input WorkshopTypeUpdateInput {
id: ID!
name: String
}
type EngagementType { type EngagementType {
id: ID! id: ID!
name: String! name: String!
@ -395,6 +428,13 @@ input EngagementTypeCreateInput {
description: String description: String
} }
input EngagementTypeUpdateInput {
id: ID!
name: String
description: String
keepLock: Boolean
}
type Engagement { type Engagement {
id: ID! id: ID!
engagementType: EngagementType! engagementType: EngagementType!
@ -402,14 +442,6 @@ type Engagement {
to: Date to: Date
participant: Participant! participant: Participant!
cargoBike: CargoBike! cargoBike: CargoBike!
roleCoordinator: Boolean!
roleEmployeeADFC: Boolean!
"""
Wahr, wenn die Person Pate ist.
"""
roleMentor: Boolean!
roleAmbulance: Boolean!
roleBringer: Boolean!
isLocked: Boolean! isLocked: Boolean!
"null if not locked by other user" "null if not locked by other user"
lockedBy: ID lockedBy: ID
@ -424,19 +456,15 @@ input EngagementCreateInput {
to: Date to: Date
participantId: ID! participantId: ID!
cargoBikeId: ID! cargoBikeId: ID!
"default: false" }
roleCoordinator: Boolean input EngagementUpdateInput {
"default: false" id: ID!
roleEmployeeADFC: Boolean engagementTypeId: ID
""" from: Date
Wahr, wenn die Person Pate ist. to: Date
default: false participantId: ID
""" cargoBikeId: ID
roleMentor: Boolean keepLock: Boolean
"default: false"
roleAmbulance: Boolean
"default: false"
roleBringer: Boolean
} }
type Taxes { type Taxes {
@ -511,6 +539,7 @@ input EquipmentTypeUpdateInput {
id: ID! id: ID!
name: String name: String
description: String description: String
keepLock: Boolean
} }
"An Event is a point in time, when the state of the bike somehow changed." "An Event is a point in time, when the state of the bike somehow changed."
@ -547,6 +576,22 @@ input BikeEventCreateInput {
remark: String remark: String
} }
input BikeEventUpdateInput {
id: ID!
bikeEventTypeId: ID
cargoBikeId: ID
responsibleId: ID
relatedId: ID
date: Date
description: String
"""
Path to documents
"""
documents: [String]
remark: String
keepLock: Boolean
}
type BikeEventType { type BikeEventType {
id: ID! id: ID!
name: String! name: String!
@ -554,9 +599,10 @@ type BikeEventType {
lockedUntil: Date lockedUntil: Date
} }
input BikeEventTypeInput { input BikeEventTypeUpdateInput {
id: ID! id: ID!
name: String name: String
keepLock: Boolean
} }
"(dt. Anbieter) bezieht sich auf die Beziehung einer Person oder Organisation zum Lastenrad" "(dt. Anbieter) bezieht sich auf die Beziehung einer Person oder Organisation zum Lastenrad"
@ -580,6 +626,16 @@ input ProviderCreateInput {
cargoBikeIds: [ID] cargoBikeIds: [ID]
} }
input ProviderUpdateInput {
id: ID!
formName: String
privatePersonId: ID
organisationId: ID
"cargoBikes are added, you can not take existing relations away. use update cargoBike or add bike to another provider instead"
cargoBikeIds: [ID]
keepLock: Boolean
}
""" """
A Person can have several instances of contact information. A Person can have several instances of contact information.
The reason for this is, that some people have info for interns and externals that are different. The reason for this is, that some people have info for interns and externals that are different.
@ -600,6 +656,13 @@ input PersonCreateInput {
firstName: String! firstName: String!
} }
input PersonUpdateInput {
id: ID!
name: String
firstName: String
keepLock: Boolean
}
type ContactInformation { type ContactInformation {
id: ID! id: ID!
person: Person! person: Person!
@ -631,6 +694,7 @@ input ContactInformationUpdateInput {
email: String email: String
email2: String email2: String
note: String note: String
keepLock: Boolean
} }
type Organisation { type Organisation {
@ -655,17 +719,27 @@ type Organisation {
input OrganisationCreateInput { input OrganisationCreateInput {
address: AddressCreateInput! address: AddressCreateInput!
name: String! name: String!
"(dt. Ausleihstation)"
lendingStationIds: [ID]
"registration number of association" "registration number of association"
associationNo: String! associationNo: String!
"If Club, at what court registered" "If Club, at what court registered"
registeredAt: String registeredAt: String
providerId: ID
contactInformationId: ID contactInformationId: ID
otherData: String otherData: String
} }
input OrganisationUpdateInput {
id: ID!
address: AddressCreateInput
name: String
"registration number of association"
associationNo: String
"If Club, at what court registered"
registeredAt: String
contactInformationId: ID
otherData: String
keepLock: Boolean
}
"(dt. Standort)" "(dt. Standort)"
type LendingStation { type LendingStation {
id: ID! id: ID!
@ -678,6 +752,7 @@ type LendingStation {
cargoBikes: [CargoBike] cargoBikes: [CargoBike]
"Total amount of cargoBikes currently assigned to the lending station" "Total amount of cargoBikes currently assigned to the lending station"
numCargoBikes: Int! numCargoBikes: Int!
organisation: Organisation
isLocked: Boolean! isLocked: Boolean!
"null if not locked by other user" "null if not locked by other user"
lockedBy: ID lockedBy: ID
@ -693,6 +768,7 @@ input LendingStationCreateInput {
contactInformationExternId: ID contactInformationExternId: ID
address: AddressCreateInput! address: AddressCreateInput!
loanPeriod: LoanPeriodInput loanPeriod: LoanPeriodInput
organisationId: ID
} }
""" """
@ -701,9 +777,12 @@ If you want to create LendingStation with cargoBikes, use createTimeFrame and se
input LendingStationUpdateInput { input LendingStationUpdateInput {
id: ID! id: ID!
name: String name: String
contactInformation: [ContactInformationUpdateInput] contactInformationInternId: ID
contactInformationExternId: ID
address: AddressUpdateInput address: AddressUpdateInput
loanPeriod: LoanPeriodInput loanPeriod: LoanPeriodInput
organisationId: ID
keepLock: Boolean
} }
""" """
@ -763,8 +842,8 @@ input TimeFrameUpdateInput {
from: Date from: Date
to: Date to: Date
note: String note: String
lendingStation: ID lendingStationId: ID
cargoBike: ID cargoBikeId: ID
keepLock: Boolean keepLock: Boolean
} }
@ -824,7 +903,7 @@ type Query {
bikeEventTypes(offset: Int!, limit: Int!): [BikeEventType] bikeEventTypes(offset: Int!, limit: Int!): [BikeEventType]
bikeEventTypeByd(id: ID!): BikeEventType bikeEventTypeByd(id: ID!): BikeEventType
bikeEvents(offset: Int!, limit: Int!): [BikeEvent]! bikeEvents(offset: Int!, limit: Int!): [BikeEvent]!
bikeEventById(id:ID!): BikeEvent! bikeEventById(id:ID!): BikeEvent
} }
type Mutation { type Mutation {
@ -851,6 +930,9 @@ type Mutation {
"update Equipment, returns updated equipment. CargoBike will be null, if cargoBikeId is not set. Pass null for cargoBikeIs to delete the relation" "update Equipment, returns updated equipment. CargoBike will be null, if cargoBikeId is not set. Pass null for cargoBikeIs to delete the relation"
updateEquipment(equipment: EquipmentUpdateInput!): Equipment! updateEquipment(equipment: EquipmentUpdateInput!): Equipment!
createEquipmentType(equipmentType: EquipmentTypeCreateInput!): EquipmentType! createEquipmentType(equipmentType: EquipmentTypeCreateInput!): EquipmentType!
lockEquipmentType(id: ID!): EquipmentType!
unlockEquipmentType(id: ID!): Boolean!
updateEquipmentType(equipmentType: EquipmentTypeUpdateInput!): EquipmentType!
""" """
LENDINGSTATION LENDINGSTATION
creates new lendingStation and returns lendingStation with new ID creates new lendingStation and returns lendingStation with new ID
@ -861,29 +943,62 @@ type Mutation {
"updates lendingStation of given ID with supplied fields and returns updated lendingStation" "updates lendingStation of given ID with supplied fields and returns updated lendingStation"
updateLendingStation(lendingStation: LendingStationUpdateInput!): LendingStation! updateLendingStation(lendingStation: LendingStationUpdateInput!): LendingStation!
createTimeFrame(timeFrame: TimeFrameCreateInput!): TimeFrame! createTimeFrame(timeFrame: TimeFrameCreateInput!): TimeFrame!
lockTimeFrame(id: ID!): TimeFrame lockTimeFrame(id: ID!): TimeFrame!
unlockTimeFrame(id: ID!): Boolean!
updateTimeFrame(timeFrame: TimeFrameUpdateInput!): TimeFrame!
""" """
BIKEEVENT BIKEEVENT
""" """
createBikeEventType(name: String!): BikeEventType! createBikeEventType(name: String!): BikeEventType!
lockBikeEventType(id: ID!): BikeEventType!
unlockBikeEventType(id:ID!): Boolean!
updateBikeEventType(bikeEventType: BikeEventTypeUpdateInput!): BikeEventType!
"creates new BikeEvent" "creates new BikeEvent"
createBikeEvent(bikeEvent: BikeEventCreateInput!): BikeEvent! createBikeEvent(bikeEvent: BikeEventCreateInput!): BikeEvent!
lockBikeEventById(id: ID!): BikeEvent lockBikeEventById(id: ID!): BikeEvent
unlockBikeEventById(id: ID!): Boolean! unlockBikeEventById(id: ID!): Boolean!
updateBikeEvent(bikeEvent: BikeEventUpdateInput!): BikeEvent
""" """
PARTICIPANTS PARTICIPANTS
""" """
createParticipant(participant: ParticipantCreateInput!): Participant! createParticipant(participant: ParticipantCreateInput!): Participant!
lockParticipant(id: ID!): Participant!
unlockParticipant(id: ID!): Boolean
updateParticipant(participant: ParticipantUpdateInput!): Participant!
createWorkshopType(workshopType: WorkshopTypeCreateInput!): WorkshopType! createWorkshopType(workshopType: WorkshopTypeCreateInput!): WorkshopType!
lockWorkshopType(id: ID!): WorkshopType!
unlockWorkshopType(id: ID!): Boolean!
updateWorkshopType(workshopType: WorkshopTypeUpdateInput!): WorkshopType!
createWorkshop(workshop: WorkshopCreateInput!): Workshop! createWorkshop(workshop: WorkshopCreateInput!): Workshop!
lockWorkshop(id: ID!): Workshop!
unlockWorkshop(id: ID!): Boolean!
updateWorkshop(workshop: WorkshopUpdateInput!): Workshop!
"create new contactInfo" "create new contactInfo"
createContactInformation(contactInformation: ContactInformationCreateInput!): ContactInformation! createContactInformation(contactInformation: ContactInformationCreateInput!): ContactInformation!
lockContactInformation(id: ID!): ContactInformation!
unlockContactInformation(id: ID!): Boolean!
updateContactInformation(contactInformation: ContactInformationUpdateInput!): ContactInformation!
createPerson(person: PersonCreateInput!): Person! createPerson(person: PersonCreateInput!): Person!
lockPerson(id: ID!): Person!
unlockPerson(id: ID!): Person!
updatePerson(person: PersonUpdateInput!): Person!
lockEngagement(id: ID!): Engagement!
unlockEngagement(id: ID!): Boolean!
updateEngagement(engagement: EngagementUpdateInput!): Engagement!
createEngagementType(engagementType: EngagementTypeCreateInput!): EngagementType! createEngagementType(engagementType: EngagementTypeCreateInput!): EngagementType!
lockEngagementType(id: ID!): EngagementType!
unlockEngagementType(id: ID!): Boolean!
updateEngagementType(engagementType: EngagementTypeUpdateInput!): EngagementType!
"create Engagement" "create Engagement"
createEngagement(engagement: EngagementCreateInput): Engagement! createEngagement(engagement: EngagementCreateInput): Engagement!
createProvider(provider: ProviderCreateInput!): Provider! createProvider(provider: ProviderCreateInput!): Provider!
lockProvider(id: ID!): Provider!
unlockProvider(id: ID!): Boolean!
updateProvider(provider: ProviderUpdateInput!): Provider!
createOrganisation(organisation: OrganisationCreateInput!): Organisation! createOrganisation(organisation: OrganisationCreateInput!): Organisation!
lockOrganisation(id: ID!): Organisation!
unlockOrganisation(id: ID!): Boolean!
updateOrganisation(organisation: OrganisationUpdateInput!): Organisation!
} }
`; `;

Loading…
Cancel
Save