Skip to content

Commit

Permalink
Merge pull request #297 from casanet/add-coutdown-reset
Browse files Browse the repository at this point in the history
Add reset timeout countdown
  • Loading branch information
haimkastner authored May 12, 2023
2 parents da94158 + 9f47be5 commit e8eef0c
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 44 deletions.
24 changes: 23 additions & 1 deletion backend/src/business-layer/timeoutBl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
// tslint:disable-next-line:ordered-imports
Minion,
MinionStatus,
MinionTimeout,
Switch,
SwitchOptions,
Toggle,
Expand Down Expand Up @@ -92,6 +93,26 @@ export class TimeoutBl {
logger.info('Timeout module init done.');
}

/**
* Restart timeout countdown for a minion
*/
public async restartMinionTimeout(minionId: string) {
const minionTimeout = this.minionsTimeoutInfo.find(mti => mti.minionId === minionId);
minionTimeout!.turnOnTimeStump = new Date();
}

/**
* Get all minions timeout countdown state
* @returns
*/
public async getTimeoutStatus(): Promise<MinionTimeout[]> {
return this.minionsTimeoutInfo.map(mti => ({
minionId: mti?.minionId,
active: mti?.status === 'on',
countdownTimestamp: mti?.turnOnTimeStump?.getTime(),
} as MinionTimeout));
}

/**
* Get minion info sturuct if exist for given minion id.
* @param minionId minion id to get info for.
Expand All @@ -107,7 +128,7 @@ export class TimeoutBl {
private async timeoutActivation(): Promise<void> {

// If currently the timeoutActivation in action, ignore other calls
if(this.isTimeoutPossessing){
if (this.isTimeoutPossessing) {
return;
}

Expand Down Expand Up @@ -232,6 +253,7 @@ export class TimeoutBl {
const timeoutMinion = this.findMinionInfo(minion.minionId);
this.minionsTimeoutInfo.splice(this.minionsTimeoutInfo.indexOf(timeoutMinion), 1);
}

}

export const TimeoutBlSingleton = new TimeoutBl(MinionsBlSingleton);
14 changes: 7 additions & 7 deletions backend/src/controllers/actionsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class ActionsController extends Controller {
@Security('userAuth')
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@MinionsRestriction({ restrictPermission: 'BLOCK', elementArgIndex: 0, extractMinionIds: async (actionId: string) => (await actionsService.getActionById(actionId)).minionId })
@MinionsRestriction({ requirePermission: 'READ', elementArgIndex: 0, extractMinionIds: async (actionId: string) => (await actionsService.getActionById(actionId)).minionId })
@Get('{actionId}')
public async getAction(actionId: string): Promise<Action> {
return await actionsService.getActionById(actionId);
Expand All @@ -54,7 +54,7 @@ export class ActionsController extends Controller {
@Security('userAuth')
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@MinionsRestriction({ restrictPermission: 'BLOCK', elementArgIndex: 0, extractMinionIds: (minionId: string) => minionId })
@MinionsRestriction({ requirePermission: 'READ', elementArgIndex: 0, extractMinionIds: (minionId: string) => minionId })
@Get('/minion/{minionId}')
public async getActionByMinion(minionId: string): Promise<Action[]> {
return await actionsService.getMinionActions(minionId);
Expand All @@ -68,8 +68,8 @@ export class ActionsController extends Controller {
@Security('userAuth')
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@MinionsRestriction({ restrictPermission: 'READ', elementArgIndex: 0, extractMinionIds: async (actionId: string) => (await actionsService.getActionById(actionId)).minionId })
@MinionsRestriction({ restrictPermission: 'READ', elementArgIndex: 1, extractMinionIds: (action: Action) => action.minionId })
@MinionsRestriction({ requirePermission: 'WRITE', elementArgIndex: 0, extractMinionIds: async (actionId: string) => (await actionsService.getActionById(actionId)).minionId })
@MinionsRestriction({ requirePermission: 'WRITE', elementArgIndex: 1, extractMinionIds: (action: Action) => action.minionId })
@Put('{actionId}')
public async setAction(actionId: string, @Body() action: Action): Promise<void> {
return await actionsService.setAction(actionId, action);
Expand All @@ -83,7 +83,7 @@ export class ActionsController extends Controller {
@Security('userAuth')
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@MinionsRestriction({ restrictPermission: 'READ', elementArgIndex: 0, extractMinionIds: async (actionId: string) => (await actionsService.getActionById(actionId)).minionId })
@MinionsRestriction({ requirePermission: 'WRITE', elementArgIndex: 0, extractMinionIds: async (actionId: string) => (await actionsService.getActionById(actionId)).minionId })
@Put('set-active/{actionId}')
public async setActionActive(actionId: string, @Query() active: boolean): Promise<void> {
return await actionsService.setActionActive(actionId, active);
Expand All @@ -96,7 +96,7 @@ export class ActionsController extends Controller {
@Security('userAuth')
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@MinionsRestriction({ restrictPermission: 'READ', elementArgIndex: 0, extractMinionIds: async (actionId: string) => (await actionsService.getActionById(actionId)).minionId })
@MinionsRestriction({ requirePermission: 'WRITE', elementArgIndex: 0, extractMinionIds: async (actionId: string) => (await actionsService.getActionById(actionId)).minionId })
@Delete('{actionId}')
public async deleteAction(actionId: string): Promise<void> {
return await actionsService.deleteAction(actionId);
Expand All @@ -110,7 +110,7 @@ export class ActionsController extends Controller {
@Security('userAuth')
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@MinionsRestriction({ restrictPermission: 'READ', elementArgIndex: 0, extractMinionIds: async (action: Action) => action.minionId })
@MinionsRestriction({ requirePermission: 'WRITE', elementArgIndex: 0, extractMinionIds: async (action: Action) => action.minionId })
@Post()
public async createAction(@Body() action: Action): Promise<Action> {
return await actionsService.createAction(action);
Expand Down
74 changes: 52 additions & 22 deletions backend/src/controllers/minionsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
} from 'tsoa';
import { MinionsBlSingleton } from '../business-layer/minionsBl';
import { TimelineBlSingleton } from '../business-layer/timelineBl';
import { TimeoutBlSingleton } from '../business-layer/timeoutBl';
import {
ErrorResponse,
MinionCalibrate,
Expand All @@ -26,6 +27,7 @@ import {
MinionSetRoomName,
MinionStatus,
MinionTimeline,
MinionTimeout,
RestrictionItem,
ScanningStatus,
SetMinionAutoTurnOff,
Expand Down Expand Up @@ -55,12 +57,51 @@ export class MinionsController extends Controller {
@Security('userAuth')
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@MinionsRestriction({ restrictPermission: 'BLOCK', elementArgIndex: 0, extractMinionIds: (minionId: string) => minionId })
@MinionsRestriction({ requirePermission: 'READ', elementArgIndex: 0, extractMinionIds: (minionId: string) => minionId })
@Get('timeline/{minionId}')
public async getMinionTimeline(minionId: string): Promise<MinionTimeline[]> {
return await TimelineBlSingleton.getTimeline(minionId);
}

/**
* Update minion auto turns off timeout.
*/
@Security('userAuth')
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@MinionsResultsRestriction((m: MinionTimeout) => m.minionId)
@Get('timeout')
public async getMinionsTimeout(): Promise<MinionTimeout[]> {
return await TimeoutBlSingleton.getTimeoutStatus();
}

