new generic lock/unlock functions

pull/14/head
leonnicolas 4 years ago
parent 81a7870cbb
commit 595f66f3dc
No known key found for this signature in database
GPG Key ID: 088D0743E2B65C07

@ -32,7 +32,7 @@ export class CargoBikeAPI extends DataSource {
} }
/** /**
* Finds cargo bike by id, retuns null if id was not found * Finds cargo bike by id, returns null if id was not found
* @param param0 id of bike * @param param0 id of bike
*/ */
async findCargoBikeById (id: number) { async findCargoBikeById (id: number) {
@ -67,40 +67,16 @@ export class CargoBikeAPI extends DataSource {
.loadOne(); .loadOne();
} }
async lockCargoBike (id: number, req: any, dataSources: any) {
if (await LockUtils.lockEntity(this.connection, CargoBike, 'cargobike', id, req, dataSources)) {
return this.findCargoBikeById(id);
} else {
return new GraphQLError('CargoBike is locked by other user');
}
}
async unlockCargoBike (id: number, req: any, dataSources: any) {
return this.unlockEntity(CargoBike, 'cargobike', id, req, dataSources);
}
async lockEntity (target: ObjectType<Lockable>, alias: string, id: number, req: any, dataSources: any) {
return LockUtils.lockEntity(this.connection, target, alias, id, req, dataSources);
}
async unlockEntity (target: ObjectType<Lockable>, alias: string, id: number, req: any, dataSources: any) {
return LockUtils.unlockEntity(this.connection, target, alias, id, req, dataSources);
}
async isLocked (id: number, req: any, dataSources: any) {
return LockUtils.isLocked(this.connection, CargoBike, 'cargobike', id, req, dataSources);
}
/** /**
* Updates CargoBike and return updated cargoBike * Updates CargoBike and return updated cargoBike
* @param param0 cargoBike to be updated * @param param0 cargoBike to be updated
*/ */
async updateCargoBike (cargoBike: any, req: any, dataSources: any) { async updateCargoBike (cargoBike: any, userId:number) {
// TODO lock cargoBike can return error to save one sql query, this will be a complex sql query // 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)) { if (!await this.checkId(CargoBike, 'cargobike', cargoBike.id)) {
return new GraphQLError('ID not found'); return new GraphQLError('ID not found');
} }
if (!await this.lockCargoBike(cargoBike.id, req, dataSources)) { if (!await LockUtils.lockEntity(this.connection, CargoBike, 'cb', cargoBike.id, userId)) {
return new GraphQLError('Bike locked by other user'); return new GraphQLError('Bike locked by other user');
} }
const keepLock = cargoBike?.keepLock; const keepLock = cargoBike?.keepLock;
@ -124,7 +100,7 @@ export class CargoBikeAPI extends DataSource {
.of(cargoBike.id) .of(cargoBike.id)
.addAndRemove(equipmentTypeIds, await this.equipmentTypeByCargoBikeId(cargoBike.id)); // TODO remove all existing relations .addAndRemove(equipmentTypeIds, await this.equipmentTypeByCargoBikeId(cargoBike.id)); // TODO remove all existing relations
}); });
!keepLock && await this.unlockCargoBike(cargoBike.id, req, dataSources); !keepLock && await LockUtils.unlockEntity(this.connection, CargoBike, 'cb', cargoBike.id, userId);
return await this.findCargoBikeById(cargoBike.id); return await this.findCargoBikeById(cargoBike.id);
} }
@ -183,6 +159,16 @@ export class CargoBikeAPI extends DataSource {
.loadOne(); .loadOne();
} }
async bikeEventsByCargoBikeId (id: number, offset: number = 0, limit:number = 100) {
return await this.connection.getRepository(CargoBike)
.createQueryBuilder('cb')
.skip(offset)
.take(limit)
.relation(CargoBike, 'bikeEvents')
.of(id)
.loadMany();
}
async createBikeEventType (bikeEventType: any) { async createBikeEventType (bikeEventType: any) {
return (await this.connection.getRepository(BikeEventType) return (await this.connection.getRepository(BikeEventType)
.createQueryBuilder('bet') .createQueryBuilder('bet')
@ -229,6 +215,14 @@ export class CargoBikeAPI extends DataSource {
.getOne(); .getOne();
} }
async lockBikeEvent (id: number, userId: number) {
return await LockUtils.lockEntity(this.connection, BikeEvent, 'be', id, userId);
}
async unlockBikeEvent (id: number, userId: number) {
return await LockUtils.unlockEntity(this.connection, BikeEvent, 'be', id, userId);
}
async findEquipmentById (id: number) { async findEquipmentById (id: number) {
return await this.connection.getRepository(Equipment) return await this.connection.getRepository(Equipment)
.createQueryBuilder('equipment') .createQueryBuilder('equipment')
@ -248,6 +242,12 @@ export class CargoBikeAPI extends DataSource {
return result === 1; return result === 1;
} }
/**
* Returns equipment of one cargoBike
* @param offset
* @param limit
* @param id
*/
async equipmentByCargoBikeId (offset: number, limit: number, id: number) { async equipmentByCargoBikeId (offset: number, limit: number, id: number) {
return await this.connection.getRepository(Equipment) return await this.connection.getRepository(Equipment)
.createQueryBuilder('equipment') .createQueryBuilder('equipment')
@ -282,16 +282,12 @@ export class CargoBikeAPI extends DataSource {
.getOne())?.cargoBike; .getOne())?.cargoBike;
} }
async lockEquipment (id: number, req: any, dataSources: any) { async lockEquipment (id: number, userId: number) {
if (await this.lockEntity(Equipment, 'equipment', id, req, dataSources)) { return LockUtils.lockEntity(this.connection, Equipment, 'e', id, userId);
return this.findEquipmentById(id);
} else {
return new GraphQLError('Equipment locked by other user');
}
} }
async unlockEquipment (id: number, req: any, dataSources: any) { async unlockEquipment (id: number, userId: number) {
return await this.unlockEntity(Equipment, 'equipment', id, req, dataSources); return await LockUtils.unlockEntity(this.connection, Equipment, 'equipment', id, userId);
} }
/** /**
@ -299,12 +295,12 @@ export class CargoBikeAPI extends DataSource {
* Will return updated Equipment joined with CargoBike only if cargoBike is was set in param0 * Will return updated Equipment joined with CargoBike only if cargoBike is was set in param0
* @param param0 struct with equipment properites * @param param0 struct with equipment properites
*/ */
async updateEquipment (equipment: any, req: any, dataSources: any) { 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 // 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)) { if (!await this.checkId(Equipment, 'alias', equipment.id)) {
return new GraphQLError('ID not found in DB'); return new GraphQLError('ID not found in DB');
} }
if (!await this.lockEntity(Equipment, 'equipment', equipment.id, req, dataSources)) { if (!await LockUtils.lockEntity(this.connection, Equipment, 'equipment', equipment.id, userId)) {
return new GraphQLError('Equipment locked by other user'); return new GraphQLError('Equipment locked by other user');
} }
const keepLock = equipment.keepLock; const keepLock = equipment.keepLock;
@ -324,7 +320,7 @@ export class CargoBikeAPI extends DataSource {
.relation(Equipment, 'cargoBike') .relation(Equipment, 'cargoBike')
.of(equipment.id) .of(equipment.id)
.set(cargoBikeId); .set(cargoBikeId);
!keepLock && this.unlockCargoBike(equipment.id, req, dataSources); !keepLock && LockUtils.unlockEntity(this.connection, Equipment, 'e', equipment.id, userId);
return this.findEquipmentById(equipment.id); return this.findEquipmentById(equipment.id);
} }
return this.findEquipmentById(equipment.id); return this.findEquipmentById(equipment.id);

@ -5,6 +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';
export class LendingStationAPI extends DataSource { export class LendingStationAPI extends DataSource {
connection : Connection connection : Connection
@ -81,6 +82,26 @@ export class LendingStationAPI extends DataSource {
.getMany().catch(() => { return []; }); .getMany().catch(() => { return []; });
} }
async timeFrameById (id: number) {
return await this.connection.getRepository(TimeFrame)
.createQueryBuilder('tf')
.select()
.where('id = :id', { id: id })
.getOne();
}
async lockLendingStationById (id: number, uId: number) {
return await LockUtils.lockEntity(this.connection, LendingStation, 'ls', id, uId);
}
unlockLendingStationById (id: number, uId: number) {
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
@ -115,22 +136,14 @@ export class LendingStationAPI extends DataSource {
*/ */
async createLendingStation (lendingStation: any) { async createLendingStation (lendingStation: any) {
let inserts: any; let inserts: any;
try {
await this.connection.transaction(async entiyManager => { await this.connection.transaction(async entiyManager => {
inserts = await entiyManager.createQueryBuilder(LendingStation, 'lendingstation') inserts = await entiyManager.createQueryBuilder(LendingStation, 'lendingstation')
.insert() .insert()
.values([lendingStation]) .values([lendingStation])
.returning('*') .returning('*')
.execute(); .execute();
await entiyManager.getRepository(LendingStation)
.createQueryBuilder('lendingstation')
.relation(LendingStation, 'contactPersons')
.of(lendingStation.id)
.add(lendingStation?.contactPersonIds.map((e: any) => { return Number(e); }));
}); });
} catch (e :any) {
return new GraphQLError('Transaction could not be completed');
}
const newLendingStaion = inserts.generatedMaps[0]; const newLendingStaion = inserts.generatedMaps[0];
newLendingStaion.id = inserts.identifiers[0].id; newLendingStaion.id = inserts.identifiers[0].id;
return newLendingStaion; return newLendingStaion;

@ -3,6 +3,7 @@ import { Connection, EntityManager, getConnection } from 'typeorm';
import { Provider } from '../../model/Provider'; 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';
export class ProviderAPI extends DataSource { export class ProviderAPI extends DataSource {
connection : Connection connection : Connection
@ -36,6 +37,14 @@ export class ProviderAPI extends DataSource {
.getOne(); .getOne();
} }
async providerByCargoBikeId (id: number) {
return await this.connection.getRepository(CargoBike)
.createQueryBuilder('cb')
.relation(CargoBike, 'provider')
.of(id)
.loadOne();
}
async organisationByProviderId (id: number) { async organisationByProviderId (id: number) {
return await this.connection.getRepository(Provider) return await this.connection.getRepository(Provider)
.createQueryBuilder() .createQueryBuilder()

@ -1,5 +1,6 @@
import { Connection, ObjectType } from 'typeorm'; import { Connection, ObjectType } from 'typeorm';
import { CargoBike, Lockable } from '../../model/CargoBike'; import { CargoBike, Lockable } from '../../model/CargoBike';
import { GraphQLError } from 'graphql';
export function genDateRange (struct: any) { export function genDateRange (struct: any) {
if (struct.to === undefined) { if (struct.to === undefined) {
@ -14,23 +15,33 @@ export function genDateRange (struct: any) {
} }
} }
/**
* Can be used in resolvers to specify if entry is locked by other user.
* Returns true if locked by other user.
* @param parent
* @param dataSources
* @param req user request
*/
export function isLocked (parent: any, { dataSources, req }: { dataSources: any; req: any }) {
return dataSources.userAPI.getUserId(LockUtils.getToken(req)).then((value: number) => {
return value !== parent.lockedBy && new Date() <= new Date(parent.lockedUntil);
});
}
export class LockUtils { export class LockUtils {
static getToken (req: any) : string { static getToken (req: any) : string {
return req.headers.authorization?.replace('Bearer ', ''); return req.headers.authorization?.replace('Bearer ', '');
} }
/** static async findById (connection: Connection, target: ObjectType<Lockable>, alias: string, id: number, userId: number): Promise<Lockable> {
* Locks any Entity, that return await connection.getRepository(target)
* @param connection .createQueryBuilder(alias)
* @param target .select()
* @param alias .where(alias + '.id = :id', { id: id })
* @param id .getOne();
* @param req }
* @param dataSources
*/ static async lockEntity (connection: Connection, target: ObjectType<Lockable>, alias: string, id: number, userId: number): Promise<Lockable> {
static async lockEntity (connection: Connection, target: ObjectType<Lockable>, alias: string, id: number, req: any, dataSources: any) {
const token = this.getToken(req);
const userId = await dataSources.userAPI.getUserId(token);
const lock = await connection.getRepository(target) const lock = await connection.getRepository(target)
.createQueryBuilder(alias) .createQueryBuilder(alias)
.select([ .select([
@ -54,25 +65,14 @@ export class LockUtils {
}) })
.where('id = :id', { id: id }) .where('id = :id', { id: id })
.execute(); .execute();
return true; return await this.findById(connection, target, alias, id, userId);
} else { } else {
// lock was set // lock was set
return false; throw new GraphQLError('Entry locked by other user');
} }
} }
/** static async unlockEntity (connection: Connection, target: ObjectType<Lockable>, alias: string, id: number, userId: number): Promise<boolean> {
* Unlocks any entity that implements Lockable.
* @param connection
* @param target
* @param alias
* @param id
* @param req
* @param dataSources
*/
static async unlockEntity (connection: Connection, target: ObjectType<Lockable>, alias: string, id: number, req: any, dataSources: any) {
const token = this.getToken(req);
const userId = await dataSources.userAPI.getUserId(token);
const lock = await connection.getRepository(target) const lock = await connection.getRepository(target)
.createQueryBuilder(alias) .createQueryBuilder(alias)
.select([ .select([
@ -115,9 +115,7 @@ export class LockUtils {
* @param req * @param req
* @param dataSources * @param dataSources
*/ */
static async isLocked (connection: Connection, target: ObjectType<Lockable>, alias: string, id: number, req: any, dataSources: any) { static async isLocked (connection: Connection, target: ObjectType<Lockable>, alias: string, id: number, userId: number) {
const token = this.getToken(req);
const userId = await dataSources.userAPI.getUserId(token);
const lock = await connection.getRepository(CargoBike) const lock = await connection.getRepository(CargoBike)
.createQueryBuilder(alias) .createQueryBuilder(alias)
.select([ .select([
@ -135,4 +133,22 @@ export class LockUtils {
// eslint-disable-next-line eqeqeq // eslint-disable-next-line eqeqeq
} else return lock?.lockedBy != userId; } else return lock?.lockedBy != userId;
} }
/**
* Returns true if id is found in database
* @param connection
* @param target
* @param alias
* @param id
*/
static async checkId (connection: Connection, target: ObjectType<Lockable>, alias: string, id: number) {
const result = await connection.getRepository(target)
.createQueryBuilder(alias)
.select([
alias + '.id'
])
.where('id = :id', { id: id })
.getCount();
return result === 1;
}
} }

@ -45,12 +45,14 @@ require('dotenv').config();
async function authenticate (req: any, res: any, next: any) { async function authenticate (req: any, res: any, next: any) {
if (process.env.NODE_ENV === 'develop') { if (process.env.NODE_ENV === 'develop') {
req.permissions = requiredPermissions.map((e) => e.name); req.permissions = requiredPermissions.map((e) => e.name);
req.userId = await userAPI.getUserId(req.headers.authorization?.replace('Bearer ', ''));
next(); next();
} else { } else {
const token = req.headers.authorization?.replace('Bearer ', ''); const token = req.headers.authorization?.replace('Bearer ', '');
if (token) { if (token) {
if (await userAPI.validateToken(token)) { if (await userAPI.validateToken(token)) {
req.permissions = await userAPI.getUserPermissions(token); req.permissions = await userAPI.getUserPermissions(token);
req.userId = await userAPI.getUserId(req.headers.authorization?.replace('Bearer ', ''));
next(); next();
} else { } else {
res.status(401); res.status(401);

@ -1,12 +1,12 @@
/* eslint no-unused-vars: "off" */ /* eslint no-unused-vars: "off" */
import { Entity, Column, PrimaryGeneratedColumn, ManyToOne, JoinColumn, TreeLevelColumn } from 'typeorm'; import { Entity, Column, PrimaryGeneratedColumn, ManyToOne, JoinColumn, TreeLevelColumn } from 'typeorm';
import { CargoBike } from './CargoBike'; import { CargoBike, Lockable } from './CargoBike';
import { BikeEventType } from './BikeEventType'; import { BikeEventType } from './BikeEventType';
import { Participant } from './Participant'; import { Participant } from './Participant';
import { type } from 'os'; import { type } from 'os';
@Entity() @Entity()
export class BikeEvent { export class BikeEvent implements Lockable {
@PrimaryGeneratedColumn() @PrimaryGeneratedColumn()
id: number; id: number;
@ -61,4 +61,15 @@ export class BikeEvent {
name: 'bikeEventTypeId' name: 'bikeEventTypeId'
}) })
bikeEventTypeId: number; bikeEventTypeId: number;
@Column({
nullable: true,
type: 'timestamp'
})
lockedUntil: Date;
@Column({
nullable: true
})
lockedBy: number;
} }

@ -1,10 +1,10 @@
import { Entity, PrimaryGeneratedColumn, ManyToOne, Column, JoinColumn } from 'typeorm'; import { Entity, PrimaryGeneratedColumn, ManyToOne, Column, JoinColumn } from 'typeorm';
import { Participant } from './Participant'; import { Participant } from './Participant';
import { CargoBike } from './CargoBike'; import { CargoBike, Lockable } from './CargoBike';
import { EngagementType } from './EngagementType'; import { EngagementType } from './EngagementType';
@Entity() @Entity()
export class Engagement { export class Engagement implements Lockable {
@PrimaryGeneratedColumn() @PrimaryGeneratedColumn()
id: number; id: number;
@ -62,4 +62,15 @@ export class Engagement {
default: false default: false
}) })
roleBringer: boolean; roleBringer: boolean;
@Column({
nullable: true,
type: 'timestamp'
})
lockedUntil: Date;
@Column({
nullable: true
})
lockedBy: number;
} }

@ -3,6 +3,7 @@ import { TimeFrame } from './TimeFrame';
import { Organisation } from './Organisation'; import { Organisation } from './Organisation';
import { Address } from './Provider'; import { Address } from './Provider';
import { ContactInformation } from './ContactInformation'; import { ContactInformation } from './ContactInformation';
import { Lockable } from './CargoBike';
export class LoanPeriod { export class LoanPeriod {
/** /**
@ -30,7 +31,7 @@ export class LoanPeriod {
} }
@Entity() @Entity()
export class LendingStation { export class LendingStation implements Lockable {
@PrimaryGeneratedColumn() @PrimaryGeneratedColumn()
id: number; id: number;
@ -63,4 +64,15 @@ export class LendingStation {
name: 'organisationId' name: 'organisationId'
}) })
organisationId: number; organisationId: number;
@Column({
nullable: true,
type: 'timestamp'
})
lockedUntil: Date;
@Column({
nullable: true
})
lockedBy: number;
} }

@ -2,9 +2,10 @@ import { PrimaryGeneratedColumn, OneToOne, OneToMany, Column, Entity, JoinColumn
import { LendingStation } from './LendingStation'; import { LendingStation } from './LendingStation';
import { Address, Provider } from './Provider'; import { Address, Provider } from './Provider';
import { ContactInformation } from './ContactInformation'; import { ContactInformation } from './ContactInformation';
import { Lockable } from './CargoBike';
@Entity() @Entity()
export class Organisation { export class Organisation implements Lockable {
@PrimaryGeneratedColumn() @PrimaryGeneratedColumn()
id: number; id: number;
@ -38,4 +39,15 @@ export class Organisation {
@Column(type => Address) @Column(type => Address)
address: Address; address: Address;
@Column({
nullable: true,
type: 'timestamp'
})
lockedUntil: Date;
@Column({
nullable: true
})
lockedBy: number;
} }

@ -2,9 +2,10 @@ import { Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn, OneToMany
import { ContactInformation } from './ContactInformation'; import { ContactInformation } from './ContactInformation';
import { Engagement } from './Engagement'; import { Engagement } from './Engagement';
import { Workshop } from './Workshop'; import { Workshop } from './Workshop';
import { Lockable } from './CargoBike';
@Entity() @Entity()
export class Participant { export class Participant implements Lockable {
@PrimaryGeneratedColumn() @PrimaryGeneratedColumn()
id: number; id: number;
@ -68,4 +69,15 @@ export class Participant {
default: false default: false
}) })
memberADFC: boolean; memberADFC: boolean;
@Column({
nullable: true,
type: 'timestamp'
})
lockedUntil: Date;
@Column({
nullable: true
})
lockedBy: number;
} }

@ -1,12 +1,12 @@
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm'; import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm';
import { LendingStation } from './LendingStation'; import { LendingStation } from './LendingStation';
import { CargoBike } from './CargoBike'; import { CargoBike, Lockable } from './CargoBike';
/** /**
* When was a cargoBike at what lendingStation * When was a cargoBike at what lendingStation
*/ */
@Entity() @Entity()
export class TimeFrame { export class TimeFrame implements Lockable {
@PrimaryGeneratedColumn() @PrimaryGeneratedColumn()
id: number; id: number;
@ -25,4 +25,15 @@ export class TimeFrame {
@ManyToOne(type => CargoBike, cargoBike => cargoBike.timeFrames) @ManyToOne(type => CargoBike, cargoBike => cargoBike.timeFrames)
cargoBike: CargoBike; cargoBike: CargoBike;
@Column({
nullable: true,
type: 'timestamp'
})
lockedUntil: Date;
@Column({
nullable: true
})
lockedBy: number;
} }

@ -1,5 +1,6 @@
import { Permission } from '../datasources/userserver/permission'; import { Permission } from '../datasources/userserver/permission';
import { GraphQLError } from 'graphql'; import { GraphQLError } from 'graphql';
import { isLocked } from '../datasources/db/utils';
export default { export default {
Query: { Query: {
@ -59,24 +60,29 @@ export default {
lendingStation (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) { lendingStation (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) {
return dataSources.lendingStationAPI.lendingStationByCargoBikeId(parent.id); return dataSources.lendingStationAPI.lendingStationByCargoBikeId(parent.id);
}, },
isLocked (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) { bikeEvents (parent: any, { offset, limit }: { offset: number, limit: number }, { dataSources, req }: { dataSources: any, req: any }) {
return dataSources.cargoBikeAPI.isLocked(parent.id, req, dataSources); return dataSources.cargoBikeAPI.bikeEventsByCargoBikeId(parent.id, offset, limit);
}, },
isLocked: (parent: any, __: any, { dataSources, req }: { dataSources: any; req: any }) => isLocked(parent, { dataSources, req }),
lockedBy (): any { lockedBy (): any {
return null; return null;
}, },
timeFrames (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) { timeFrames (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) {
return dataSources.lendingStationAPI.timeFramesByCargoBikeId(parent.id, req, dataSources); return dataSources.lendingStationAPI.timeFramesByCargoBikeId(parent.id);
}, },
equipmentType (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) { equipmentType (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) {
return dataSources.cargoBikeAPI.equipmentTypeByCargoBikeId(parent.id, req, dataSources); return dataSources.cargoBikeAPI.equipmentTypeByCargoBikeId(parent.id);
},
provider (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) {
return dataSources.providerAPI.providerByCargoBikeId(parent.id);
} }
}, },
Equipment: { Equipment: {
cargoBike (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) { cargoBike (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) {
return dataSources.cargoBikeAPI.cargoBikeByEquipmentId(parent.id); return dataSources.cargoBikeAPI.cargoBikeByEquipmentId(parent.id);
} },
isLocked: (parent: any, __: any, { dataSources, req }: { dataSources: any; req: any }) => isLocked(parent, { dataSources, req })
}, },
BikeEvent: { BikeEvent: {
cargoBike (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) { cargoBike (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) {
@ -90,7 +96,11 @@ export default {
}, },
related (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) { related (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) {
return dataSources.cargoBikeAPI.relatedByBikeEventId(parent.id); return dataSources.cargoBikeAPI.relatedByBikeEventId(parent.id);
} },
isLocked: (parent: any, __: any, { dataSources, req }: { dataSources: any; req: any }) => isLocked(parent, { dataSources, req })
},
BikeEventType: {
isLocked: (parent: any, __: any, { dataSources, req }: { dataSources: any; req: any }) => isLocked(parent, { dataSources, req })
}, },
Mutation: { Mutation: {
createCargoBike: (_: any, { cargoBike }: { cargoBike: any }, { dataSources, req }: { dataSources: any, req: any }) => { createCargoBike: (_: any, { cargoBike }: { cargoBike: any }, { dataSources, req }: { dataSources: any, req: any }) => {
@ -102,21 +112,21 @@ export default {
}, },
lockCargoBikeById: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => { lockCargoBikeById: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteBike)) { if (req.permissions.includes(Permission.WriteBike)) {
return dataSources.cargoBikeAPI.lockCargoBike(id, req, dataSources); return dataSources.cargoBikeAPI.lockCargoBike(id, req.userId);
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
}, },
unlockCargoBikeById: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => { unlockCargoBikeById: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteBike)) { if (req.permissions.includes(Permission.WriteBike)) {
return dataSources.cargoBikeAPI.unlockCargoBike(id, req, dataSources); return dataSources.cargoBikeAPI.unlockCargoBike(id, req.userId);
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
}, },
updateCargoBike: (_: any, { cargoBike }: { cargoBike: any }, { dataSources, req }: { dataSources: any, req: any }) => { updateCargoBike: (_: any, { cargoBike }: { cargoBike: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteBike)) { if (req.permissions.includes(Permission.WriteBike)) {
return dataSources.cargoBikeAPI.updateCargoBike(cargoBike, req, dataSources); return dataSources.cargoBikeAPI.updateCargoBike(cargoBike, req.userId);
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
@ -128,6 +138,20 @@ export default {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
}, },
lockBikeEventById: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteBike)) {
return dataSources.cargoBikeAPI.lockBikeEvent(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
unlockBikeEventById: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteBike)) {
return dataSources.cargoBikeAPI.unlockBikeEvent(id, 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.WriteBike)) { if (req.permissions.includes(Permission.WriteBike)) {
return dataSources.cargoBikeAPI.createEquipment({ equipment }); return dataSources.cargoBikeAPI.createEquipment({ equipment });
@ -137,21 +161,21 @@ export default {
}, },
lockEquipmentById: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => { lockEquipmentById: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteBike)) { if (req.permissions.includes(Permission.WriteBike)) {
return dataSources.cargoBikeAPI.lockEquipment(id, req, dataSources); return dataSources.cargoBikeAPI.lockEquipment(id, req.userId);
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
}, },
unlockEquipment: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => { unlockEquipmentById: (_: any, { id }: { id: number }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteBike)) { if (req.permissions.includes(Permission.WriteBike)) {
return dataSources.cargoBikeAPI.unlockEquipment(id, req, dataSources); return dataSources.cargoBikeAPI.unlockEquipment(id, req.userId);
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
}, },
updateEquipment: (_: any, { equipment }: { equipment: any }, { dataSources, req }: { dataSources: any, req: any }) => { updateEquipment: (_: any, { equipment }: { equipment: any }, { dataSources, req }: { dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteBike)) { if (req.permissions.includes(Permission.WriteBike)) {
return dataSources.cargoBikeAPI.updateEquipment(equipment, req, dataSources); return dataSources.cargoBikeAPI.updateEquipment(equipment, req.userId);
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }

@ -1,6 +1,7 @@
import { GraphQLError } from 'graphql'; import { GraphQLError } from 'graphql';
import { Permission } from '../datasources/userserver/permission'; import { Permission } from '../datasources/userserver/permission';
import { Person } from '../model/Person'; import { Person } from '../model/Person';
import { isLocked } from '../datasources/db/utils';
export default { export default {
Query: { Query: {
@ -26,7 +27,8 @@ export default {
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
} },
isLocked: (parent: any, __: any, { dataSources, req }: { dataSources: any; req: any }) => isLocked(parent, { dataSources, req })
}, },
Person: { Person: {
contactInformation: (parent: Person, __: any, { dataSources, req }: { dataSources: any, req: any }) => { contactInformation: (parent: Person, __: any, { dataSources, req }: { dataSources: any, req: any }) => {
@ -35,7 +37,8 @@ export default {
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
} },
isLocked: (parent: any, __: any, { dataSources, req }: { dataSources: any; req: any }) => isLocked(parent, { dataSources, req })
}, },
ContactInformation: { ContactInformation: {
person: (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) => { person: (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) => {
@ -44,7 +47,8 @@ export default {
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
} },
isLocked: (parent: any, __: any, { dataSources, req }: { dataSources: any; req: any }) => isLocked(parent, { dataSources, req })
}, },
Mutation: { Mutation: {
createContactPerson: (_: any, { contactPerson }: { contactPerson: any }, { dataSources, req }: { dataSources: any, req: any }) => { createContactPerson: (_: any, { contactPerson }: { contactPerson: any }, { dataSources, req }: { dataSources: any, req: any }) => {

@ -1,6 +1,7 @@
import { Permission } from '../datasources/userserver/permission'; import { Permission } from '../datasources/userserver/permission';
import { GraphQLError } from 'graphql'; import { GraphQLError } from 'graphql';
import { LendingStation } from '../model/LendingStation'; import { LendingStation } from '../model/LendingStation';
import { isLocked } from '../datasources/db/utils';
export default { export default {
Query: { Query: {
@ -35,6 +36,12 @@ export default {
}, },
cargoBikes (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) { cargoBikes (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) {
return dataSources.lendingStationAPI.cargoBikesByLendingStationId(parent.id); return dataSources.lendingStationAPI.cargoBikesByLendingStationId(parent.id);
},
isLocked: (parent: any, __: any, { dataSources, req }: { dataSources: any; req: any }) => isLocked(parent, { dataSources, req })
},
LoanPeriod: {
loanTimes (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) {
return parent.loanTimes.split(',');
} }
}, },
TimeFrame: { TimeFrame: {
@ -50,7 +57,8 @@ export default {
}, },
lendingStation (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) { lendingStation (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) {
return dataSources.lendingStationAPI.lendingStationByTimeFrameId(parent.id); return dataSources.lendingStationAPI.lendingStationByTimeFrameId(parent.id);
} },
isLocked: (parent: any, __: any, { dataSources, req }: { dataSources: any; req: any }) => isLocked(parent, { dataSources, req })
}, },
Mutation: { Mutation: {
createLendingStation: (_: any, { lendingStation }:{ lendingStation: LendingStation }, { dataSources, req }:{dataSources: any, req: any }) => { createLendingStation: (_: any, { lendingStation }:{ lendingStation: LendingStation }, { dataSources, req }:{dataSources: any, req: any }) => {
@ -60,6 +68,16 @@ export default {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
}, },
lockLendingStationById: (_: any, { id }:{ id: number }, { dataSources, req }:{dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteBike)) {
return dataSources.lendingStationAPI.lockLendingStationById(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
},
unlockLendingStationById: (_: any, { id }:{ id: number }, { dataSources, req }:{dataSources: any, req: any }) => {
return dataSources.lendingStationAPI.unlockLendingStationById(id, req.userId);
},
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.WriteBike)) { if (req.permissions.includes(Permission.WriteBike)) {
return dataSources.lendingStationAPI.updateLendingStation({ lendingStation }); return dataSources.lendingStationAPI.updateLendingStation({ lendingStation });
@ -73,6 +91,13 @@ export default {
} else { } else {
return new GraphQLError('Insufficient Permissions'); return new GraphQLError('Insufficient Permissions');
} }
},
lockTimeFrame: (_: any, { id }:{ id: number }, { dataSources, req }:{dataSources: any, req: any }) => {
if (req.permissions.includes(Permission.WriteBike)) {
return dataSources.lendingStationAPI.lockTimeFrame(id, req.userId);
} else {
return new GraphQLError('Insufficient Permissions');
}
} }
} }
}; };

@ -1,6 +1,7 @@
import { GraphQLError } from 'graphql'; import { GraphQLError } from 'graphql';
import { Permission } from '../datasources/userserver/permission'; import { Permission } from '../datasources/userserver/permission';
import { EngagementType } from '../model/EngagementType'; import { EngagementType } from '../model/EngagementType';
import { isLocked } from '../datasources/db/utils';
export default { export default {
Query: { Query: {
@ -25,7 +26,8 @@ export default {
}, },
contactInformation (parent: any, _: any, { dataSources, req }: { dataSources: any, req: any }) { contactInformation (parent: any, _: any, { dataSources, req }: { dataSources: any, req: any }) {
return (dataSources.participantAPI.contactInformationByParticipantId(parent.id)); return (dataSources.participantAPI.contactInformationByParticipantId(parent.id));
} },
isLocked: (parent: any, __: any, { dataSources, req }: { dataSources: any; req: any }) => isLocked(parent, { dataSources, req })
}, },
Engagement: { Engagement: {
cargoBike (parent: any, _: any, { dataSources, req }: { dataSources: any, req: any }) { cargoBike (parent: any, _: any, { dataSources, req }: { dataSources: any, req: any }) {
@ -43,7 +45,8 @@ export default {
to (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) { to (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) {
const str = (parent.dateRange as string).split(',')[1].replace(')', ''); const str = (parent.dateRange as string).split(',')[1].replace(')', '');
return (str.length > 0) ? str : null; return (str.length > 0) ? str : null;
} },
isLocked: (parent: any, __: any, { dataSources, req }: { dataSources: any; req: any }) => isLocked(parent, { dataSources, req })
}, },
Mutation: { Mutation: {
createParticipant: (_: any, { participant }: { participant: any }, { dataSources, req }: { dataSources: any, req: any }) => { createParticipant: (_: any, { participant }: { participant: any }, { dataSources, req }: { dataSources: any, req: any }) => {

@ -1,5 +1,6 @@
import { GraphQLError } from 'graphql'; import { GraphQLError } from 'graphql';
import { Permission } from '../datasources/userserver/permission'; import { Permission } from '../datasources/userserver/permission';
import { isLocked } from '../datasources/db/utils';
export default { export default {
Query: { Query: {
@ -31,7 +32,8 @@ export default {
}, },
privatePerson: (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) => { privatePerson: (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) => {
return dataSources.providerAPI.privatePersonByProviderId(parent.id); return dataSources.providerAPI.privatePersonByProviderId(parent.id);
} },
isLocked: (parent: any, __: any, { dataSources, req }: { dataSources: any; req: any }) => isLocked(parent, { dataSources, req })
}, },
Organisation: { Organisation: {
provider: (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) => { provider: (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) => {
@ -39,7 +41,8 @@ export default {
}, },
contactInformation: (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) => { contactInformation: (parent: any, __: any, { dataSources, req }: { dataSources: any, req: any }) => {
return dataSources.providerAPI.contactInformationByOrganisationId(parent.id); return dataSources.providerAPI.contactInformationByOrganisationId(parent.id);
} },
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: number }, { dataSources, req }: { dataSources: any, req: any }) => {

@ -1,5 +1,6 @@
import { Permission } from '../datasources/userserver/permission'; import { Permission } from '../datasources/userserver/permission';
import { GraphQLError } from 'graphql'; import { GraphQLError } from 'graphql';
import { isLocked } from '../datasources/db/utils';
export default { export default {
Query: { Query: {
@ -24,7 +25,11 @@ export default {
}, },
trainer2: (parent: any, __:any, { dataSources, req }: { dataSources: any, req: any }) => { trainer2: (parent: any, __:any, { dataSources, req }: { dataSources: any, req: any }) => {
return dataSources.workshopAPI.trainer2ByWorkshopId(parent.id); return dataSources.workshopAPI.trainer2ByWorkshopId(parent.id);
} },
isLocked: (parent: any, __: any, { dataSources, req }: { dataSources: any; req: any }) => isLocked(parent, { dataSources, req })
},
WorkshopType: {
isLocked: (parent: any, __: any, { dataSources, req }: { dataSources: any; req: any }) => isLocked(parent, { dataSources, req })
}, },
Mutation: { Mutation: {
createWorkshop: (_: any, { workshop }: { workshop: number }, { dataSources, req }: { dataSources: any, req: any }) => { createWorkshop: (_: any, { workshop }: { workshop: number }, { dataSources, req }: { dataSources: any, req: any }) => {

@ -31,7 +31,7 @@ type CargoBike {
Does not refer to an extra table in the database. Does not refer to an extra table in the database.
""" """
dimensionsAndLoad: DimensionsAndLoad! dimensionsAndLoad: DimensionsAndLoad!
bikeEvents: [BikeEvent] bikeEvents(offset: Int, limit: Int): [BikeEvent]
equipment(offset: Int!, limit: Int!): [Equipment] equipment(offset: Int!, limit: Int!): [Equipment]
"Refers to equipment that is not unique. See kommentierte info tabelle -> Fragen -> Frage 2" "Refers to equipment that is not unique. See kommentierte info tabelle -> Fragen -> Frage 2"
equipmentType: [EquipmentType] equipmentType: [EquipmentType]
@ -184,6 +184,116 @@ input InsuranceDataUpdateInput {
notes: String notes: String
} }
"How are the dimensions and how much weight can handle a bike. This data is merged in the CargoBike table and the BikeModel table."
type DimensionsAndLoad {
hasCoverBox: Boolean!
lockable: Boolean!
boxLength: Float!
boxWidth: Float!
boxHeight: Float!
maxWeightBox: Float!
maxWeightLuggageRack: Float!
maxWeightTotal: Float!
bikeLength: Float!
bikeWidth: Float
bikeHeight: Float
bikeWeight: Float
}
input DimensionsAndLoadCreateInput {
hasCoverBox: Boolean!
lockable: Boolean!
boxLength: Float!
boxWidth: Float!
boxHeight: Float!
maxWeightBox: Float!
maxWeightLuggageRack: Float!
maxWeightTotal: Float!
bikeLength: Float!
bikeWidth: Float
bikeHeight: Float
bikeWeight: Float
}
input DimensionsAndLoadUpdateInput {
hasCoverBox: Boolean
lockable: Boolean
boxLength: Float
boxWidth: Float
boxHeight: Float
maxWeightBox: Float
maxWeightLuggageRack: Float
maxWeightTotal: Float
bikeLength: Float
bikeWidth: Float
bikeHeight: Float
bikeWeight: Float
}
"""
Some Technical Info about the bike.
This should be 1-1 Relation with the CargoBike.
So no id needed for mutation. One Mutation for the CargoBike will be enough.
"""
type TechnicalEquipment {
bicycleShift: String!
isEBike: Boolean!
hasLightSystem: Boolean!
specialFeatures: String
}
input TechnicalEquipmentCreateInput {
bicycleShift: String!
isEBike: Boolean!
hasLightSystem: Boolean!
specialFeatures: String
}
input TechnicalEquipmentUpdateInput {
bicycleShift: String
isEBike: Boolean
hasLightSystem: Boolean
specialFeatures: String
}
"""
The Security Info about the bike.
his should be 1-1 Relation with the CargoBike.
So no id needed for mutation. One Mutation for the CargoBike will be enough.
"""
type Security {
frameNumber: String!
keyNumberFrameLock: String
keyNumberAXAChain: String
policeCoding: String
adfcCoding: String
}
input SecurityCreateInput {
frameNumber: String!
keyNumberFrameLock: String
keyNumberAXAChain: String
policeCoding: String
adfcCoding: String
}
input SecurityUpdateInput {
frameNumber: String
keyNumberFrameLock: String
keyNumberAXAChain: String
policeCoding: String
adfcCoding: String
}
enum StickerBikeNameState {
OK
IMPROVE
PRODUCED
NONEED
MISSING
UNKNOWN
}
enum Group{ enum Group{
KL KL
LI LI
@ -195,18 +305,6 @@ enum Group{
TK TK
} }
"""
The BikeModel can be used for instantiate new bikes with a given model.
It should only be used to fill in default values.
Even bikes of the same model can have different properties.
"""
type BikeModel {
id: ID!
name: String!
dimensionsAndLoad: DimensionsAndLoad!
technicalEquipment: TechnicalEquipment!
}
type Participant { type Participant {
id: ID! id: ID!
start: Date! start: Date!
@ -225,6 +323,10 @@ type Participant {
""" """
distributedActiveBikeParte: Boolean! distributedActiveBikeParte: Boolean!
engagement: [Engagement] engagement: [Engagement]
isLocked: Boolean!
"null if not locked by other user"
lockedBy: ID
lockedUntil: Date
} }
input ParticipantCreateInput { input ParticipantCreateInput {
@ -250,6 +352,10 @@ type Workshop {
workshopType: WorkshopType! workshopType: WorkshopType!
trainer1: Participant! trainer1: Participant!
trainer2: Participant trainer2: Participant
isLocked: Boolean!
"null if not locked by other user"
lockedBy: ID
lockedUntil: Date
} }
input WorkshopCreateInput { input WorkshopCreateInput {
@ -264,6 +370,10 @@ input WorkshopCreateInput {
type WorkshopType { type WorkshopType {
id: ID! id: ID!
name: String! name: String!
isLocked: Boolean!
"null if not locked by other user"
lockedBy: ID
lockedUntil: Date
} }
input WorkshopTypeCreateInput { input WorkshopTypeCreateInput {
@ -274,6 +384,10 @@ type EngagementType {
id: ID! id: ID!
name: String! name: String!
description: String! description: String!
isLocked: Boolean!
"null if not locked by other user"
lockedBy: ID
lockedUntil: Date
} }
input EngagementTypeCreateInput { input EngagementTypeCreateInput {
@ -296,6 +410,10 @@ type Engagement {
roleMentor: Boolean! roleMentor: Boolean!
roleAmbulance: Boolean! roleAmbulance: Boolean!
roleBringer: Boolean! roleBringer: Boolean!
isLocked: Boolean!
"null if not locked by other user"
lockedBy: ID
lockedUntil: Date
} }
input EngagementCreateInput { input EngagementCreateInput {
@ -341,16 +459,6 @@ enum OrganisationArea {
ZB ZB
} }
type ChainSwap {
id: ID!
"""
TODO why is this a string"
"""
mechanic: String
timeOfSwap: Date
keyNumberOldAXAChain: String
}
""" """
This type represents a piece of equipment that represents a real physical object. This type represents a piece of equipment that represents a real physical object.
The object must be unique. So it is possible to tell it apart from similar objects by a serial number. The object must be unique. So it is possible to tell it apart from similar objects by a serial number.
@ -358,35 +466,27 @@ The object must be unique. So it is possible to tell it apart from similar objec
type Equipment { type Equipment {
id: ID! id: ID!
serialNo: String! serialNo: String!
"""
TODO unclear what this means. tomy fragen
"""
investable: Boolean
title: String! title: String!
description: String description: String
cargoBike: CargoBike cargoBike: CargoBike
isLocked: Boolean!
"null if not locked by other user"
lockedBy: ID
lockedUntil: Date
} }
input EquipmentCreateInput { input EquipmentCreateInput {
serialNo: String! serialNo: String!
"""
TODO unclear what this means. tomy fragen
"""
title: String! title: String!
description: String description: String
investable: Boolean
cargoBikeId: ID cargoBikeId: ID
} }
input EquipmentUpdateInput { input EquipmentUpdateInput {
id: ID! id: ID!
serialNo: String serialNo: String
"""
TODO unclear what this means. tomy fragen
"""
title: String title: String
description: String description: String
investable: Boolean
cargoBikeId: ID cargoBikeId: ID
"will keep Bike locked if set to true, default = false" "will keep Bike locked if set to true, default = false"
keepLock: Boolean keepLock: Boolean
@ -396,6 +496,10 @@ type EquipmentType {
id: ID! id: ID!
name: String! name: String!
description: String! description: String!
isLocked: Boolean!
"null if not locked by other user"
lockedBy: ID
lockedUntil: Date
} }
input EquipmentTypeCreateInput { input EquipmentTypeCreateInput {
@ -423,6 +527,10 @@ type BikeEvent {
""" """
documents: [String]! documents: [String]!
remark: String remark: String
isLocked: Boolean!
"null if not locked by other user"
lockedBy: ID
lockedUntil: Date
} }
input BikeEventCreateInput { input BikeEventCreateInput {
@ -442,6 +550,8 @@ input BikeEventCreateInput {
type BikeEventType { type BikeEventType {
id: ID! id: ID!
name: String! name: String!
isLocked: Boolean!
lockedUntil: Date
} }
input BikeEventTypeInput { input BikeEventTypeInput {
@ -449,116 +559,6 @@ input BikeEventTypeInput {
name: String name: String
} }
"How are the dimensions and how much weight can handle a bike. This data is merged in the CargoBike table and the BikeModel table."
type DimensionsAndLoad {
hasCoverBox: Boolean!
lockable: Boolean!
boxLength: Float!
boxWidth: Float!
boxHeight: Float!
maxWeightBox: Float!
maxWeightLuggageRack: Float!
maxWeightTotal: Float!
bikeLength: Float!
bikeWidth: Float
bikeHeight: Float
bikeWeight: Float
}
input DimensionsAndLoadCreateInput {
hasCoverBox: Boolean!
lockable: Boolean!
boxLength: Float!
boxWidth: Float!
boxHeight: Float!
maxWeightBox: Float!
maxWeightLuggageRack: Float!
maxWeightTotal: Float!
bikeLength: Float!
bikeWidth: Float
bikeHeight: Float
bikeWeight: Float
}
input DimensionsAndLoadUpdateInput {
hasCoverBox: Boolean
lockable: Boolean
boxLength: Float
boxWidth: Float
boxHeight: Float
maxWeightBox: Float
maxWeightLuggageRack: Float
maxWeightTotal: Float
bikeLength: Float
bikeWidth: Float
bikeHeight: Float
bikeWeight: Float
}
"""
Some Technical Info about the bike.
This should be 1-1 Relation with the CargoBike.
So no id needed for mutation. One Mutation for the CargoBike will be enough.
"""
type TechnicalEquipment {
bicycleShift: String!
isEBike: Boolean!
hasLightSystem: Boolean!
specialFeatures: String
}
input TechnicalEquipmentCreateInput {
bicycleShift: String!
isEBike: Boolean!
hasLightSystem: Boolean!
specialFeatures: String
}
input TechnicalEquipmentUpdateInput {
bicycleShift: String
isEBike: Boolean
hasLightSystem: Boolean
specialFeatures: String
}
"""
The Security Info about the bike.
his should be 1-1 Relation with the CargoBike.
So no id needed for mutation. One Mutation for the CargoBike will be enough.
"""
type Security {
frameNumber: String!
keyNumberFrameLock: String
keyNumberAXAChain: String
policeCoding: String
adfcCoding: String
}
input SecurityCreateInput {
frameNumber: String!
keyNumberFrameLock: String
keyNumberAXAChain: String
policeCoding: String
adfcCoding: String
}
input SecurityUpdateInput {
frameNumber: String
keyNumberFrameLock: String
keyNumberAXAChain: String
policeCoding: String
adfcCoding: String
}
enum StickerBikeNameState {
OK
IMPROVE
PRODUCED
NONEED
MISSING
UNKNOWN
}
"(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"
type Provider { type Provider {
id: ID! id: ID!
@ -566,6 +566,10 @@ type Provider {
privatePerson: ContactInformation privatePerson: ContactInformation
organisation: Organisation organisation: Organisation
cargoBikes: [CargoBike] cargoBikes: [CargoBike]
isLocked: Boolean!
"null if not locked by other user"
lockedBy: ID
lockedUntil: Date
} }
"(dt. Anbieter)" "(dt. Anbieter)"
@ -585,6 +589,10 @@ type Person {
name: String! name: String!
firstName: String! firstName: String!
contactInformation: [ContactInformation] contactInformation: [ContactInformation]
isLocked: Boolean!
"null if not locked by other user"
lockedBy: ID
lockedUntil: Date
} }
input PersonCreateInput { input PersonCreateInput {
@ -600,6 +608,10 @@ type ContactInformation {
email: String email: String
email2: String email2: String
note: String note: String
isLocked: Boolean!
"null if not locked by other user"
lockedBy: ID
lockedUntil: Date
} }
input ContactInformationCreateInput { input ContactInformationCreateInput {
@ -626,6 +638,10 @@ type ContactPerson {
id: ID! id: ID!
intern: Boolean! intern: Boolean!
contactInformation: ContactInformation! contactInformation: ContactInformation!
isLocked: Boolean!
"null if not locked by other user"
lockedBy: ID
lockedUntil: Date
} }
input ContactPersonCreateInput { input ContactPersonCreateInput {
@ -652,6 +668,10 @@ type Organisation {
provider: Provider provider: Provider
contactInformation: ContactInformation contactInformation: ContactInformation
otherData: String otherData: String
isLocked: Boolean!
"null if not locked by other user"
lockedBy: ID
lockedUntil: Date
} }
input OrganisationCreateInput { input OrganisationCreateInput {
@ -680,6 +700,10 @@ 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!
isLocked: Boolean!
"null if not locked by other user"
lockedBy: ID
lockedUntil: Date
} }
""" """
@ -715,7 +739,7 @@ type LoanPeriod {
Loan times from and until for each day of the week. Loan times from and until for each day of the week.
Starting with Monday from, Monday to, Tuesday from, ..., Sunday to Starting with Monday from, Monday to, Tuesday from, ..., Sunday to
""" """
times: [String] loanTimes: [String]
} }
""" """
@ -729,7 +753,7 @@ input LoanPeriodInput {
Loan times from and until for each day of the week. Loan times from and until for each day of the week.
Starting with Monday from, Monday to, Tuesday from, ..., Sunday to Starting with Monday from, Monday to, Tuesday from, ..., Sunday to
""" """
times: [String] loanTimes: [String]
} }
"(dt. Zeitscheibe) When was a bike where" "(dt. Zeitscheibe) When was a bike where"
@ -742,6 +766,10 @@ type TimeFrame {
note: String note: String
lendingStation: LendingStation! lendingStation: LendingStation!
cargoBike: CargoBike! cargoBike: CargoBike!
isLocked: Boolean!
"null if not locked by other user"
lockedBy: ID
lockedUntil: Date
} }
input TimeFrameCreateInput { input TimeFrameCreateInput {
@ -828,7 +856,7 @@ type Mutation {
"lock equipment returns true if bike is not locked or if it doesnt exist" "lock equipment returns true if bike is not locked or if it doesnt exist"
lockEquipmentById(id: ID!): Equipment! lockEquipmentById(id: ID!): Equipment!
"unlock Equipment, returns true if Bike does not exist" "unlock Equipment, returns true if Bike does not exist"
unlockEquipment(id: ID!): Boolean! unlockEquipmentById(id: ID!): Boolean!
"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!
@ -837,15 +865,20 @@ type Mutation {
creates new lendingStation and returns lendingStation with new ID creates new lendingStation and returns lendingStation with new ID
""" """
createLendingStation(lendingStation: LendingStationCreateInput): LendingStation! createLendingStation(lendingStation: LendingStationCreateInput): LendingStation!
lockLendingStationById(id: ID!): LendingStation
unlockLendingStationById(id: ID!): Boolean!
"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
""" """
BIKEEVENT BIKEEVENT
""" """
createBikeEventType(name: String!): BikeEventType! createBikeEventType(name: String!): BikeEventType!
"creates new BikeEvent" "creates new BikeEvent"
createBikeEvent(bikeEvent: BikeEventCreateInput!): BikeEvent! createBikeEvent(bikeEvent: BikeEventCreateInput!): BikeEvent!
lockBikeEventById(id: ID!): BikeEvent
unlockBikeEventById(id: ID!): Boolean!
"create participant" "create participant"
createParticipant(participant: ParticipantCreateInput!): Participant! createParticipant(participant: ParticipantCreateInput!): Participant!
createWorkshopType(workshopType: WorkshopTypeCreateInput!): WorkshopType! createWorkshopType(workshopType: WorkshopTypeCreateInput!): WorkshopType!

Loading…
Cancel
Save