Pārlūkot izejas kodu

WIP: Authentication

Nicolas Meienberger 3 gadi atpakaļ
vecāks
revīzija
8f5f2c09e8

+ 11 - 0
apps/invidious/config.json

@@ -0,0 +1,11 @@
+{
+  "name": "Invidious",
+  "port": 8095,
+  "id": "invidious",
+  "description": "",
+  "short_desc": "",
+  "author": "",
+  "source": "https://github.com/iv-org/invidious",
+  "image": "https://raw.githubusercontent.com/iv-org/invidious/master/assets/invidious-colored-vector.svg",
+  "form_fields": {}
+}

+ 45 - 0
apps/invidious/docker-compose.yml

@@ -0,0 +1,45 @@
+version: "3"
+services:
+  invidious:
+    user: 1000:1000
+    container_name: invidious
+    image: quay.io/invidious/invidious:latest-arm64
+    # image: quay.io/invidious/invidious:latest-arm64 # ARM64/AArch64 devices
+    restart: unless-stopped
+    ports:
+      - "${APP_PORT}:3000"
+    environment:
+      # Please read the following file for a comprehensive list of all available
+      # configuration options and their associated syntax:
+      # https://github.com/iv-org/invidious/blob/master/config/config.example.yml
+      INVIDIOUS_CONFIG: |
+        db:
+          dbname: invidious
+          user: tipi
+          password: tipi
+          host: invidious-db
+          port: 5432
+        check_tables: true
+    healthcheck:
+      test: wget -nv --tries=1 --spider http://127.0.0.1:3000/api/v1/comments/jNQXAC9IVRw || exit 1
+      interval: 30s
+      timeout: 5s
+      retries: 2
+    depends_on:
+      - invidious-db
+
+  invidious-db:
+    user: 1000:1000
+    container_name: invidious-db
+    image: docker.io/library/postgres:14
+    restart: unless-stopped
+    volumes:
+      - ${APP_DATA_DIR}/data/postgres:/var/lib/postgresql/data
+      - ${APP_DATA_DIR}/data/sql:/config/sql
+      - ./docker/init-invidious-db.sh:/docker-entrypoint-initdb.d/init-invidious-db.sh
+    environment:
+      POSTGRES_DB: invidious
+      POSTGRES_USER: tipi
+      POSTGRES_PASSWORD: tipi
+    healthcheck:
+      test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]

+ 12 - 0
apps/n8n/config.json

@@ -0,0 +1,12 @@
+{
+  "name": "n8n",
+  "port": 8094,
+  "id": "n8n",
+  "description": "n8n is an extendable workflow automation tool. With a fair-code distribution model, n8n will always have visible source code, be available to self-host, and allow you to add your own custom functions, logic and apps. n8n's node-based approach makes it highly versatile, enabling you to connect anything to everything.",
+  "short_desc": "Workflow Automation Tool. Alternative to Zapier",
+  "author": "n8n.io",
+  "source": "https://github.com/n8n-io/n8n",
+  "website": "https://n8n.io/",
+  "image": "https://avatars.githubusercontent.com/u/45487711?s=200&v=4",
+  "form_fields": {}
+}

+ 36 - 0
apps/n8n/docker-compose.yml

@@ -0,0 +1,36 @@
+version: "3.7"
+
+services:
+  db-n8n:
+    container_name: db-n8n
+    image: postgres:14.2
+    restart: on-failure
+    volumes:
+      - ${APP_DATA_DIR}/data/db:/var/lib/postgresql/data
+    environment:
+      - POSTGRES_PASSWORD=tipi
+      - POSTGRES_USER=tipi
+      - POSTGRES_DB=n8n
+    networks:
+      - tipi_main_network
+
+  n8n:
+    container_name: n8n
+    image: n8nio/n8n:0.174.0
+    restart: unless-stopped
+    ports:
+      - ${APP_PORT}:5678
+    volumes:
+      - ${APP_DATA_DIR}/data/n8n:/home/node/.n8n
+    command: /bin/sh -c "sleep 5; n8n start"
+    environment:
+      - DB-TYPE=postgresdb
+      - DB_POSTGRESDB_DATABASE=n8n
+      - DB_POSTGRESDB_HOST=db-n8n
+      - DB_POSTGRESDB_PORT=5432
+      - DB_POSTGRESDB_USER=tipi
+      - DB_POSTGRESDB_PASSWORD=tipi
+    depends_on:
+      - db-n8n
+    networks:
+      - tipi_main_network

+ 5 - 0
dashboard/src/core/types.ts

@@ -13,6 +13,7 @@ interface FormField {
   label: string;
   max?: number;
   min?: number;
+  hint?: string;
   required?: boolean;
   env_variable: string;
 }
@@ -49,3 +50,7 @@ export enum AppStatus {
   STOPPING = 'stopping',
   STARTING = 'starting',
 }
+
+export interface IUser {
+  first_name: string;
+}

+ 25 - 0
dashboard/src/modules/Dashboard/components/SystemStat.tsx