/**
* URestart minion timeout countdown.
*/
@Security('userAuth')
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@MinionsRestriction({ requirePermission: 'WRITE', elementArgIndex: 0, extractMinionIds: (minionId: string) => minionId })
@Post('timeout/restart/{minionId}')
public async restartMinionTimeout(minionId: string): Promise<void> {
return await TimeoutBlSingleton.restartMinionTimeout(minionId);
}

/**
* Update minion auto turns off timeout.
* @param minionId Minion id.
* @param setTimeout Timeout property.
*/
@Security('userAuth')
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@MinionsRestriction({ requirePermission: 'WRITE', elementArgIndex: 0, extractMinionIds: (minionId: string) => minionId })
@Put('timeout/{minionId}')
public async setMinionTimeout(minionId: string, @Body() setTimeout: SetMinionAutoTurnOff): Promise<void> {
return await MinionsBlSingleton.setMinionTimeout(minionId, setTimeout.setAutoTurnOffMS);
}


/**
* Power off all minions
*/
Expand All @@ -79,7 +120,7 @@ export class MinionsController extends Controller {
@Security('userAuth')
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@MinionsRestriction({ restrictPermission: 'READ', elementArgIndex: 0, extractMinionIds: (minionId: string) => minionId })
@MinionsRestriction({ requirePermission: 'WRITE', elementArgIndex: 0, extractMinionIds: (minionId: string) => minionId })
@Put('rename/{minionId}')
public async renameMinion(minionId: string, @Body() minionRename: MinionRename): Promise<void> {
return await MinionsBlSingleton.renameMinion(minionId, minionRename.name);
Expand All @@ -93,7 +134,7 @@ export class MinionsController extends Controller {
@Security('userAuth')
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@MinionsRestriction({ restrictPermission: 'READ', elementArgIndex: 0, extractMinionIds: (minionId: string) => minionId })
@MinionsRestriction({ requirePermission: 'WRITE', elementArgIndex: 0, extractMinionIds: (minionId: string) => minionId })
@Put('room/{minionId}')
public async renameRoom(minionId: string, @Body() roomName: MinionSetRoomName): Promise<void> {
return await MinionsBlSingleton.setMinionRoom(minionId, roomName.room);
Expand All @@ -107,25 +148,14 @@ export class MinionsController extends Controller {
@Security('userAuth')
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@MinionsRestriction({ restrictPermission: 'READ', elementArgIndex: 0, extractMinionIds: (minionId: string) => minionId })
@MinionsRestriction({ requirePermission: 'WRITE', elementArgIndex: 0, extractMinionIds: (minionId: string) => minionId })
@Put('network-device/{minionId}')
public async replaceNetworkDevice(minionId: string, @Body() macToSet: MinionSetDevice): Promise<void> {
return await MinionsBlSingleton.replaceNetworkDevice(minionId, macToSet.mac);
}

/**
* Update minion auto turns off timeout.
* @param minionId Minion id.
* @param setTimeout Timeout property.
*/
@Security('userAuth')
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@MinionsRestriction({ restrictPermission: 'READ', elementArgIndex: 0, extractMinionIds: (minionId: string) => minionId })
@Put('timeout/{minionId}')
public async setMinionTimeout(minionId: string, @Body() setTimeout: SetMinionAutoTurnOff): Promise<void> {
return await MinionsBlSingleton.setMinionTimeout(minionId, setTimeout.setAutoTurnOffMS);
}



/**
* Update minion auto turns off timeout.
Expand All @@ -135,7 +165,7 @@ export class MinionsController extends Controller {
@Security('userAuth')
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@MinionsRestriction({ restrictPermission: 'READ', elementArgIndex: 0, extractMinionIds: (minionId: string) => minionId })
@MinionsRestriction({ requirePermission: 'WRITE', elementArgIndex: 0, extractMinionIds: (minionId: string) => minionId })
@Put('calibrate/{minionId}')
public async setMinionCalibrate(minionId: string, @Body() calibration: MinionCalibrate): Promise<void> {
return await MinionsBlSingleton.setMinionCalibrate(minionId, calibration);
Expand All @@ -147,7 +177,7 @@ export class MinionsController extends Controller {
@Security('userAuth')
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@MinionsRestriction({ restrictPermission: 'READ', elementArgIndex: 0, extractMinionIds: (minionId: string) => minionId })
@MinionsRestriction({ requirePermission: 'WRITE', elementArgIndex: 0, extractMinionIds: (minionId: string) => minionId })
@Post('rescan/{minionId}')
public async rescanMinionStatus(minionId: string): Promise<void> {
return await MinionsBlSingleton.scanMinionStatus(minionId);
Expand Down Expand Up @@ -199,7 +229,7 @@ export class MinionsController extends Controller {
@Security('userAuth')
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@MinionsRestriction({ restrictPermission: 'READ', elementArgIndex: 0, extractMinionIds: (minionId: string) => minionId })
@MinionsRestriction({ requirePermission: 'WRITE', elementArgIndex: 0, extractMinionIds: (minionId: string) => minionId })
@Delete('{minionId}')
public async deleteMinion(minionId: string): Promise<void> {
return await MinionsBlSingleton.deleteMinion(minionId);
Expand Down Expand Up @@ -238,7 +268,7 @@ export class MinionsController extends Controller {
@Security('userAuth')
@Security('adminAuth')
@MinionSanitation()
@MinionsRestriction({ restrictPermission: 'BLOCK', elementArgIndex: 0, extractMinionIds: (minionId: string) => minionId })
@MinionsRestriction({ requirePermission: 'READ', elementArgIndex: 0, extractMinionIds: (minionId: string) => minionId })
@Get('{minionId}')
public async getMinion(minionId: string): Promise<Minion> {
return await MinionsBlSingleton.getMinionById(minionId)
Expand All @@ -252,7 +282,7 @@ export class MinionsController extends Controller {
@Security('userAuth')
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@MinionsRestriction({ restrictPermission: 'READ', elementArgIndex: 1, extractMinionIds: (minionId: string) => minionId })
@MinionsRestriction({ requirePermission: 'WRITE', elementArgIndex: 1, extractMinionIds: (minionId: string) => minionId })
@Put('{minionId}')
public async setMinion(@Request() request, minionId: string, @Body() setStatus: MinionStatus): Promise<void> {
return await MinionsBlSingleton.setMinionStatus(minionId, setStatus, 'user', request.user);
Expand Down
10 changes: 5 additions & 5 deletions backend/src/controllers/timingsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class TimingsController extends Controller {
@Security('userAuth')
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@MinionsRestriction({ restrictPermission: 'BLOCK', elementArgIndex: 0, extractMinionIds: async (timingId: string) => (await TimingsBlSingleton.getTimingById(timingId))?.triggerDirectAction?.minionId })
@MinionsRestriction({ requirePermission: 'READ', elementArgIndex: 0, extractMinionIds: async (timingId: string) => (await TimingsBlSingleton.getTimingById(timingId))?.triggerDirectAction?.minionId })
@Get('{timingId}')
public async getTiming(timingId: string): Promise<Timing> {
return await TimingsBlSingleton.getTimingById(timingId);
Expand All @@ -55,8 +55,8 @@ export class TimingsController extends Controller {
@Security('userAuth')
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@MinionsRestriction({ restrictPermission: 'READ', elementArgIndex: 0, extractMinionIds: async (timingId: string) => (await TimingsBlSingleton.getTimingById(timingId))?.triggerDirectAction?.minionId })
@MinionsRestriction({ restrictPermission: 'READ', elementArgIndex: 1, extractMinionIds: (timing: Timing) => timing.triggerDirectAction?.minionId })
@MinionsRestriction({ requirePermission: 'WRITE', elementArgIndex: 0, extractMinionIds: async (timingId: string) => (await TimingsBlSingleton.getTimingById(timingId))?.triggerDirectAction?.minionId })
@MinionsRestriction({ requirePermission: 'WRITE', elementArgIndex: 1, extractMinionIds: (timing: Timing) => timing.triggerDirectAction?.minionId })
@Put('{timingId}')
public async setTiming(timingId: string, @Body() timing: Timing): Promise<void> {
return await TimingsBlSingleton.SetTiming(timingId, timing);
Expand All @@ -69,7 +69,7 @@ export class TimingsController extends Controller {
@Security('userAuth')
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@MinionsRestriction({ restrictPermission: 'READ', elementArgIndex: 0, extractMinionIds: async (timingId: string) => (await TimingsBlSingleton.getTimingById(timingId))?.triggerDirectAction?.minionId })
@MinionsRestriction({ requirePermission: 'WRITE', elementArgIndex: 0, extractMinionIds: async (timingId: string) => (await TimingsBlSingleton.getTimingById(timingId))?.triggerDirectAction?.minionId })
@Delete('{timingId}')
public async deleteTiming(timingId: string): Promise<void> {
return await TimingsBlSingleton.DeleteTiming(timingId);
Expand All @@ -82,7 +82,7 @@ export class TimingsController extends Controller {
@Security('userAuth')
@Security('adminAuth')
@Response<ErrorResponse>(501, 'Server error')
@MinionsRestriction({ restrictPermission: 'READ', elementArgIndex: 0, extractMinionIds: (timing: Timing) => timing.triggerDirectAction?.minionId })
@MinionsRestriction({ requirePermission: 'WRITE', elementArgIndex: 0, extractMinionIds: (timing: Timing) => timing.triggerDirectAction?.minionId })
@Post()
public async createTiming(@Body() timing: Timing): Promise<void> {
return await TimingsBlSingleton.CreateTiming(timing);
Expand Down
15 changes: 13 additions & 2 deletions backend/src/models/sharedInterfaces.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,17 @@ export declare interface DeviceKind {
isFetchCommandsAvailable: boolean;
}

/**
* Minion timeout countdown information
*/
export declare interface MinionTimeout {
minionId: string;
/** IS countdown active */
active: boolean;
/** EPOCH time when countdown started */
countdownTimestamp: number;
}

/**
* Scopes of authentication, right know in our system there are only 3 scopes.
* admin and user. any API route protect by one of them.
Expand Down Expand Up @@ -597,14 +608,14 @@ export declare interface MinionSetDevice {
/**
* Type of resection of access
*/
export declare type RestrictionType = 'BLOCK' | 'READ' | 'WRITE';
export declare type RestrictionType = 'BLOCK' | 'READ' | 'WRITE';

export declare interface RestrictionItem {
/** The use to restrict */
userEmail: string;
/** The limited access type to grant user */
restrictionType: RestrictionType;
}
}

/**
* Represents a minion in system.
Expand Down
Loading

0 comments on commit e8eef0c

Please sign in to comment.