Basic user can only update the cars that he owns
MODIFY
src/server/rest/service/CarService.ts
src/server/rest/service/CarService.ts
@@ -311,6 +311,19 @@ export default class CarService {
const car = await CarStorage.getCar(req.user.tenantID, filteredRequest.id);
UtilsService.assertObjectExists(action, car, `Car ID '${filteredRequest.id}' does not exist`,
MODULE_NAME, 'handleUpdateCar', req.user);
+ if (Authorizations.isBasic(req.user)) {
+ const userCar = await CarStorage.getUserCarByCarUser(req.user.tenantID, filteredRequest.id, req.user.id);
+ if (!userCar || !userCar.owner) {
+ throw new AppAuthError({
+ errorCode: HTTPAuthError.ERROR,
+ user: req.user,
+ action: Action.UPDATE,
+ entity: Entity.CAR,
+ module: MODULE_NAME,
+ method: 'handleUpdateCar'
+ });
+ }
+ }
if (car.licensePlate !== filteredRequest.licensePlate || car.vin !== filteredRequest.vin) {
const checkCar = await CarStorage.getCarByVinLicensePlate(req.user.tenantID, filteredRequest.licensePlate, filteredRequest.vin);
if (checkCar) {
@@ -342,6 +355,9 @@ export default class CarService {
if (Authorizations.isBasic(req.user)) {
const userCar = await CarStorage.getUserCarByCarUser(req.user.tenantID, car.id, req.user.id);
if (userCar.default !== filteredRequest.isDefault) {
+ if (filteredRequest.isDefault) {
+ await CarStorage.clearDefaultUserCar(req.user.tenantID, req.user.id);
+ }
userCar.default = filteredRequest.isDefault;
userCar.lastChangedBy = { 'id': req.user.id };
userCar.lastChangedOn = new Date();
@@ -379,7 +395,8 @@ export default class CarService {
const cars = await CarStorage.getCars(req.user.tenantID,
{
search: filteredRequest.Search,
- userIDs: Authorizations.isBasic(req.user) ? [req.user.id] : null
+ userIDs: Authorizations.isBasic(req.user) ? [req.user.id] : null,
+ withUsers: true
},
{ limit: filteredRequest.Limit, skip: filteredRequest.Skip, sort: filteredRequest.Sort, onlyRecordCount: filteredRequest.OnlyRecordCount });
// Filter

MODIFY
src/server/rest/service/security/CarSecurity.ts
src/server/rest/service/security/CarSecurity.ts
@@ -221,6 +221,9 @@ export default class CarSecurity {
if (car.carCatalog) {
filteredCar.carCatalog = CarSecurity.filterCarCatalogResponse(car.carCatalog, loggedUser);
}
+ if (car.usersCar) {
+ filteredCar.owner = (car.usersCar.find((usersCar) => usersCar.userID.toString() === loggedUser.id)).owner;
+ }
return filteredCar;
}

MODIFY
src/storage/mongodb/CarStorage.ts
src/storage/mongodb/CarStorage.ts
@@ -568,11 +568,11 @@ export default class CarStorage {
try {
const userCarDB = await CarStorage.getUserCarByCarUser(tenantID, carID, userCar.userID);
if (userCarDB) {
- if (userCarDB.default !== userCar.default || !userCarDB.active) {
+ if (userCarDB.default !== userCar.default || !userCarDB.active || (userCar.owner && !userCarDB.owner)) {
if (userCar.default) {
await CarStorage.clearDefaultUserCar(tenantID, userCar.userID);
}
- if (userCar.owner !== userCarDB.owner) {
+ if (userCar.owner && !userCarDB.owner) {
await CarStorage.clearUserCarOwner(tenantID, carID);
}
userCarDB.owner = userCar.owner;
@@ -667,13 +667,13 @@ export default class CarStorage {
if (!Utils.isEmptyArray(params.userIDs) || params.withUsers) {
DatabaseUtils.pushUserCarLookupInAggregation({
tenantID: tenantID, aggregation, localField: '_id', foreignField: 'carID',
- asField: 'userscars', oneToOneCardinality: false
+ asField: 'usersCar', oneToOneCardinality: false
});
if (!Utils.isEmptyArray(params.userIDs)) {
- filters['userscars.userID'] = { $in: params.userIDs.map((userID) => Utils.convertToObjectID(userID)) };
+ filters['usersCar.userID'] = { $in: params.userIDs.map((userID) => Utils.convertToObjectID(userID)) };
}
if (params.defaultCar) {
- filters['userscars.default'] = true;
+ filters['usersCar.default'] = true;
}
}
// Filters
@@ -688,8 +688,8 @@ export default class CarStorage {
});
if (params.withUsers) {
DatabaseUtils.pushUserLookupInAggregation({
- tenantID: tenantID, aggregation, localField: 'userscars.userID', foreignField: '_id',
- asField: 'users', oneToOneCardinality: false
+ tenantID: tenantID, aggregation, localField: 'usersCar.userID', foreignField: '_id',
+ asField: 'users', oneToOneCardinality: false, objectIDFields: ['_id']
});
}
// Limit records?
@@ -715,6 +715,7 @@ export default class CarStorage {
DatabaseUtils.pushCreatedLastChangedInAggregation(tenantID, aggregation);
// Handle the ID
DatabaseUtils.pushRenameDatabaseID(aggregation);
+
// Sort
if (dbParams.sort) {
aggregation.push({

MODIFY
src/types/Car.ts
src/types/Car.ts
@@ -139,6 +139,8 @@ export interface Car extends CreatedUpdatedProps {
type?: CarType;
converterType?: string;
isDefault?: boolean;
+ owner?: boolean;
+ usersCar?: UserCar[];
}
export interface UserCar extends CreatedUpdatedProps {

Basic user can only update the cars that he owns