import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { getToken } from 'src/utility/token'; import { Repository } from 'typeorm'; import { AccessEntity } from './access.entity'; import { IcynetActorEntity } from './icynet.entity'; import { ZoneEntity } from './zone.entity'; @Injectable() export class ManagerService { constructor( @InjectRepository(AccessEntity) private access: Repository, @InjectRepository(ZoneEntity) private zone: Repository, @InjectRepository(IcynetActorEntity) private actors: Repository, ) {} public async getZoneForKey(key: string): Promise { const keyData = await this.getKey(key); if ( !keyData || (keyData.expires_at && keyData.expires_at.getTime() < Date.now()) ) return null; return keyData.zone; } public async getKey(key: string): Promise { return this.access.findOne({ where: { key }, relations: ['zone'], }); } public async getZone(zone: string): Promise { return this.zone.findOne({ where: { zone, }, }); } public async getAllKeys(zone: string): Promise { const obj = await this.getZone(zone); if (!obj) return []; return this.access.find({ where: { zone: { id: obj.id } }, }); } public async getZonesByIcynetUUID(uuid: string): Promise { const actor = await this.actors.findOne({ where: { icynetUUID: uuid }, }); if (!actor) return []; return actor.zones; } /** * Create a new temporary API key for Icy Network user for their domain. * @param icynetUUID Icy Network user UUID * @param domain Zone name * @returns Access key when authorized */ public async createIcynetAccessKey( icynetUUID: string, domain: string, ): Promise { const zones = await this.getZonesByIcynetUUID(icynetUUID); if (!zones.length) return null; const entry = zones.find((zone) => zone.zone === domain); if (!entry) return null; const newObject = { key: getToken(), zone: entry, expires_at: Date.now() + 24 * 60 * 60 * 1000, }; return this.access.save(newObject); } /** * Grant access of a zone to an Icy Network user * @param icynetUUID Icy Network user UUID * @param domain Zone name */ public async authorizeIcynetUser( icynetUUID: string, domain: string, ): Promise { const zone = await this.getZone(domain); if (!zone) return false; const zones = await this.getZonesByIcynetUUID(icynetUUID); if (zones.length && zones.some((item) => item.zone === zone.zone)) { return false; } const actor = await this.actors.findOne({ where: { icynetUUID }, }); actor.zones = [...zones, zone]; await this.actors.save(actor); return true; } /** * Remove access of a zone from an Icy Network user * @param icynetUUID Icy Network user UUID * @param domain Zone name */ public async revokeIcynetUser( icynetUUID: string, domain: string, ): Promise { const zone = await this.getZone(domain); if (!zone) return false; const zones = await this.getZonesByIcynetUUID(icynetUUID); if (zones.length || !zones.some((item) => item.zone === zone.zone)) { return false; } const actor = await this.actors.findOne({ where: { icynetUUID }, }); actor.zones = actor.zones.filter((item) => item.zone !== zone.zone); await this.actors.save(actor); return true; } /** * Create a new API token for accessing a zone. * @param domain Zone to access * @returns Access object */ public async createToken(domain: string): Promise { const zone = await this.getZone(domain); if (!zone) return null; const newObject = { key: getToken(), zone, }; return this.access.save(newObject); } /** * Add a new zone to be managed. * @param domain Zone to add * @returns Zone object */ public async addZone(domain: string): Promise { const zone = await this.getZone(domain); if (zone) return zone; return this.zone.save({ zone: domain, }); } }