-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(events-subscription): allow to instantly refresh permissions whe…
…n they change (#692)
- Loading branch information
Showing
33 changed files
with
2,481 additions
and
1,674 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
/// <reference types="jest-extended" /> | ||
|
||
declare module 'forest-ip-utils'; | ||
declare module 'eventsource'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
packages/forestadmin-client/src/events-subscription/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import EventSource from 'eventsource'; | ||
|
||
import { RefreshEventsHandlerService, ServerEvent, ServerEventType } from './types'; | ||
import { ForestAdminClientOptionsWithDefaults } from '../types'; | ||
|
||
export default class EventsSubscriptionService { | ||
constructor( | ||
private readonly options: ForestAdminClientOptionsWithDefaults, | ||
private readonly refreshEventsHandlerService: RefreshEventsHandlerService, | ||
) {} | ||
|
||
async subscribeEvents(): Promise<void> { | ||
if (!this.options.instantCacheRefresh) { | ||
this.options.logger( | ||
'Debug', | ||
'Event source deactivated.. Use agent option [instantCacheRefresh=true] ' + | ||
'if you want to activate them', | ||
); | ||
|
||
return; | ||
} | ||
|
||
const eventSourceConfig = { | ||
// forest-secret-key act as the credential | ||
withCredentials: false, | ||
headers: { 'forest-secret-key': this.options.envSecret }, | ||
https: { | ||
rejectUnauthorized: process.env.NODE_TLS_REJECT_UNAUTHORIZED !== '0', | ||
}, | ||
}; | ||
const url = new URL('/liana/v4/subscribe-to-events', this.options.forestServerUrl).toString(); | ||
|
||
const source = new EventSource(url, eventSourceConfig); | ||
|
||
source.addEventListener('error', this.onEventError.bind(this)); | ||
|
||
source.addEventListener('open', () => this.onEventOpen()); | ||
|
||
source.addEventListener(ServerEventType.RefreshUsers, async () => | ||
this.refreshEventsHandlerService.refreshUsers(), | ||
); | ||
|
||
source.addEventListener(ServerEventType.RefreshRoles, async () => | ||
this.refreshEventsHandlerService.refreshRoles(), | ||
); | ||
|
||
source.addEventListener(ServerEventType.RefreshRenderings, async (event: ServerEvent) => | ||
this.handleSeverEventRefreshRenderings(event), | ||
); | ||
|
||
source.addEventListener(ServerEventType.RefreshCustomizations, async () => | ||
this.refreshEventsHandlerService.refreshCustomizations(), | ||
); | ||
} | ||
|
||
private async handleSeverEventRefreshRenderings(event: ServerEvent) { | ||
if (!event.data) { | ||
this.options.logger('Debug', 'Server Event - RefreshRenderings missing required data.'); | ||
|
||
return; | ||
} | ||
|
||
const { renderingIds } = JSON.parse(event.data as unknown as string); | ||
await this.refreshEventsHandlerService.refreshRenderings(renderingIds); | ||
} | ||
|
||
private onEventError(event: { type: string; status?: number; message?: string }) { | ||
if (event.status === 502) { | ||
this.options.logger('Debug', 'Server Event - Connection lost'); | ||
|
||
return; | ||
} | ||
|
||
if (event.message) | ||
this.options.logger('Warn', `Server Event - Error: ${JSON.stringify(event)}`); | ||
} | ||
|
||
private onEventOpen() { | ||
this.options.logger( | ||
'Debug', | ||
'Server Event - Open EventSource (SSE) connection with Forest Admin servers', | ||
); | ||
|
||
// Flush all previous data as we could have missed some events | ||
this.refreshEventsHandlerService.refreshEverything(); | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
packages/forestadmin-client/src/events-subscription/native-refresh-events-handler-service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import EventEmitter from 'events'; | ||
|
||
import { RefreshEventsHandlerService } from './types'; | ||
import ActionPermissionService from '../permissions/action-permission'; | ||
import RenderingPermissionService from '../permissions/rendering-permission'; | ||
import UserPermissionService from '../permissions/user-permission'; | ||
|
||
export default class NativeRefreshEventsHandlerService | ||
extends EventEmitter | ||
implements RefreshEventsHandlerService | ||
{ | ||
constructor( | ||
private readonly actionPermissionService: ActionPermissionService, | ||
private readonly usersPermissionService: UserPermissionService, | ||
private readonly renderingPermissionService: RenderingPermissionService, | ||
) { | ||
super(); | ||
} | ||
|
||
public refreshUsers() { | ||
this.usersPermissionService.invalidateCache(); | ||
} | ||
|
||
public refreshRoles() { | ||
this.actionPermissionService.invalidateCache(); | ||
} | ||
|
||
public refreshRenderings(renderingIds: (string | number)[]) { | ||
for (const renderingId of renderingIds) | ||
this.renderingPermissionService.invalidateCache(renderingId); | ||
} | ||
|
||
public refreshCustomizations() { | ||
this.emit('RefreshCustomizations'); | ||
} | ||
|
||
public refreshEverything() { | ||
this.usersPermissionService.invalidateCache(); | ||
this.actionPermissionService.invalidateCache(); | ||
this.renderingPermissionService.invalidateAllCache(); | ||
|
||
// Emit RefreshCustomizations event | ||
this.emit('RefreshCustomizations'); | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
packages/forestadmin-client/src/events-subscription/types.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import EventEmitter from 'events'; | ||
|
||
export enum ServerEventType { | ||
RefreshUsers = 'refresh-users', | ||
RefreshRoles = 'refresh-roles', | ||
RefreshRenderings = 'refresh-renderings', | ||
RefreshCustomizations = 'refresh-customizations', | ||
} | ||
|
||
export type ServerEvent = MessageEvent<{ | ||
type: `${ServerEventType}`; | ||
data?: string; | ||
}>; | ||
|
||
export interface RefreshEventsHandlerService extends EventEmitter { | ||
refreshUsers: () => Promise<void> | void; | ||
refreshRoles: () => Promise<void> | void; | ||
refreshRenderings: (renderingIds: [string | number]) => Promise<void> | void; | ||
refreshCustomizations: () => Promise<void> | void; | ||
|
||
refreshEverything: () => Promise<void> | void; | ||
} |
Oops, something went wrong.