@@ -0,0 +1,25 @@
+import { Progress, Stat, StatHelpText, StatLabel, StatNumber } from '@chakra-ui/react';
+import React from 'react';
+import { IconType } from 'react-icons';
+
+interface IProps {
+  icon: IconType;
+  progress: number;
+  title: string;
+  subtitle: string;
+  metric: string;
+}
+
+const SystemStat: React.FC<IProps> = ({ icon: Icon, progress, title, subtitle, metric }) => {
+  return (
+    <Stat className="border-2 px-5 py-3 rounded-lg">
+      <StatLabel>{title}</StatLabel>
+      <StatNumber>{metric}</StatNumber>
+      <StatHelpText>{subtitle}</StatHelpText>
+      <Progress value={progress} size="sm" />
+      <Icon size={30} className="absolute top-3 right-3" />
+    </Stat>
+  );
+};
+
+export default SystemStat;

+ 53 - 0
dashboard/src/modules/Dashboard/containers/Dashboard.tsx

@@ -0,0 +1,53 @@
+import { SimpleGrid, Text } from '@chakra-ui/react';
+import React, { useEffect } from 'react';
+import { BsCpu } from 'react-icons/bs';
+import { FaMemory } from 'react-icons/fa';
+import { FiHardDrive } from 'react-icons/fi';
+import { useSytemStore } from '../../../state/systemStore';
+import SystemStat from '../components/SystemStat';
+
+const Dashboard: React.FC = () => {
+  const { fetchDiskSpace, fetchCpuLoad, fetchMemoryLoad, disk, cpuLoad, memory } = useSytemStore();
+
+  useEffect(() => {
+    fetchDiskSpace();
+    fetchCpuLoad();
+    fetchMemoryLoad();
+
+    const interval = setInterval(() => {
+      fetchDiskSpace();
+      fetchCpuLoad();
+      fetchMemoryLoad();
+    }, 10000);
+
+    return () => clearInterval(interval);
+  }, [fetchCpuLoad, fetchDiskSpace, fetchMemoryLoad]);
+
+  // Convert bytes to GB
+  const diskFree = Math.round(disk.available / 1024 / 1024 / 1024);
+  const diskSize = Math.round(disk.size / 1024 / 1024 / 1024);
+  const diskUsed = diskSize - diskFree;
+  const percentUsed = Math.round((diskUsed / diskSize) * 100);
+
+  const memoryTotal = Math.round(memory?.total / 1024 / 1024 / 1024);
+  const memoryFree = Math.round(memory?.free / 1024 / 1024 / 1024);
+  const percentUsedMemory = Math.round(((memoryTotal - memoryFree) / memoryTotal) * 100);
+
+  return (
+    <>
+      <Text fontSize="3xl" className="font-bold">
+        Tipi Dashboard
+      </Text>
+      <Text fontSize="xl" color="gray.500">
+        Welcome home!
+      </Text>
+      <SimpleGrid className="mt-5" minChildWidth="180px" spacing="20px">
+        <SystemStat title="Disk space" metric={`${diskUsed} GB`} subtitle={`Used out of ${diskSize} GB`} icon={FiHardDrive} progress={percentUsed} />
+        <SystemStat title="CPU Load" metric={`${cpuLoad.toFixed(2)}%`} subtitle="Uninstall apps if there is to much load" icon={BsCpu} progress={cpuLoad} />
+        <SystemStat title="Memory Used" metric={`${percentUsedMemory}%`} subtitle={`${memoryTotal} GB`} icon={FaMemory} progress={percentUsedMemory} />
+      </SimpleGrid>
+    </>
+  );
+};
+
+export default Dashboard;

+ 0 - 13
dashboard/src/pages/api/device/cpu.ts

@@ -1,13 +0,0 @@
-// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
-import type { NextApiRequest, NextApiResponse } from 'next';
-import si from 'systeminformation';
-
-type Data = Awaited<ReturnType<typeof si.currentLoad>>;
-
-const handler = async (req: NextApiRequest, res: NextApiResponse<Data>) => {
-  const cpuLoad = await si.currentLoad();
-
-  res.status(200).json(cpuLoad);
-};
-
-export default handler;

+ 0 - 13
dashboard/src/pages/api/device/disk.ts

@@ -1,13 +0,0 @@
-// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
-import type { NextApiRequest, NextApiResponse } from 'next';
-import si from 'systeminformation';
-
-type Data = Awaited<ReturnType<typeof si.fsSize>>;
-
-const handler = async (req: NextApiRequest, res: NextApiResponse<Data>) => {
-  const disk = await si.fsSize();
-
-  res.status(200).json(disk);
-};
-
-export default handler;

+ 0 - 13
dashboard/src/pages/api/device/memory.ts

@@ -1,13 +0,0 @@
-// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
-import type { NextApiRequest, NextApiResponse } from 'next';
-import si from 'systeminformation';
-
-type Data = Awaited<ReturnType<typeof si.mem>>;
-
-const handler = async (req: NextApiRequest, res: NextApiResponse<Data>) => {
-  const memory = await si.mem();
-
-  res.status(200).json(memory);
-};
-
-export default handler;

+ 20 - 61
dashboard/src/pages/index.tsx

