From 38fcdbf391d88979e39b2fd22414f3e630cd7bdf Mon Sep 17 00:00:00 2001
From: KartoffelChips <104089082+KartoffelChipss@users.noreply.github.com>
Date: Mon, 6 Apr 2026 18:01:37 +0200
Subject: [PATCH] Added site index file and created_at
---
backend/app/handlers/site.go | 3 ++
backend/app/handlers/static.go | 6 ++--
backend/app/models/site.go | 3 ++
backend/internal/database/init_sqlite.go | 5 +++-
backend/internal/database/site_sqlite.go | 18 ++++++------
frontend/src/api/types/site.ts | 6 +++-
frontend/src/pages/NewSite/NewSite.tsx | 2 ++
.../src/pages/SiteOverview/OverviewTab.tsx | 2 +-
.../src/pages/SiteOverview/SettingsTab.tsx | 28 +++++++++++++++++++
9 files changed, 59 insertions(+), 14 deletions(-)
diff --git a/backend/app/handlers/site.go b/backend/app/handlers/site.go
index 1472381..b4fa9a0 100644
--- a/backend/app/handlers/site.go
+++ b/backend/app/handlers/site.go
@@ -110,6 +110,9 @@ func validateIncomingSite(site *models.Site) error {
if site.NotFoundFile == "" {
site.NotFoundFile = "404.html"
}
+ if site.IndexFile == "" {
+ site.IndexFile = "index.html"
+ }
if site.ForwardRules == nil {
site.ForwardRules = []models.ForwardRule{}
}
diff --git a/backend/app/handlers/static.go b/backend/app/handlers/static.go
index b599db5..96b8a75 100644
--- a/backend/app/handlers/static.go
+++ b/backend/app/handlers/static.go
@@ -62,7 +62,7 @@ func NewStaticHandler(storagePath string, siteRepo repository.SiteRepository) fi
}
if urlPath == "/" || urlPath == "." {
- urlPath = "/index.html"
+ urlPath = "/" + site.IndexFile
}
basePath := filepath.Join(storagePath, site.ID)
@@ -71,7 +71,7 @@ func NewStaticHandler(storagePath string, siteRepo repository.SiteRepository) fi
info, err := os.Stat(filePath)
if err == nil {
if info.IsDir() {
- indexPath := filepath.Join(filePath, "index.html")
+ indexPath := filepath.Join(filePath, site.IndexFile)
if _, err := os.Stat(indexPath); err == nil {
return c.SendFile(indexPath)
}
@@ -81,7 +81,7 @@ func NewStaticHandler(storagePath string, siteRepo repository.SiteRepository) fi
}
if site.Spa {
- indexPath := filepath.Join(basePath, "index.html")
+ indexPath := filepath.Join(basePath, site.IndexFile)
if _, err := os.Stat(indexPath); err == nil {
return c.SendFile(indexPath)
}
diff --git a/backend/app/models/site.go b/backend/app/models/site.go
index aa27893..a807cea 100644
--- a/backend/app/models/site.go
+++ b/backend/app/models/site.go
@@ -33,6 +33,9 @@ type Site struct {
Enabled bool `json:"enabled"`
Spa bool `json:"spa"`
NotFoundFile string `json:"not_found_file"`
+ IndexFile string `json:"index_file"`
+ TrailingSlash *bool `json:"trailing_slash"`
+ CreatedAt string `json:"created_at"`
ForwardRules []ForwardRule `json:"forward_rules"`
CustomHeaders []CustomHeaders `json:"custom_headers"`
}
diff --git a/backend/internal/database/init_sqlite.go b/backend/internal/database/init_sqlite.go
index d1de047..7d0cdce 100644
--- a/backend/internal/database/init_sqlite.go
+++ b/backend/internal/database/init_sqlite.go
@@ -18,7 +18,10 @@ CREATE TABLE IF NOT EXISTS sites (
deploy_token TEXT NOT NULL,
enabled INTEGER NOT NULL DEFAULT 1,
spa INTEGER NOT NULL DEFAULT 0,
- not_found_file TEXT NOT NULL DEFAULT '404.html'
+ not_found_file TEXT NOT NULL DEFAULT '404.html',
+ index_file TEXT NOT NULL DEFAULT 'index.html',
+ trailing_slash INTEGER DEFAULT NULL,
+ created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS forward_rules (
diff --git a/backend/internal/database/site_sqlite.go b/backend/internal/database/site_sqlite.go
index 49c44d4..22105d7 100644
--- a/backend/internal/database/site_sqlite.go
+++ b/backend/internal/database/site_sqlite.go
@@ -25,7 +25,7 @@ var _ repository.SiteRepository = (*SQLiteSiteRepository)(nil)
func (r *SQLiteSiteRepository) GetSite(id string) (*models.Site, error) {
row := r.db.QueryRow(`
- SELECT id, name, git_server, owner, repository, branch, domain, deploy_token, spa, enabled, not_found_file
+ SELECT id, name, git_server, owner, repository, branch, domain, deploy_token, spa, enabled, not_found_file, index_file, trailing_slash, created_at
FROM sites WHERE id = ?`, id)
s, err := scanSite(row)
@@ -41,7 +41,7 @@ func (r *SQLiteSiteRepository) GetSite(id string) (*models.Site, error) {
func (r *SQLiteSiteRepository) GetSiteByDomain(domain string) (*models.Site, error) {
row := r.db.QueryRow(`
- SELECT id, name, git_server, owner, repository, branch, domain, deploy_token, spa, enabled, not_found_file
+ SELECT id, name, git_server, owner, repository, branch, domain, deploy_token, spa, enabled, not_found_file, index_file, trailing_slash, created_at
FROM sites WHERE domain = ?`, domain)
s, err := scanSite(row)
@@ -60,7 +60,7 @@ func (r *SQLiteSiteRepository) GetSiteByDomain(domain string) (*models.Site, err
func (r *SQLiteSiteRepository) ListSites() ([]models.Site, error) {
rows, err := r.db.Query(`
- SELECT id, name, git_server, owner, repository, branch, domain, deploy_token, spa, enabled, not_found_file
+ SELECT id, name, git_server, owner, repository, branch, domain, deploy_token, spa, enabled, not_found_file, index_file, trailing_slash, created_at
FROM sites`)
if err != nil {
return nil, fmt.Errorf("list sites: %w", err)
@@ -98,10 +98,10 @@ func (r *SQLiteSiteRepository) CreateSite(s *models.Site) error {
s.ID = uuid.NewString()
_, err = tx.Exec(`
- INSERT INTO sites (id, name, git_server, owner, repository, branch, domain, deploy_token, spa, enabled, not_found_file)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
+ INSERT INTO sites (id, name, git_server, owner, repository, branch, domain, deploy_token, spa, enabled, not_found_file, index_file, trailing_slash)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
s.ID, s.Name, s.GitServer, s.Owner, s.Repository, s.Branch,
- s.Domain, s.DeployToken, s.Spa, s.Enabled, s.NotFoundFile,
+ s.Domain, s.DeployToken, s.Spa, s.Enabled, s.NotFoundFile, s.IndexFile, s.TrailingSlash,
)
if err != nil {
return fmt.Errorf("create site insert: %w", err)
@@ -131,9 +131,10 @@ func (r *SQLiteSiteRepository) UpdateSite(s *models.Site) error {
_, err = tx.Exec(`
UPDATE sites SET name=?, git_server=?, owner=?, repository=?, branch=?, domain=?,
- deploy_token=?, spa=?, enabled=?, not_found_file=? WHERE id=?`,
+ deploy_token=?, spa=?, enabled=?, not_found_file=?, index_file=?, trailing_slash=? WHERE id=?`,
s.Name, s.GitServer, s.Owner, s.Repository, s.Branch, s.Domain,
- s.DeployToken, s.Spa, s.Enabled, s.NotFoundFile, s.ID,
+ s.DeployToken, s.Spa, s.Enabled, s.NotFoundFile, s.IndexFile, s.TrailingSlash,
+ s.ID,
)
if err != nil {
return fmt.Errorf("update site: %w", err)
@@ -364,6 +365,7 @@ func scanSite(s scanner) (*models.Site, error) {
err := s.Scan(
&site.ID, &site.Name, &site.GitServer, &site.Owner, &site.Repository,
&site.Branch, &site.Domain, &site.DeployToken, &site.Spa, &enabled, &site.NotFoundFile,
+ &site.IndexFile, &site.TrailingSlash, &site.CreatedAt,
)
if err != nil {
return nil, err
diff --git a/frontend/src/api/types/site.ts b/frontend/src/api/types/site.ts
index 4c440be..29d350e 100644
--- a/frontend/src/api/types/site.ts
+++ b/frontend/src/api/types/site.ts
@@ -31,7 +31,9 @@ export interface Site {
enabled: boolean;
spa: boolean;
not_found_file: string;
- last_deployed: string;
+ index_file: string;
+ trailing_slash: boolean | null;
+ created_at: string;
forward_rules: ForwardRule[];
custom_headers: CustomHeaders[];
}
@@ -45,6 +47,8 @@ export interface CreateSiteRequest {
domain: string;
enabled: boolean;
spa: boolean;
+ not_found_file: string;
+ index_file: string;
}
export interface GetAllSitesResponse {
diff --git a/frontend/src/pages/NewSite/NewSite.tsx b/frontend/src/pages/NewSite/NewSite.tsx
index 577a40e..c18888c 100644
--- a/frontend/src/pages/NewSite/NewSite.tsx
+++ b/frontend/src/pages/NewSite/NewSite.tsx
@@ -100,6 +100,8 @@ const NewSite = () => {
domain,
spa,
enabled: true,
+ not_found_file: '',
+ index_file: '',
});
console.log('Created site:', data);
};
diff --git a/frontend/src/pages/SiteOverview/OverviewTab.tsx b/frontend/src/pages/SiteOverview/OverviewTab.tsx
index 3eb7487..4b4121a 100644
--- a/frontend/src/pages/SiteOverview/OverviewTab.tsx
+++ b/frontend/src/pages/SiteOverview/OverviewTab.tsx
@@ -79,7 +79,7 @@ const OverviewTab = ({ site }: { site: Site }) => (