diff --git a/.gitignore b/.gitignore index 21bb28d..f5005c3 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,7 @@ config/static/* db/* !db/.kener database/* -!database/.kener \ No newline at end of file +!database/.kener + +static/uploads/* +!static/uploads/upload.dir \ No newline at end of file diff --git a/delay.js b/delay.js index 4a8f937..2c2ad70 100644 --- a/delay.js +++ b/delay.js @@ -1,17 +1,20 @@ -import fs from "fs-extra"; -import path from "path"; import db from "./src/lib/server/db/db.js"; let maxWait = 5000; let interval = 1000; let waitTime = 0; -let serverDataPath = path.join(process.cwd(), "database", "server.json"); -let siteDataPath = path.join(process.cwd(), "database", "site.json"); -let monitorsDataPath = path.join(process.cwd(), "database", "monitors.json"); async function allFilesExist() { let tablesCreated = (await db.checkTables()).map((table) => table.name); - let tablesRequired = ["MonitoringData", "MonitorAlerts", "SiteData", "Monitors", "Alerts"]; + let tablesRequired = [ + "MonitoringData", + "MonitorAlerts", + "SiteData", + "Monitors", + "Triggers", + "Users", + "ApiKeys" + ]; for (let table of tablesRequired) { let tableExists = tablesCreated.includes(table); diff --git a/src/lib/clientTools.js b/src/lib/clientTools.js index 87c8b2d..f6c0ca2 100644 --- a/src/lib/clientTools.js +++ b/src/lib/clientTools.js @@ -147,6 +147,7 @@ function IsValidNameServer(nameServer) { const IsValidURL = function (url) { return /^(http|https):\/\/[^ "]+$/.test(url); }; + export { siteDataExtractFromDb, storeSiteData, diff --git a/src/lib/components/manage/homePage.svelte b/src/lib/components/manage/homePage.svelte index a398951..f808f59 100644 --- a/src/lib/components/manage/homePage.svelte +++ b/src/lib/components/manage/homePage.svelte @@ -140,20 +140,38 @@ } } - function handleFileChangeLogo(event, i) { + async function handleFileChangeLogo(event, i) { const file = event.target.files[0]; - if (file) { - if (file.size > 100000) { - alert("File size should be less than 100KB"); - return; - } + if (!file) { + alert("Please select a file to upload."); + return; + } - const reader = new FileReader(); - reader.onload = () => { - nav[i].iconURL = reader.result; - }; - reader.readAsDataURL(file); + if (file.size > 100000) { + alert("File size should be less than 100KB"); + return; + } + + nav[i].uploading = true; + const formData = new FormData(); + formData.append("image", file); + try { + const response = await fetch("/manage/upload", { + method: "POST", + body: formData + }); + + if (response.ok) { + const result = await response.json(); + nav[i].iconURL = base + "/uploads/" + result.filename; + } else { + alert("Failed to upload file."); + } + } catch (error) { + alert("An error occurred while uploading the file."); + } finally { + nav[i].uploading = false; } } function addNewRow() { @@ -307,6 +325,7 @@ { diff --git a/src/lib/components/manage/monitorSheet.svelte b/src/lib/components/manage/monitorSheet.svelte index f4f75c4..68001ea 100644 --- a/src/lib/components/manage/monitorSheet.svelte +++ b/src/lib/components/manage/monitorSheet.svelte @@ -33,17 +33,42 @@ let formState = "idle"; export let newMonitor; + let loadingLogo = false; let selectedCategory = categories.find((category) => category.name === newMonitor.categoryName); - function handleFileChangeLogo(event) { + async function handleFileChangeLogo(event) { const file = event.target.files[0]; - if (file) { - const reader = new FileReader(); - reader.onload = () => { - newMonitor.image = reader.result; - }; - reader.readAsDataURL(file); + if (!file) { + event.target.value = ""; + alert("Please select a file to upload."); + return; + } + if (file.size > 100000) { + event.target.value = ""; + alert("File size should be less than 100KB"); + return; + } + + loadingLogo = true; + const formData = new FormData(); + formData.append("image", file); + try { + const response = await fetch("/manage/upload", { + method: "POST", + body: formData + }); + + if (response.ok) { + const result = await response.json(); + newMonitor.image = base + "/uploads/" + result.filename; + } else { + alert("Failed to upload file."); + } + } catch (error) { + alert("An error occurred while uploading the file."); + } finally { + loadingLogo = false; } } function addHeader() { @@ -257,6 +282,7 @@ class="w-1/2" id="logo" type="file" + disabled={loadingLogo} accept=".jpg, .jpeg, .png" on:change={(e) => { handleFileChangeLogo(e); diff --git a/src/lib/components/manage/monitorsAdd.svelte b/src/lib/components/manage/monitorsAdd.svelte index 0e842b7..ab7abaa 100644 --- a/src/lib/components/manage/monitorsAdd.svelte +++ b/src/lib/components/manage/monitorsAdd.svelte @@ -260,25 +260,27 @@
- +

{monitor.tag}

- +

{monitor.monitorType}

- +

{monitor.cron}

- +

{!!monitor.categoryName ? monitor.categoryName : "-"}

diff --git a/src/lib/components/manage/seoInfo.svelte b/src/lib/components/manage/seoInfo.svelte index 3155932..eec96d5 100644 --- a/src/lib/components/manage/seoInfo.svelte +++ b/src/lib/components/manage/seoInfo.svelte @@ -149,7 +149,7 @@
{#each metaTags as metaTag, i} -
+
-
-
- - {#if !!siteInformation.logo} - - {/if} - + +
+
+
-
- - {#if !!siteInformation.favicon} - +
+ {#if !!siteInformation.logo} +
+ + +
+ +
+ {#if uploadingLogo} +
+ +
+ {/if} +
{/if} - +
+ +

+ Please upload a square image of max size 100KB +

+

+ {uploadLogoStatus} +

+
+
+
+ +
+
+ {#if !!siteInformation.favicon} +
+ + +
+ +
+ {#if uploadingFavicon} +
+ +
+ {/if} +
+ {/if} +
+ +

+ Please upload a square image of max size 20KB +

+

+ {uploadFaviconStatus} +

+
diff --git a/src/lib/components/monitor.svelte b/src/lib/components/monitor.svelte index fd9e85e..7c45b07 100644 --- a/src/lib/components/monitor.svelte +++ b/src/lib/components/monitor.svelte @@ -247,9 +247,9 @@
-
+
{ showDailyDataModal = false; @@ -269,7 +269,7 @@ href="#" class="oneline h-[34px] w-[6px] border-b-2 {bar.border ? 'border-indigo-400' - : 'border-transparent'} pb-1" + : 'border-transparent'} pb-1" >
{dateFetchedFor} diff --git a/src/lib/components/nav.svelte b/src/lib/components/nav.svelte index e9172b5..0bf525f 100644 --- a/src/lib/components/nav.svelte +++ b/src/lib/components/nav.svelte @@ -10,8 +10,8 @@
-
-
+
+
{#if data.site.logo} {#each data.site.nav as navItem} analyticsEvent("nav", navItem.name)} > {#if navItem.iconURL} {navItem.name} diff --git a/src/lib/server/controllers/controller.js b/src/lib/server/controllers/controller.js index a7d4565..3807c91 100644 --- a/src/lib/server/controllers/controller.js +++ b/src/lib/server/controllers/controller.js @@ -336,3 +336,12 @@ export const VerifyAPIKey = async (apiKey) => { } // Adjust this for your DB query return false; }; + +export const IsSetupComplete = async () => { + let data = await db.getAllSiteData(); + + if (!data) { + return false; + } + return data.length > 0; +}; diff --git a/src/lib/server/db/db.js b/src/lib/server/db/db.js index 6dbd77c..a1824d5 100644 --- a/src/lib/server/db/db.js +++ b/src/lib/server/db/db.js @@ -1,22 +1,15 @@ // @ts-nocheck import Sqlite from "./sqlite.js"; import Postgres from "./postgres.js"; -import migration2 from "./migration2.js"; -import { serverStore } from "../stores/server.js"; -import { get } from "svelte/store"; let instance = null; -const server = get(serverStore); -let database = server.database; -if (database === undefined) { - database = { - sqlite: { - dbName: "kener.db" - } - }; -} -const supportedDatabases = ["sqlite", "postgres"]; +let database = { + sqlite: { + dbName: "kener.local3.db" + } +}; +const supportedDatabases = ["sqlite"]; const dbType = Object.keys(database)[0] || "sqlite"; const dbConfig = database[dbType]; @@ -57,7 +50,7 @@ if (dbType === "sqlite") { instance = new Postgres(dbConfig); } -migration2(instance, "./database"); +//migration2(instance, "./database"); //create anonymous function to call the init function diff --git a/src/lib/server/db/seedMonitorData.js b/src/lib/server/db/seedMonitorData.js new file mode 100644 index 0000000..e6a5354 --- /dev/null +++ b/src/lib/server/db/seedMonitorData.js @@ -0,0 +1,22 @@ +let seedMonitorData = [ + { + tag: "earth", + name: "Earth - Planet 3", + description: + "Earth is the 3rd planet in our solar system and it is the most majestic one. ", + image: "https://kener.ing/earth.png", + cron: "* * * * *", + defaultStatus: "UP", + status: "ACTIVE", + categoryName: "Home", + monitorType: "NONE", + downTrigger: null, + degradedTrigger: null, + typeData: "", + dayDegradedMinimumCount: 0, + dayDownMinimumCount: 0, + includeDegradedInDowntime: "NO" + } +]; + +export default seedMonitorData; diff --git a/src/lib/server/db/seedSiteData.js b/src/lib/server/db/seedSiteData.js index 25fb92c..72a32ab 100644 --- a/src/lib/server/db/seedSiteData.js +++ b/src/lib/server/db/seedSiteData.js @@ -3,9 +3,8 @@ const seedSiteData = { siteName: "Kener.ing", siteURL: "https://kener.ing", home: "/", - logo: "data:image/png;base64,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", - favicon: - "data:image/png;base64,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", + logo: "https://kener.ing/logo.png", + favicon: "https://kener.ing/logo96.png", github: { apiURL: "https://api.github.com", owner: "rajnandan1", @@ -46,6 +45,7 @@ const seedSiteData = { } ], nav: [ + { name: "Login", url: "/signin", iconURL: "" }, { name: "Documentation", url: "/docs/home", iconURL: "" }, { name: "Github", iconURL: "", url: "https://github.com/rajnandan1/kener" }, { name: "Buy me a coffee", iconURL: "", url: "https://buymeacoffee.com/rajnandan1" } diff --git a/src/manage.css b/src/manage.css index 8624860..9562787 100644 --- a/src/manage.css +++ b/src/manage.css @@ -22,3 +22,15 @@ textarea { .dark textarea { background-color: rgba(0, 0, 0, 0.1) !important; } + +input[type="file"]::file-selector-button { + display: none; +} +input[type="file"] { + font-weight: 500; + padding-top: 10px; +} + +.image-upload .has-bg:hover .invisible { + visibility: visible !important; +} diff --git a/src/routes/(account)/+layout.svelte b/src/routes/(account)/+layout.svelte index a99617a..5a51a26 100644 --- a/src/routes/(account)/+layout.svelte +++ b/src/routes/(account)/+layout.svelte @@ -2,6 +2,7 @@ import "../../app.postcss"; import "../../kener.css"; import "../../manage.css"; + import { base } from "$app/paths"; import { setMode, mode, ModeWatcher } from "mode-watcher"; setMode("dark"); @@ -10,6 +11,8 @@ Setup Kener + +
diff --git a/src/routes/(account)/setup/+page.server.js b/src/routes/(account)/setup/+page.server.js index 2842967..3773933 100644 --- a/src/routes/(account)/setup/+page.server.js +++ b/src/routes/(account)/setup/+page.server.js @@ -2,6 +2,7 @@ export async function load({ params, route, url, parent }) { //read query parameters const query = url.searchParams; return { - error: query.get("error") + error: query.get("error"), + isSecretSet: process.env.KENER_SECRET_KEY !== undefined }; } diff --git a/src/routes/(account)/setup/+page.svelte b/src/routes/(account)/setup/+page.svelte index 5508d46..994067d 100644 --- a/src/routes/(account)/setup/+page.svelte +++ b/src/routes/(account)/setup/+page.svelte @@ -11,76 +11,110 @@ name: "" }; export let data = { - error: null + error: null, + isSecretSet: false }; + console.log(">>>>>>---- +page:17 ", data);
Your Company

Set up Kener.ing

+

Welcome to Kener.ing! Let's get you set up.

+ {#if data.isSecretSet} +
+ {#if data.error} + + Error + {data.error} + + {/if} - diff --git a/src/routes/(account)/setup/submit/+server.js b/src/routes/(account)/setup/submit/+server.js index 99863c6..3245292 100644 --- a/src/routes/(account)/setup/submit/+server.js +++ b/src/routes/(account)/setup/submit/+server.js @@ -3,8 +3,25 @@ import { json, redirect } from "@sveltejs/kit"; import { base } from "$app/paths"; import db from "$lib/server/db/db.js"; import seedSiteData from "$lib/server/db/seedSiteData.js"; +import seedMonitorData from "$lib/server/db/seedMonitorData.js"; import { HashPassword, GenerateSalt } from "$lib/server/controllers/controller.js"; +//function to validate a strong password +/** + * Validates a password to ensure it meets the following criteria: + * - Contains at least one digit. + * - Contains at least one lowercase letter. + * - Contains at least one uppercase letter. + * - Contains at least one letter (either lowercase or uppercase). + * - Has a minimum length of 8 characters. + * + * @param {string} password - The password to validate. + * @returns {boolean} - Returns true if the password meets the criteria, otherwise false. + */ +function validatePassword(password) { + return /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[a-zA-Z]).{8,}$/.test(password); +} + export async function POST({ request }) { //read form post data email and passowrd const formdata = await request.formData(); @@ -26,6 +43,14 @@ export async function POST({ request }) { name: name, role: "admin" }; + + //validate password + if (!validatePassword(password)) { + let errorMessage = + "Password must contain at least one digit, one lowercase letter, one uppercase letter, and have a minimum length of 8 characters."; + throw redirect(302, base + "/setup?error=" + errorMessage); + } + await db.insertUser(user); for (const key in seedSiteData) { @@ -35,9 +60,13 @@ export async function POST({ request }) { if (dataType === "object") { value = JSON.stringify(value); } - await this.insertOrUpdateSiteData(key, value, dataType); + await db.insertOrUpdateSiteData(key, value, dataType); } } + //loop through array seedMonitorData + for (const monitor of seedMonitorData) { + await db.insertMonitor(monitor); + } throw redirect(302, base + "/signin"); } diff --git a/src/routes/(account)/signin/+page.svelte b/src/routes/(account)/signin/+page.svelte index da0d5a9..2b92ad6 100644 --- a/src/routes/(account)/signin/+page.svelte +++ b/src/routes/(account)/signin/+page.svelte @@ -14,10 +14,14 @@ }; + + Login Kener +
Your Company -

Signin

+

Sign in

+

Sign in to manage your kener instance.

diff --git a/src/routes/(kener)/+layout.server.js b/src/routes/(kener)/+layout.server.js index 94411f7..6c86872 100644 --- a/src/routes/(kener)/+layout.server.js +++ b/src/routes/(kener)/+layout.server.js @@ -1,8 +1,19 @@ // @ts-nocheck import i18n from "$lib/i18n/server"; -import { GetAllSiteData } from "$lib/server/controllers/controller.js"; +import { redirect } from "@sveltejs/kit"; +import { base } from "$app/paths"; +import { GetAllSiteData, IsSetupComplete } from "$lib/server/controllers/controller.js"; export async function load({ params, route, url, cookies, request }) { + let isSetupComplete = await IsSetupComplete(); + if (!isSetupComplete) { + throw redirect(302, base + "/setup"); + } + + if (process.env.KENER_SECRET_KEY === undefined) { + throw redirect(302, base + "/setup"); + } + let site = await GetAllSiteData(); const headers = request.headers; const userAgent = headers.get("user-agent"); diff --git a/src/routes/(kener)/+layout.svelte b/src/routes/(kener)/+layout.svelte index 444ecd7..747a9b4 100644 --- a/src/routes/(kener)/+layout.svelte +++ b/src/routes/(kener)/+layout.svelte @@ -11,7 +11,6 @@ import * as DropdownMenu from "$lib/components/ui/dropdown-menu"; import { analyticsEvent } from "$lib/analytics"; import { setMode, mode, ModeWatcher } from "mode-watcher"; - // import { Termo } from "termo"; export let data; let defaultLocaleKey = data.selectedLang; diff --git a/src/routes/(manage)/+layout.server.js b/src/routes/(manage)/+layout.server.js index 8419b00..9049af7 100644 --- a/src/routes/(manage)/+layout.server.js +++ b/src/routes/(manage)/+layout.server.js @@ -11,7 +11,11 @@ function maskString(str) { export async function load({ params, route, url, cookies, request }) { let siteData = await GetAllSiteData(); //check if user is authenticated using cookies + if (process.env.KENER_SECRET_KEY === undefined) { + throw redirect(302, base + "/setup"); + } let tokenData = cookies.get("kener-user"); + if (!!!tokenData) { //redirect to signin page if user is not authenticated throw redirect(302, base + "/signin"); diff --git a/src/routes/(manage)/+layout.svelte b/src/routes/(manage)/+layout.svelte index 54a13a2..0cb0994 100644 --- a/src/routes/(manage)/+layout.svelte +++ b/src/routes/(manage)/+layout.svelte @@ -28,9 +28,11 @@ Manage Kener + + -
-
+
+
Kener

Manage Kener

diff --git a/src/routes/(manage)/manage/api/+server.js b/src/routes/(manage)/manage/api/+server.js index e13016f..5d9e1bf 100644 --- a/src/routes/(manage)/manage/api/+server.js +++ b/src/routes/(manage)/manage/api/+server.js @@ -11,13 +11,37 @@ import { GetAllAlertsPaginated, GetAllAPIKeys, CreateNewAPIKey, - UpdateApiKeyStatus + UpdateApiKeyStatus, + VerifyToken } from "$lib/server/controllers/controller.js"; -export async function POST({ request }) { +export async function POST({ request, cookies }) { const payload = await request.json(); let action = payload.action; let data = payload.data || {}; let resp = {}; + + let tokenData = cookies.get("kener-user"); + + if (!!!tokenData) { + return json( + { + error: "Unauthorized" + }, + { status: 401 } + ); + } + + let tokenUser = await VerifyToken(tokenData); + if (!!!tokenUser) { + //redirect to signin page if user is not authenticated + return json( + { + error: "Unauthorized" + }, + { status: 401 } + ); + } + try { if (action === "storeSiteData") { resp = await storeSiteData(data); diff --git a/src/routes/(manage)/manage/upload/+server.js b/src/routes/(manage)/manage/upload/+server.js new file mode 100644 index 0000000..0365a97 --- /dev/null +++ b/src/routes/(manage)/manage/upload/+server.js @@ -0,0 +1,46 @@ +// @ts-nocheck +import { writeFileSync } from "fs-extra"; +import { randomUUID } from "crypto"; +import { json } from "@sveltejs/kit"; +import { VerifyToken } from "$lib/server/controllers/controller.js"; + +export async function POST({ request, cookies }) { + let tokenData = cookies.get("kener-user"); + + if (!!!tokenData) { + return json( + { + error: "Unauthorized" + }, + { status: 401 } + ); + } + + let tokenUser = await VerifyToken(tokenData); + if (!!!tokenUser) { + //redirect to signin page if user is not authenticated + return json( + { + error: "Unauthorized" + }, + { status: 401 } + ); + } + // Parse the form data from the request + const formData = await request.formData(); + + // Get the image file from the form data + const imageFile = formData.get("image"); + + // Generate a unique filename + const filename = `${randomUUID()}-${imageFile.name}`; + + // Read the file as a buffer + const fileBuffer = await imageFile.arrayBuffer(); + + // Save the file to the static directory + writeFileSync(`./static/uploads/${filename}`, Buffer.from(fileBuffer)); + + // Return a response + return json({ filename }); +} diff --git a/static/uploads/upload.dir b/static/uploads/upload.dir new file mode 100644 index 0000000..25f88e1 --- /dev/null +++ b/static/uploads/upload.dir @@ -0,0 +1 @@ +this is the upload directory \ No newline at end of file diff --git a/test.db b/test.db deleted file mode 100644 index 0b58f0d..0000000 Binary files a/test.db and /dev/null differ diff --git a/test.db-shm b/test.db-shm deleted file mode 100644 index 8ce43e5..0000000 Binary files a/test.db-shm and /dev/null differ diff --git a/test.db-wal b/test.db-wal deleted file mode 100644 index 1ecf42f..0000000 Binary files a/test.db-wal and /dev/null differ