@@ -1,72 +1,31 @@
-import { Progress, SimpleGrid, Stat, StatHelpText, StatLabel, StatNumber, Text } from '@chakra-ui/react';
 import type { NextPage } from 'next';
-import { useEffect } from 'react';
 import Layout from '../components/Layout';
-import { useSytemStore } from '../state/systemStore';
-import { BsCpu } from 'react-icons/bs';
-import { FiHardDrive } from 'react-icons/fi';
-import { FaMemory } from 'react-icons/fa';
+import api from '../core/api';
+import { IUser } from '../core/types';
+import Dashboard from '../modules/Dashboard/containers/Dashboard';
 
 const Home: NextPage = () => {
-  const { fetchDiskSpace, fetchCpuLoad, fetchMemoryLoad, disk, cpuLoad, memory } = useSytemStore();
-
-  useEffect(() => {
-    fetchDiskSpace();
-    fetchCpuLoad();
-    fetchMemoryLoad();
-
-    const interval = setInterval(() => {
-      fetchDiskSpace();
-      fetchCpuLoad();
-      fetchMemoryLoad();
-    }, 10000);
-
-    return () => clearInterval(interval);
-  }, [fetchCpuLoad, fetchDiskSpace]);
-
-  // Convert bytes to GB
-  const diskFree = Math.round(disk.available / 1024 / 1024 / 1024);
-  const diskSize = Math.round(disk.size / 1024 / 1024 / 1024);
-  const diskUsed = diskSize - diskFree;
-  const percentUsed = Math.round((diskUsed / diskSize) * 100);
-
-  const memoryTotal = Math.round(memory?.total / 1024 / 1024 / 1024);
-  const memoryUsed = Math.round(memory?.used / 1024 / 1024 / 1024);
-  const percentUsedMemory = Math.round((memoryUsed / memoryTotal) * 100);
-
   return (
     <Layout>
-      <Text fontSize="3xl" className="font-bold">
-        Tipi Dashboard
-      </Text>
-      <Text fontSize="xl" color="gray.500">
-        Welcome home!
-      </Text>
-      <SimpleGrid className="mt-5" minChildWidth="180px" spacing="20px">
-        <Stat className="border-2 px-5 py-3 rounded-lg">
-          <StatLabel>Disk space</StatLabel>
-          <StatNumber>{diskUsed} GB</StatNumber>
-          <StatHelpText>Used out of {diskSize} GB</StatHelpText>
-          <Progress value={percentUsed} size="sm" />
-          <FiHardDrive size={30} className="absolute top-3 right-3" />
-        </Stat>
-        <Stat className="border-2 px-5 py-3 rounded-lg">
-          <StatLabel>CPU Load</StatLabel>
-          <StatNumber>{cpuLoad.toFixed(2)}%</StatNumber>
-          <StatHelpText>Uninstall apps if there is to much load</StatHelpText>
-          <Progress value={cpuLoad} size="sm" />
-          <BsCpu size={30} className="absolute top-3 right-3" />
-        </Stat>
-        <Stat className="border-2 px-5 py-3 rounded-lg">
-          <StatLabel>Memory Used</StatLabel>
-          <StatNumber>{percentUsedMemory}%</StatNumber>
-          <StatHelpText>{memoryTotal} GB</StatHelpText>
-          <Progress value={percentUsedMemory} size="sm" />
-          <FaMemory size={30} className="absolute top-3 right-3" />
-        </Stat>
-      </SimpleGrid>
+      <Dashboard />
     </Layout>
   );
 };
 
+export async function getServerSideProps() {
+  const token = localStorage.getItem('tipi_token');
+
+  // Fetch data from external API
+  const res = await api.fetch<IUser>({
+    endpoint: '/user',
+    method: 'post',
+    data: { token },
+  });
+
+  console.log(res);
+
+  // Pass data to the page via props
+  return { props: { user: res } };
+}
+
 export default Home;

BIN
screenshots/2.png


+ 3 - 3
scripts/start.sh

@@ -77,9 +77,9 @@ function get_json_field() {
 str=$(get_json_field ${STATE_FOLDER}/apps.json installed)
 apps_to_start=($str)
 
-for app in "${apps_to_start[@]}"; do
-    "${ROOT_FOLDER}/scripts/app.sh" start $app
-done
+# for app in "${apps_to_start[@]}"; do
+#     "${ROOT_FOLDER}/scripts/app.sh" start $app
+# done
 
 echo "Tipi is now running"
 echo ""

+ 1 - 1
system-api/src/config/apps.ts

@@ -1 +1 @@
-export const appNames = ['nextcloud', 'freshrss', 'anonaddy', 'filerun', 'wg-easy', 'radarr', 'transmission', 'jellyfin', 'pihole', 'tailscale'];
+export const appNames = ['nextcloud', 'freshrss', 'anonaddy', 'filerun', 'wg-easy', 'radarr', 'transmission', 'jellyfin', 'pihole', 'tailscale', 'n8n', 'invidious'];

+ 0 - 5
tipi.config.json.example

@@ -1,5 +0,0 @@
-{
-  "main": {
-    "domain": "mydomain.com"
-  }
-}