Keys auf SSE umgestellt
This commit is contained in:
@@ -15,6 +15,7 @@ import { CacheInterceptor, CacheModule } from '@nestjs/cache-manager';
|
|||||||
import { APP_INTERCEPTOR } from '@nestjs/core';
|
import { APP_INTERCEPTOR } from '@nestjs/core';
|
||||||
import { MailModule } from './modules/mail/mail.module';
|
import { MailModule } from './modules/mail/mail.module';
|
||||||
import { LogModule } from './modules/log/log.module';
|
import { LogModule } from './modules/log/log.module';
|
||||||
|
import { SseModule } from './modules/realtime/sse/sse.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
@@ -33,6 +34,7 @@ import { LogModule } from './modules/log/log.module';
|
|||||||
SystemModule,
|
SystemModule,
|
||||||
MailModule,
|
MailModule,
|
||||||
LogModule,
|
LogModule,
|
||||||
|
SseModule
|
||||||
],
|
],
|
||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [
|
providers: [
|
||||||
|
|||||||
@@ -7,48 +7,57 @@ import {
|
|||||||
Post,
|
Post,
|
||||||
Put,
|
Put,
|
||||||
Req,
|
Req,
|
||||||
|
Sse,
|
||||||
UseGuards,
|
UseGuards,
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { KeyService } from './key.service';
|
import { KeyService } from './key.service';
|
||||||
import { AuthenticatedRequest } from 'src/model/interface/authenticated-request.interface';
|
import { AuthenticatedRequest } from 'src/model/interface/authenticated-request.interface';
|
||||||
import { AuthGuard } from 'src/core/guards/auth.guard';
|
import { AuthGuard } from 'src/core/guards/auth.guard';
|
||||||
import { Key } from 'src/model/entitites';
|
import { Key } from 'src/model/entitites';
|
||||||
|
import { interval, map, Observable } from 'rxjs';
|
||||||
|
|
||||||
|
|
||||||
@UseGuards(AuthGuard)
|
|
||||||
@Controller('key')
|
@Controller('key')
|
||||||
export class KeyController {
|
export class KeyController {
|
||||||
constructor(private service: KeyService) {}
|
constructor(private service: KeyService) {}
|
||||||
|
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
@Get()
|
@Get()
|
||||||
getKeys(@Req() req: AuthenticatedRequest) {
|
getKeys(@Req() req: AuthenticatedRequest) {
|
||||||
return this.service.getUsersKeys(req.user);
|
return this.service.getUsersKeys(req.user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
@Get('lost')
|
@Get('lost')
|
||||||
getLostKeys(@Req() req: AuthenticatedRequest) {
|
getLostKeys(@Req() req: AuthenticatedRequest) {
|
||||||
return this.service.getLostKeys(req.user);
|
return this.service.getLostKeys(req.user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
@Post()
|
@Post()
|
||||||
postKey(@Req() req: AuthenticatedRequest, @Body() key: Key) {
|
postKey(@Req() req: AuthenticatedRequest, @Body() key: Key) {
|
||||||
return this.service.createKey(req.user, key);
|
return this.service.createKey(req.user, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
@Put()
|
@Put()
|
||||||
updateKey(@Req() req: AuthenticatedRequest, @Body() key: Key) {
|
updateKey(@Req() req: AuthenticatedRequest, @Body() key: Key) {
|
||||||
return this.service.updateKey(req.user, key);
|
return this.service.updateKey(req.user, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
@Put(':id/restore')
|
@Put(':id/restore')
|
||||||
restoreKey(@Req() req: AuthenticatedRequest, @Param('id') id: string) {
|
restoreKey(@Req() req: AuthenticatedRequest, @Param('id') id: string) {
|
||||||
return this.service.restoreKey(req.user, id);
|
return this.service.restoreKey(req.user, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
@Delete(':id')
|
@Delete(':id')
|
||||||
deleteKey(@Req() req: AuthenticatedRequest, @Param('id') id: string) {
|
deleteKey(@Req() req: AuthenticatedRequest, @Param('id') id: string) {
|
||||||
return this.service.deleteKey(req.user, id);
|
return this.service.deleteKey(req.user, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
@Post(':id/handover')
|
@Post(':id/handover')
|
||||||
handoutKey(
|
handoutKey(
|
||||||
@Req() req: AuthenticatedRequest,
|
@Req() req: AuthenticatedRequest,
|
||||||
@@ -58,11 +67,13 @@ export class KeyController {
|
|||||||
return this.service.handoverKey(req.user, body, id);
|
return this.service.handoverKey(req.user, body, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
@Get(':id/handover')
|
@Get(':id/handover')
|
||||||
getKeyHandouts(@Req() req: AuthenticatedRequest, @Param('id') id: string) {
|
getKeyHandouts(@Req() req: AuthenticatedRequest, @Param('id') id: string) {
|
||||||
return this.service.getKeyHandovers(req.user, id);
|
return this.service.getKeyHandovers(req.user, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
@Get('archive')
|
@Get('archive')
|
||||||
getArchive(@Req() req: AuthenticatedRequest) {
|
getArchive(@Req() req: AuthenticatedRequest) {
|
||||||
return this.service.getDeletedKeys(req.user);
|
return this.service.getDeletedKeys(req.user);
|
||||||
|
|||||||
@@ -6,10 +6,11 @@ import { AuthModule } from '../auth/auth.module';
|
|||||||
import { SharedServiceModule } from 'src/shared/service/shared.service.module';
|
import { SharedServiceModule } from 'src/shared/service/shared.service.module';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { MailModule } from '../mail/mail.module';
|
import { MailModule } from '../mail/mail.module';
|
||||||
|
import { SseModule } from '../realtime/sse/sse.module';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
controllers: [KeyController],
|
controllers: [KeyController],
|
||||||
providers: [KeyService, ConfigService],
|
providers: [KeyService, ConfigService],
|
||||||
imports: [DatabaseModule, AuthModule, SharedServiceModule, MailModule],
|
imports: [DatabaseModule, AuthModule, SharedServiceModule, MailModule, SseModule],
|
||||||
})
|
})
|
||||||
export class KeyModule {}
|
export class KeyModule {}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { FindOperator, IsNull, Not } from 'typeorm';
|
|||||||
import { faker } from '@faker-js/faker';
|
import { faker } from '@faker-js/faker';
|
||||||
import { ConfigService } from '@nestjs/config';
|
import { ConfigService } from '@nestjs/config';
|
||||||
import { MailService } from '../mail/mail.service';
|
import { MailService } from '../mail/mail.service';
|
||||||
|
import { SseService } from '../realtime/sse/sse.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class KeyService {
|
export class KeyService {
|
||||||
@@ -23,7 +24,10 @@ export class KeyService {
|
|||||||
private readonly helper: HelperService,
|
private readonly helper: HelperService,
|
||||||
private readonly configService: ConfigService,
|
private readonly configService: ConfigService,
|
||||||
private readonly mailService: MailService,
|
private readonly mailService: MailService,
|
||||||
) {}
|
private readonly sseService: SseService
|
||||||
|
) {
|
||||||
|
console.log("INIT KEYSERVICE")
|
||||||
|
}
|
||||||
|
|
||||||
get isDevelopMode(): boolean {
|
get isDevelopMode(): boolean {
|
||||||
return (this.configService.get('DEVELOP_MODE') || '').toLowerCase() == 'true';
|
return (this.configService.get('DEVELOP_MODE') || '').toLowerCase() == 'true';
|
||||||
@@ -87,7 +91,19 @@ export class KeyService {
|
|||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.keyrepository.save(this.keyrepository.create(key));
|
const saved = await this.keyrepository.save(this.keyrepository.create(key));
|
||||||
|
|
||||||
|
this.sendKeysToSSE(saved);
|
||||||
|
return saved;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private async sendKeysToSSE(key: Key) {
|
||||||
|
const system = await this.helper.getSystemOfKey(key)
|
||||||
|
for (let manager of system.managers) {
|
||||||
|
const keys = await this.getUsersKeys(manager);
|
||||||
|
this.sseService.sendKeysToUsers(manager.id, keys)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -129,7 +145,6 @@ export class KeyService {
|
|||||||
where: { id: keyID },
|
where: { id: keyID },
|
||||||
relations: [ 'cylinder', 'cylinder.system', 'cylinder.system.managers', 'cylinder.system.managers.settings' ]
|
relations: [ 'cylinder', 'cylinder.system', 'cylinder.system.managers', 'cylinder.system.managers.settings' ]
|
||||||
});
|
});
|
||||||
console.log(managerOb.cylinder[0].system.managers)
|
|
||||||
managerOb.cylinder[0].system.managers.filter(m => m.settings.sendSystemUpdateMails).forEach(m => {
|
managerOb.cylinder[0].system.managers.filter(m => m.settings.sendSystemUpdateMails).forEach(m => {
|
||||||
this.mailService.sendKeyHandoutMail({ to: m, key, handoutAction: res })
|
this.mailService.sendKeyHandoutMail({ to: m, key, handoutAction: res })
|
||||||
})
|
})
|
||||||
@@ -137,7 +152,7 @@ export class KeyService {
|
|||||||
} catch (e){
|
} catch (e){
|
||||||
console.log(e)
|
console.log(e)
|
||||||
}
|
}
|
||||||
|
this.sendKeysToSSE(key);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,18 +188,22 @@ export class KeyService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async createKey(user: User, key: any) {
|
async createKey(user: User, key: any): Promise<Key> {
|
||||||
const k = await this.keyrepository.save(this.keyrepository.create(key));
|
const k = await this.keyrepository.save(this.keyrepository.create(key)) as any as Key;
|
||||||
this.activityService.logKeyCreated(user, key, key.cylinder[0].system);
|
this.activityService.logKeyCreated(user, key, key.cylinder[0].system);
|
||||||
|
this.sendKeysToSSE(k as any)
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteKey(user: User, id: string) {
|
async deleteKey(user: User, id: string): Promise<Key> {
|
||||||
const key = await this.keyrepository.findOneOrFail({
|
const key = await this.keyrepository.findOneOrFail({
|
||||||
where: { id, cylinder: { system: { managers: { id: user.id } } } },
|
where: { id, cylinder: { system: { managers: { id: user.id } } } },
|
||||||
});
|
});
|
||||||
await this.activityService.logDeleteKey(user, key);
|
await this.activityService.logDeleteKey(user, key);
|
||||||
return this.keyrepository.softRemove(key);
|
const k = await this.keyrepository.softRemove(key);
|
||||||
|
this.sendKeysToSSE(k)
|
||||||
|
return k;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getDeletedKeys(user: User) {
|
getDeletedKeys(user: User) {
|
||||||
@@ -198,7 +217,7 @@ export class KeyService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async restoreKey(user: User, keyID: string) {
|
async restoreKey(user: User, keyID: string): Promise<Key> {
|
||||||
|
|
||||||
const key = await this.keyrepository.findOneOrFail({
|
const key = await this.keyrepository.findOneOrFail({
|
||||||
where: { cylinder: { system: { managers: { id: user.id } } }, id: keyID },
|
where: { cylinder: { system: { managers: { id: user.id } } }, id: keyID },
|
||||||
@@ -207,6 +226,8 @@ export class KeyService {
|
|||||||
key.deletedAt = null;
|
key.deletedAt = null;
|
||||||
await this.activityService.logKeyRestored(user, key);
|
await this.activityService.logKeyRestored(user, key);
|
||||||
await this.helper.deleteKeyArchiveCache();
|
await this.helper.deleteKeyArchiveCache();
|
||||||
return this.keyrepository.save(key);
|
const k = await this.keyrepository.save(key);
|
||||||
|
this.sendKeysToSSE(k)
|
||||||
|
return k;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
21
api/src/modules/realtime/sse/sse-ticket.service.ts
Normal file
21
api/src/modules/realtime/sse/sse-ticket.service.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SseTicketService {
|
||||||
|
private userTickets: Map<string, {userId: string, used: boolean}> = new Map();
|
||||||
|
|
||||||
|
generateTicket(userId: string): {ticket: string } {
|
||||||
|
const ticket = crypto.randomUUID();
|
||||||
|
|
||||||
|
this.userTickets.set(ticket, { userId, used: false });
|
||||||
|
|
||||||
|
return {ticket};
|
||||||
|
}
|
||||||
|
|
||||||
|
getUserIdToTicket(ticketId: string): string {
|
||||||
|
if (!this.userTickets.has(ticketId)) { return null; }
|
||||||
|
const ticket = this.userTickets.get(ticketId);
|
||||||
|
if (!ticket || ticket.used) { return null; }
|
||||||
|
return ticket.userId;
|
||||||
|
}
|
||||||
|
}
|
||||||
18
api/src/modules/realtime/sse/sse.controller.spec.ts
Normal file
18
api/src/modules/realtime/sse/sse.controller.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { SseController } from './sse.controller';
|
||||||
|
|
||||||
|
describe('SseController', () => {
|
||||||
|
let controller: SseController;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
controllers: [SseController],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
controller = module.get<SseController>(SseController);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(controller).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
38
api/src/modules/realtime/sse/sse.controller.ts
Normal file
38
api/src/modules/realtime/sse/sse.controller.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import { Controller, Get, Param, Query, Req, Sse, UnauthorizedException, UseGuards } from '@nestjs/common';
|
||||||
|
import { AuthenticatedRequest } from 'src/model/interface/authenticated-request.interface';
|
||||||
|
import { SseTicketService } from './sse-ticket.service';
|
||||||
|
import { AuthGuard } from 'src/core/guards/auth.guard';
|
||||||
|
import { Observable, interval, map } from 'rxjs';
|
||||||
|
import { KeyService } from 'src/modules/key/key.service';
|
||||||
|
import { AuthService } from 'src/modules/auth/auth.service';
|
||||||
|
import { User } from 'src/model/entitites';
|
||||||
|
import { UserService } from 'src/modules/user/user.service';
|
||||||
|
import { SseService } from './sse.service';
|
||||||
|
|
||||||
|
@Controller('sse')
|
||||||
|
export class SseController {
|
||||||
|
|
||||||
|
constructor(private ticketService: SseTicketService, private sseService: SseService, private userService: UserService) {}
|
||||||
|
|
||||||
|
@UseGuards(AuthGuard)
|
||||||
|
@Get('ticket')
|
||||||
|
getTicket(@Req() req: AuthenticatedRequest) {
|
||||||
|
return this.ticketService.generateTicket(req.user.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Sse('key')
|
||||||
|
async sse(@Query('ticket') ticket: string): Promise<Observable<any>> {
|
||||||
|
const userId = this.ticketService.getUserIdToTicket(ticket);
|
||||||
|
if (!userId) throw new UnauthorizedException('Invalid/expired ticket');
|
||||||
|
const user = await this.getUserToId(userId);
|
||||||
|
if (!userId) throw new UnauthorizedException('Invalid/expired ticket');
|
||||||
|
|
||||||
|
|
||||||
|
return this.sseService.register(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getUserToId(userId: string): Promise<User> {
|
||||||
|
const user = await this.userService.getUserById(userId);
|
||||||
|
return Promise.resolve(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
17
api/src/modules/realtime/sse/sse.module.ts
Normal file
17
api/src/modules/realtime/sse/sse.module.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { SseController } from './sse.controller';
|
||||||
|
import { DatabaseModule } from 'src/shared/database/database.module';
|
||||||
|
import { SseTicketService } from './sse-ticket.service';
|
||||||
|
import { AuthModule } from 'src/modules/auth/auth.module';
|
||||||
|
import { SharedServiceModule } from 'src/shared/service/shared.service.module';
|
||||||
|
import { MailModule } from 'src/modules/mail/mail.module';
|
||||||
|
import { UserService } from 'src/modules/user/user.service';
|
||||||
|
import { SseService } from './sse.service';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
controllers: [SseController],
|
||||||
|
imports: [DatabaseModule, AuthModule, SharedServiceModule, MailModule],
|
||||||
|
providers: [SseTicketService, UserService, SseService],
|
||||||
|
exports: [SseService]
|
||||||
|
})
|
||||||
|
export class SseModule {}
|
||||||
18
api/src/modules/realtime/sse/sse.service.spec.ts
Normal file
18
api/src/modules/realtime/sse/sse.service.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { SseService } from './sse.service';
|
||||||
|
|
||||||
|
describe('SseService', () => {
|
||||||
|
let service: SseService;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
providers: [SseService],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
service = module.get<SseService>(SseService);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(service).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
22
api/src/modules/realtime/sse/sse.service.ts
Normal file
22
api/src/modules/realtime/sse/sse.service.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { Injectable,MessageEvent } from '@nestjs/common';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import { Key } from 'src/model/entitites';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class SseService {
|
||||||
|
private clients = new Map<string, Subject<MessageEvent>>();
|
||||||
|
|
||||||
|
sendKeysToUsers(userId: string, keys: Key[]) {
|
||||||
|
try {
|
||||||
|
const sub = this.clients.get(userId);
|
||||||
|
if (!sub) { return; }
|
||||||
|
sub.next({ data: keys })
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
|
||||||
|
register(userId: string) {
|
||||||
|
const subj = new Subject<MessageEvent>();
|
||||||
|
this.clients.set(userId, subj);
|
||||||
|
return subj;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -67,4 +67,8 @@ export class UserService {
|
|||||||
updateSettings(settings: UserSettings) {
|
updateSettings(settings: UserSettings) {
|
||||||
return this.userSettingsRepository.save(settings);
|
return this.userSettingsRepository.save(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getUserById(id: string) {
|
||||||
|
return this.userRepo.findOneBy({ id })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ export class HelperService {
|
|||||||
async getSystemOfKey(key: Key): Promise<KeySystem> {
|
async getSystemOfKey(key: Key): Promise<KeySystem> {
|
||||||
const k = await this.keyRepo.findOne({
|
const k = await this.keyRepo.findOne({
|
||||||
where: { id: key.id },
|
where: { id: key.id },
|
||||||
relations: ['cylinder', 'cylinder.system'],
|
relations: ['cylinder', 'cylinder.system', 'cylinder.system.managers'],
|
||||||
withDeleted: true,
|
withDeleted: true,
|
||||||
});
|
});
|
||||||
this.cache()
|
this.cache()
|
||||||
|
|||||||
@@ -25,7 +25,11 @@ export class ApiService {
|
|||||||
public settings: BehaviorSubject<Object> = new BehaviorSubject<Object>(null!);
|
public settings: BehaviorSubject<Object> = new BehaviorSubject<Object>(null!);
|
||||||
|
|
||||||
|
|
||||||
constructor() { }
|
constructor() {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.setupKeyFeed();
|
||||||
|
}, 2000)
|
||||||
|
}
|
||||||
|
|
||||||
getMe(): Promise<IUser> {
|
getMe(): Promise<IUser> {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
@@ -87,7 +91,7 @@ export class ApiService {
|
|||||||
).subscribe({
|
).subscribe({
|
||||||
next: (key: IKey) => resolve(key),
|
next: (key: IKey) => resolve(key),
|
||||||
error: () => resolve(null),
|
error: () => resolve(null),
|
||||||
complete: () => { this.refreshKeys(); }
|
// complete: () => { this.refreshKeys(); }
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -424,4 +428,29 @@ export class ApiService {
|
|||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async setupKeyFeed() {
|
||||||
|
const ticket = await this.getSSETicket();
|
||||||
|
|
||||||
|
console.log(ticket)
|
||||||
|
const sseSource = new EventSource('api/sse/key?ticket=' + ticket);
|
||||||
|
sseSource.addEventListener('message', (e: MessageEvent<string>) => {
|
||||||
|
console.log(e.data)
|
||||||
|
this.keys.next(JSON.parse(e.data))
|
||||||
|
})
|
||||||
|
sseSource.addEventListener('error', (error) => {
|
||||||
|
console.error(error)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private getSSETicket() {
|
||||||
|
return new Promise<string>(resolve => {
|
||||||
|
this.http.get<{ ticket: string }>('api/sse/ticket').subscribe({
|
||||||
|
next: (ticket) => {
|
||||||
|
return resolve(ticket.ticket)
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user