diff --git a/resources/scripts/api/admin/egg.ts b/resources/scripts/api/admin/egg.ts new file mode 100644 index 000000000..3449eb2c7 --- /dev/null +++ b/resources/scripts/api/admin/egg.ts @@ -0,0 +1,24 @@ +import { Model, UUID } from '@/api/admin/index'; + +export interface Egg extends Model { + id: string; + uuid: UUID; + relationships: { + variables?: EggVariable[]; + }; +} + +export interface EggVariable extends Model { + id: number; + eggId: number; + name: string; + description: string; + environmentVariable: string; + defaultValue: string; + isUserViewable: boolean; + isUserEditable: boolean; + isRequired: boolean; + rules: string; + createdAt: Date; + updatedAt: Date; +} diff --git a/resources/scripts/api/admin/location.ts b/resources/scripts/api/admin/location.ts new file mode 100644 index 000000000..82ff394f8 --- /dev/null +++ b/resources/scripts/api/admin/location.ts @@ -0,0 +1,13 @@ +import { Model } from '@/api/admin/index'; +import { Node } from '@/api/admin/node'; + +export interface Location extends Model { + id: number; + short: string; + long: string; + createdAt: Date; + updatedAt: Date; + relationships: { + nodes?: Node[]; + }; +} diff --git a/resources/scripts/api/admin/node.ts b/resources/scripts/api/admin/node.ts new file mode 100644 index 000000000..9bc333541 --- /dev/null +++ b/resources/scripts/api/admin/node.ts @@ -0,0 +1,67 @@ +import { Model, UUID, WithRelationships, withRelationships } from '@/api/admin/index'; +import { Location } from '@/api/admin/location'; +import http from '@/api/http'; +import { AdminTransformers } from '@/api/admin/transformers'; +import { Server } from '@/api/admin/server'; + +interface NodePorts { + http: { + listen: number; + public: number; + }; + sftp: { + listen: number; + public: number; + }; +} + +export interface Allocation extends Model { + id: number; + ip: string; + port: number; + alias: string | null; + isAssigned: boolean; + relationships: { + node?: Node; + server?: Server | null; + }; +} + +export interface Node extends Model { + id: number; + uuid: UUID; + isPublic: boolean; + locationId: number; + databaseHostId: number; + name: string; + description: string | null; + fqdn: string; + ports: NodePorts; + scheme: 'http' | 'https'; + isBehindProxy: boolean; + isMaintenanceMode: boolean; + memory: number; + memoryOverallocate: number; + disk: number; + diskOverallocate: number; + uploadSize: number; + daemonBase: string; + createdAt: Date; + updatedAt: Date; + relationships: { + location?: Location; + }; +} + +/** + * Gets a single node and returns it. + */ +export const getNode = async (id: string | number): Promise> => { + const { data } = await http.get(`/api/application/nodes/${id}`, { + params: { + includes: [ 'location' ], + }, + }); + + return withRelationships(AdminTransformers.toNode(data.data), 'location'); +}; diff --git a/resources/scripts/api/admin/server.ts b/resources/scripts/api/admin/server.ts index fd45aa0bb..b65f50636 100644 --- a/resources/scripts/api/admin/server.ts +++ b/resources/scripts/api/admin/server.ts @@ -1,14 +1,12 @@ -import { Allocation } from '@/api/admin/nodes/getAllocations'; -import { Egg } from '@/api/admin/eggs/getEgg'; -import { User } from '@/api/admin/users/getUsers'; -import { Node } from '@/api/admin/nodes/getNodes'; -import { rawDataToServer, ServerVariable } from '@/api/admin/servers/getServers'; import useSWR, { SWRResponse } from 'swr'; import { AxiosError } from 'axios'; import { useRouteMatch } from 'react-router-dom'; import http from '@/api/http'; import { Model, UUID, withRelationships, WithRelationships } from '@/api/admin/index'; import { AdminTransformers } from '@/api/admin/transformers'; +import { Allocation, Node } from '@/api/admin/node'; +import { User } from '@/api/admin/user'; +import { Egg, EggVariable } from '@/api/admin/egg'; /** * Defines the limits for a server that exists on the Panel. @@ -23,6 +21,10 @@ interface ServerLimits { oomDisabled: boolean; } +export interface ServerVariable extends EggVariable { + serverValue: string; +} + /** * Defines a single server instance that is returned from the Panel's admin * API endpoints. diff --git a/resources/scripts/api/admin/transformers.ts b/resources/scripts/api/admin/transformers.ts index d3d21a1ab..795a0f441 100644 --- a/resources/scripts/api/admin/transformers.ts +++ b/resources/scripts/api/admin/transformers.ts @@ -1,11 +1,10 @@ /* eslint-disable camelcase */ -import { Server } from '@/api/admin/server'; +import { Allocation, Node } from '@/api/admin/node'; +import { Server, ServerVariable } from '@/api/admin/server'; import { FractalResponseData, FractalResponseList } from '@/api/http'; -import { rawDataToAllocation } from '@/api/admin/nodes/getAllocations'; -import { rawDataToEgg } from '@/api/admin/eggs/getEgg'; -import { rawDataToNode } from '@/api/admin/nodes/getNodes'; -import { rawDataToUser } from '@/api/admin/users/getUsers'; -import { rawDataToServerVariable } from '@/api/admin/servers/getServers'; +import { User, UserRole } from '@/api/admin/user'; +import { Location } from '@/api/admin/location'; +import { Egg, EggVariable } from '@/api/admin/egg'; const isList = (data: FractalResponseList | FractalResponseData): data is FractalResponseList => data.object === 'list'; @@ -45,12 +44,129 @@ export class AdminTransformers { createdAt: new Date(attributes.created_at), updatedAt: new Date(attributes.updated_at), relationships: { - allocations: transform(allocations as FractalResponseList | undefined, rawDataToAllocation), - egg: transform(egg as FractalResponseData | undefined, rawDataToEgg), - node: transform(node as FractalResponseData | undefined, rawDataToNode), - user: transform(user as FractalResponseData | undefined, rawDataToUser), - variables: transform(variables as FractalResponseList | undefined, rawDataToServerVariable), + allocations: transform(allocations as FractalResponseList | undefined, this.toAllocation), + egg: transform(egg as FractalResponseData | undefined, this.toEgg), + node: transform(node as FractalResponseData | undefined, this.toNode), + user: transform(user as FractalResponseData | undefined, this.toUser), + variables: transform(variables as FractalResponseList | undefined, this.toServerEggVariable), }, }; }; + + static toNode = ({ attributes }: FractalResponseData): Node => { + return { + id: attributes.id, + uuid: attributes.uuid, + isPublic: attributes.public, + locationId: attributes.location_id, + databaseHostId: attributes.database_host_id, + name: attributes.name, + description: attributes.description, + fqdn: attributes.fqdn, + ports: { + http: { + public: attributes.publicPortHttp, + listen: attributes.listenPortHttp, + }, + sftp: { + public: attributes.publicPortSftp, + listen: attributes.listenPortSftp, + }, + }, + scheme: attributes.scheme, + isBehindProxy: attributes.behindProxy, + isMaintenanceMode: attributes.maintenance_mode, + memory: attributes.memory, + memoryOverallocate: attributes.memory_overallocate, + disk: attributes.disk, + diskOverallocate: attributes.disk_overallocate, + uploadSize: attributes.upload_size, + daemonBase: attributes.daemonBase, + createdAt: new Date(attributes.created_at), + updatedAt: new Date(attributes.updated_at), + relationships: { + location: transform(attributes.relationships!.location as FractalResponseData, this.toLocation), + }, + }; + }; + + static toUserRole = ({ attributes }: FractalResponseData): UserRole => ({ + id: attributes.id, + name: attributes.name, + description: attributes.description, + relationships: {}, + }); + + static toUser = ({ attributes }: FractalResponseData): User => { + return { + id: attributes.id, + uuid: attributes.uuid, + externalId: attributes.external_id, + username: attributes.username, + email: attributes.email, + language: attributes.language, + adminRoleId: attributes.adminRoleId || null, + roleName: attributes.role_name, + isRootAdmin: attributes.root_admin, + isUsingTwoFactor: attributes['2fa'] || false, + avatarUrl: attributes.avatar_url, + createdAt: new Date(attributes.created_at), + updatedAt: new Date(attributes.updated_at), + relationships: { + role: transform(attributes.relationships?.role as FractalResponseData, this.toUserRole) || null, + }, + }; + }; + + static toLocation = ({ attributes }: FractalResponseData): Location => ({ + id: attributes.id, + short: attributes.short, + long: attributes.long, + createdAt: new Date(attributes.created_at), + updatedAt: new Date(attributes.updated_at), + relationships: { + nodes: transform(attributes.relationships?.node as FractalResponseList, this.toNode), + }, + }); + + static toEgg = ({ attributes }: FractalResponseData): Egg => ({ + id: attributes.id, + uuid: attributes.uuid, + relationships: { + variables: transform(attributes.relationships?.variables as FractalResponseList, this.toEggVariable), + }, + }); + + static toEggVariable = ({ attributes }: FractalResponseData): EggVariable => ({ + id: attributes.id, + eggId: attributes.egg_id, + name: attributes.name, + description: attributes.description, + environmentVariable: attributes.env_variable, + defaultValue: attributes.default_value, + isUserViewable: attributes.user_viewable, + isUserEditable: attributes.user_editable, + isRequired: attributes.required, + rules: attributes.rules, + createdAt: new Date(attributes.created_at), + updatedAt: new Date(attributes.updated_at), + relationships: {}, + }); + + static toServerEggVariable = (data: FractalResponseData): ServerVariable => ({ + ...this.toEggVariable(data), + serverValue: data.attributes.server_value, + }); + + static toAllocation = ({ attributes }: FractalResponseData): Allocation => ({ + id: attributes.id, + ip: attributes.ip, + port: attributes.port, + alias: attributes.alias || null, + isAssigned: attributes.assigned, + relationships: { + node: transform(attributes.relationships?.node as FractalResponseData, this.toNode), + server: transform(attributes.relationships?.server as FractalResponseData, this.toServer), + }, + }); } diff --git a/resources/scripts/api/admin/user.ts b/resources/scripts/api/admin/user.ts new file mode 100644 index 000000000..7d67e908b --- /dev/null +++ b/resources/scripts/api/admin/user.ts @@ -0,0 +1,36 @@ +import { Model, UUID } from '@/api/admin/index'; +import { Server } from '@/api/admin/server'; +import http from '@/api/http'; +import { AdminTransformers } from '@/api/admin/transformers'; + +export interface User extends Model { + id: number; + uuid: UUID; + externalId: string; + username: string; + email: string; + language: string; + adminRoleId: number | null; + roleName: string; + isRootAdmin: boolean; + isUsingTwoFactor: boolean; + avatarUrl: string; + createdAt: Date; + updatedAt: Date; + relationships: { + role: UserRole | null; + servers?: Server[]; + }; +} + +export interface UserRole extends Model { + id: string; + name: string; + description: string; +} + +export const getUser = async (id: string | number): Promise => { + const { data } = await http.get(`/api/application/users/${id}`); + + return AdminTransformers.toUser(data.data); +};