icydns/src/modules/objects/manager/manager.service.ts

172 lines
4.2 KiB
TypeScript

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<AccessEntity>,
@InjectRepository(ZoneEntity)
private zone: Repository<ZoneEntity>,
@InjectRepository(IcynetActorEntity)
private actors: Repository<IcynetActorEntity>,
) {}
public async getZoneForKey(key: string): Promise<ZoneEntity> {
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<AccessEntity> {
return this.access.findOne({
where: { key },
relations: ['zone'],
});
}
public async getZone(zone: string): Promise<ZoneEntity> {
return this.zone.findOne({
where: {
zone,
},
});
}
public async getAllKeys(zone: string): Promise<AccessEntity[]> {
const obj = await this.getZone(zone);
if (!obj) return [];
return this.access.find({
where: { zone: { id: obj.id } },
});
}
public async getZonesByIcynetUUID(uuid: string): Promise<ZoneEntity[]> {
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<AccessEntity> {
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<boolean> {
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<boolean> {
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<AccessEntity> {
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<ZoneEntity> {
const zone = await this.getZone(domain);
if (zone) return zone;
return this.zone.save({
zone: domain,
});
}
}