setup unifi wlans
This commit is contained in:
@@ -2,7 +2,7 @@ import { Company } from "../../generated/prisma/client";
|
||||
import { fetchCwCompanyById } from "../modules/cw-utils/fetchCompany";
|
||||
import { fetchCompanyConfigurations } from "../modules/cw-utils/configurations/fetchCompanyConfigurations";
|
||||
import { updateCwInternalCompany } from "../modules/cw-utils/updateCompany";
|
||||
import { Company as CWCompany } from "../types/ConnectWiseTypes";
|
||||
import { Company as CWCompany, Contact } from "../types/ConnectWiseTypes";
|
||||
|
||||
/**
|
||||
* Company Controller
|
||||
@@ -16,9 +16,13 @@ export class CompanyController {
|
||||
public name: string;
|
||||
public readonly cw_Identifier: string;
|
||||
public readonly cw_CompanyId: number;
|
||||
public readonly cw_Data?: CWCompany;
|
||||
public readonly cw_Data?: {
|
||||
company: CWCompany;
|
||||
defaultContact: Contact;
|
||||
allContacts: Contact[];
|
||||
};
|
||||
|
||||
constructor(companyData: Company, cwData?: CWCompany) {
|
||||
constructor(companyData: Company, cwData?: typeof this.cw_Data) {
|
||||
this.id = companyData.id;
|
||||
this.name = companyData.name;
|
||||
this.cw_Identifier = companyData.cw_Identifier;
|
||||
@@ -67,23 +71,66 @@ export class CompanyController {
|
||||
return data;
|
||||
}
|
||||
|
||||
public toJson(opts?: { includeAddress: boolean }) {
|
||||
public toJson(opts?: {
|
||||
includeAddress: boolean;
|
||||
includePrimaryContact: boolean;
|
||||
includeAllContacts?: boolean;
|
||||
}) {
|
||||
return {
|
||||
id: this.id,
|
||||
name: this.name,
|
||||
cw_Identifier: this.cw_Identifier,
|
||||
cw_CompanyId: this.cw_CompanyId,
|
||||
cw_Data: {
|
||||
address: {
|
||||
line1: this.cw_Data?.addressLine1,
|
||||
line2: this.cw_Data?.addressLine2 ?? null,
|
||||
city: this.cw_Data?.city,
|
||||
state: this.cw_Data?.state,
|
||||
zip: this.cw_Data?.zip,
|
||||
country: this.cw_Data?.country
|
||||
? this.cw_Data.country.name
|
||||
: "United States",
|
||||
},
|
||||
address: !opts?.includeAddress
|
||||
? undefined
|
||||
: {
|
||||
line1: this.cw_Data?.company.addressLine1,
|
||||
line2: this.cw_Data?.company.addressLine2 ?? null,
|
||||
city: this.cw_Data?.company.city,
|
||||
state: this.cw_Data?.company.state,
|
||||
zip: this.cw_Data?.company.zip,
|
||||
country: this.cw_Data?.company.country
|
||||
? this.cw_Data.company.country.name
|
||||
: "United States",
|
||||
},
|
||||
primaryContact: !opts?.includePrimaryContact
|
||||
? undefined
|
||||
: {
|
||||
firstName: this.cw_Data?.defaultContact.firstName,
|
||||
lastName: this.cw_Data?.defaultContact.lastName,
|
||||
cwId: this.cw_Data?.defaultContact.id,
|
||||
inactive: this.cw_Data?.defaultContact.inactiveFlag,
|
||||
title: this.cw_Data?.defaultContact.title,
|
||||
phone: this.cw_Data?.defaultContact.defaultPhoneNbr,
|
||||
email: (() => {
|
||||
if (!this.cw_Data?.defaultContact.communicationItems)
|
||||
return null;
|
||||
return (
|
||||
this.cw_Data?.defaultContact.communicationItems.find(
|
||||
(v) => v.type.name === "Email",
|
||||
)?.value ?? null
|
||||
);
|
||||
})(),
|
||||
},
|
||||
allContacts: !opts?.includeAllContacts
|
||||
? undefined
|
||||
: this.cw_Data?.allContacts.map((contact) => ({
|
||||
firstName: contact.firstName,
|
||||
lastName: contact.lastName,
|
||||
cwId: contact.id,
|
||||
inactive: contact.inactiveFlag,
|
||||
title: contact.title,
|
||||
phone: contact.defaultPhoneNbr,
|
||||
email: (() => {
|
||||
if (!contact.communicationItems) return null;
|
||||
return (
|
||||
contact.communicationItems.find(
|
||||
(v) => v.type.name === "Email",
|
||||
)?.value ?? null
|
||||
);
|
||||
})(),
|
||||
})),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -28,11 +28,13 @@ export class CredentialController {
|
||||
public notes: string | null;
|
||||
public readonly typeId: string;
|
||||
public readonly companyId: string;
|
||||
public readonly subCredentialOfId: string | null;
|
||||
public fields: any;
|
||||
|
||||
private _type: CredentialType;
|
||||
private _company: Company;
|
||||
private _secureValues: SecureValue[];
|
||||
private _subCredentials: CredentialController[];
|
||||
|
||||
public readonly createdAt: Date;
|
||||
public updatedAt: Date;
|
||||
@@ -42,6 +44,11 @@ export class CredentialController {
|
||||
type: CredentialType;
|
||||
company: Company;
|
||||
securevalues: SecureValue[];
|
||||
subCredentials?: (Credential & {
|
||||
type: CredentialType;
|
||||
company: Company;
|
||||
securevalues: SecureValue[];
|
||||
})[];
|
||||
},
|
||||
) {
|
||||
this.id = credentialData.id;
|
||||
@@ -49,13 +56,69 @@ export class CredentialController {
|
||||
this.notes = credentialData.notes;
|
||||
this.typeId = credentialData.typeId;
|
||||
this.companyId = credentialData.companyId;
|
||||
this.subCredentialOfId = credentialData.subCredentialOfId;
|
||||
this._type = credentialData.type;
|
||||
this._company = credentialData.company;
|
||||
this._secureValues = credentialData.securevalues;
|
||||
this.fields = (() => {
|
||||
let fields = credentialData.fields as Record<string, any>;
|
||||
this._subCredentials = (credentialData.subCredentials ?? []).map(
|
||||
(sc) => new CredentialController(sc),
|
||||
);
|
||||
this.fields = this._buildFields(credentialData);
|
||||
this.createdAt = credentialData.createdAt;
|
||||
this.updatedAt = credentialData.updatedAt;
|
||||
}
|
||||
|
||||
return (this._type.fields! as any).map((f: any) => ({
|
||||
/**
|
||||
* Build Fields
|
||||
*
|
||||
* Maps raw credential data into a structured fields array.
|
||||
* - Regular credentials: maps through the type's field definitions.
|
||||
* - Multi-credential fields: returns sub-credential references and subField definitions.
|
||||
* - Sub-credentials: returns raw field data (validated against subFields, not the type's top-level fields).
|
||||
*/
|
||||
private _buildFields(credentialData: Credential) {
|
||||
const raw = credentialData.fields as Record<string, any>;
|
||||
const typeFields = this._type.fields as any as CredentialTypeField[];
|
||||
|
||||
// Sub-credentials: their fields don't match the type's top-level definitions,
|
||||
// so we return a simple id/value list built from raw JSON + secure values.
|
||||
if (credentialData.subCredentialOfId) {
|
||||
const result: any[] = [];
|
||||
|
||||
// Collect field IDs that have secure values
|
||||
const secureFieldIds = new Set(this._secureValues.map((sv) => sv.name));
|
||||
|
||||
// Non-secure fields from JSON
|
||||
Object.entries(raw).forEach(([fieldId, value]) => {
|
||||
if (!secureFieldIds.has(fieldId)) {
|
||||
result.push({ id: fieldId, value, secure: false });
|
||||
}
|
||||
});
|
||||
|
||||
// Secure value references
|
||||
this._secureValues.forEach((sv) => {
|
||||
result.push({ id: sv.name, value: `secure-${sv.id}`, secure: true });
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Regular (parent) credential: map through type field definitions
|
||||
return typeFields.map((f: any) => {
|
||||
if (f.valueType === ValueType.MULTI_CREDENTIAL) {
|
||||
const subCredIds: string[] = raw[f.id] ?? [];
|
||||
return {
|
||||
id: f.id,
|
||||
name: f.name,
|
||||
secure: false,
|
||||
required: f.required,
|
||||
valueType: f.valueType,
|
||||
subFields: f.subFields ?? [],
|
||||
subCredentialIds: subCredIds,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
id: f.id,
|
||||
name: f.name,
|
||||
secure: f.secure,
|
||||
@@ -63,13 +126,9 @@ export class CredentialController {
|
||||
valueType: f.valueType as ValueType,
|
||||
value: f.secure
|
||||
? `secure-${this._secureValues.find((sv) => sv.name === f.id)?.id}`
|
||||
: fields[f.id],
|
||||
}));
|
||||
|
||||
return fields;
|
||||
})();
|
||||
this.createdAt = credentialData.createdAt;
|
||||
this.updatedAt = credentialData.updatedAt;
|
||||
: raw[f.id],
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,6 +210,19 @@ export class CredentialController {
|
||||
fieldsObject[field.fieldId] = field.value;
|
||||
});
|
||||
|
||||
// Preserve multi-credential field values (sub-credential ID arrays)
|
||||
const currentFields = (await prisma.credential.findFirst({
|
||||
where: { id: this.id },
|
||||
select: { fields: true },
|
||||
}))!.fields as Record<string, any>;
|
||||
|
||||
const typeFields = this._type.fields as any as CredentialTypeField[];
|
||||
typeFields.forEach((f) => {
|
||||
if (f.valueType === ValueType.MULTI_CREDENTIAL && currentFields[f.id]) {
|
||||
fieldsObject[f.id] = currentFields[f.id];
|
||||
}
|
||||
});
|
||||
|
||||
// Update the credential with non-secure fields
|
||||
const updatedCredential = await prisma.credential.update({
|
||||
where: { id: this.id },
|
||||
@@ -313,13 +385,14 @@ export class CredentialController {
|
||||
* @param opts - Options to change the output
|
||||
* @returns - An object that is JSON friendly
|
||||
*/
|
||||
toJson(opts?: { includeSecureValues?: boolean }) {
|
||||
toJson(opts?: { includeSecureValues?: boolean }): Record<string, any> {
|
||||
return {
|
||||
id: this.id,
|
||||
name: this.name,
|
||||
notes: this.notes,
|
||||
typeId: this.typeId,
|
||||
companyId: this.companyId,
|
||||
subCredentialOfId: this.subCredentialOfId ?? undefined,
|
||||
fields: this.fields,
|
||||
type: {
|
||||
id: this._type.id,
|
||||
@@ -331,6 +404,10 @@ export class CredentialController {
|
||||
id: this._company.id,
|
||||
name: this._company.name,
|
||||
},
|
||||
subCredentials:
|
||||
this._subCredentials.length > 0
|
||||
? this._subCredentials.map((sc) => sc.toJson(opts))
|
||||
: undefined,
|
||||
secureFieldIds: opts?.includeSecureValues
|
||||
? this._secureValues.map((sv) => sv.name)
|
||||
: undefined,
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { UnifiSite } from "../../generated/prisma/client";
|
||||
|
||||
/**
|
||||
* UniFi Site Controller
|
||||
*
|
||||
* Handles formatting and presentation of UniFi site data.
|
||||
*/
|
||||
export class UnifiSiteController {
|
||||
public readonly id: string;
|
||||
public readonly name: string;
|
||||
public readonly siteId: string;
|
||||
public readonly companyId: string | null;
|
||||
|
||||
constructor(site: UnifiSite) {
|
||||
this.id = site.id;
|
||||
this.name = site.name;
|
||||
this.siteId = site.siteId;
|
||||
this.companyId = site.companyId;
|
||||
}
|
||||
|
||||
public toJson() {
|
||||
return {
|
||||
id: this.id,
|
||||
name: this.name,
|
||||
siteId: this.siteId,
|
||||
companyId: this.companyId,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user