7 Commits

Author SHA1 Message Date
122651677f set views by env 2025-04-11 18:17:33 +02:00
af11f88769 add check 2025-04-11 18:11:04 +02:00
0bcec807c8 add test 2025-04-11 18:10:55 +02:00
a3b066859b set static file by env 2025-04-11 18:10:37 +02:00
b349c4baba update header 2025-04-11 18:08:57 +02:00
e406eda9c9 add editorder view 2025-04-11 17:32:17 +02:00
a1fc053fa8 give go module proper name 2025-04-11 17:31:46 +02:00
20 changed files with 197 additions and 31 deletions

View File

@@ -11,9 +11,9 @@ import (
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"example.com/gin/test/models"
//"example.com/gin/test/services"
"example.com/gin/test/repositories"
"git.dynamicdiscord.de/kalipso/zineshop/models"
//"git.dynamicdiscord.de/kalipso/zineshop/services"
"git.dynamicdiscord.de/kalipso/zineshop/repositories"
)
type CartItemController interface {

View File

@@ -5,8 +5,8 @@ import (
"net/http"
"strconv"
"example.com/gin/test/models"
"example.com/gin/test/repositories"
"git.dynamicdiscord.de/kalipso/zineshop/models"
"git.dynamicdiscord.de/kalipso/zineshop/repositories"
"github.com/gin-gonic/gin"
)

View File

@@ -9,9 +9,9 @@ import (
"github.com/gin-gonic/gin"
"example.com/gin/test/models"
//"example.com/gin/test/services"
"example.com/gin/test/repositories"
"git.dynamicdiscord.de/kalipso/zineshop/models"
//"git.dynamicdiscord.de/kalipso/zineshop/services"
"git.dynamicdiscord.de/kalipso/zineshop/repositories"
)
type CRUDController interface {

View File

@@ -7,9 +7,9 @@ import (
"github.com/gin-gonic/gin"
"example.com/gin/test/models"
"example.com/gin/test/repositories"
"example.com/gin/test/services"
"git.dynamicdiscord.de/kalipso/zineshop/models"
"git.dynamicdiscord.de/kalipso/zineshop/repositories"
"git.dynamicdiscord.de/kalipso/zineshop/services"
)
type UserController struct{}

View File

@@ -23,5 +23,91 @@
tailwindcss
];
};
})) {};
packages.zineshop = nixpkgs.legacyPackages.x86_64-linux.buildGoModule {
pname = "zineshop";
version = "1.0";
vendorHash = "sha256-0M/xblZXVw4xIFZeDewYrFu7VGUCsPTPG13r9ZpTGJo=";
src = ./.;
postInstall = ''
cp -r views $out/
cp -r static $out/
'';
};
checks = let
checkArgs = {
pkgs = pkgs;
inherit self;
};
in {
zineshop = import ./test/test.nix checkArgs;
};
})) {
nixosModules.zineshop = { config, lib, pkgs, ... }:
let
cfg = config.services.zineshop;
zineshop-pkg = self.packages.x86_64-linux.zineshop;
in
{
options = {
services.zineshop = {
enable = lib.mkOption {
default = false;
type = lib.types.bool;
description = lib.mdDoc ''
Enables zineshop
'';
};
};
};
config = lib.mkIf cfg.enable {
environment.systemPackages = [ zineshop-pkg ];
users = {
groups.zineshop = {};
users.zineshop = {
description = "zineshop user";
group = "zineshop";
isNormalUser = true;
};
};
systemd.services.zineshop = {
description = "zineshop daemon";
serviceConfig = {
Type = "simple";
ExecStart = "${zineshop-pkg}/bin/zineshop";
Restart = "on-failure";
};
environment = {
SQLITE_DB = "/var/lib/zineshop/zineshop.db";
SECRET = "secretforjwt"; #TODO: BAD!
PORT = "8080";
STATIC = "/var/lib/zineshop/static";
VIEWS = "/var/lib/zineshop/views";
};
preStart = ''
mkdir -m 0770 -p "/var/lib/zineshop"
chown zineshop:zineshop "/var/lib/zineshop"
cp -r ${zineshop-pkg}/views /var/lib/zineshop/
cp -r ${zineshop-pkg}/static /var/lib/zineshop/
'';
wantedBy = [ "default.target" ];
environment = {
USER = "zineshop";
HOME = "/var/lib/zineshop";
};
};
};
};
};
}

2
go.mod
View File

@@ -1,4 +1,4 @@
module example.com/gin/test
module git.dynamicdiscord.de/kalipso/zineshop
go 1.23.3

10
main.go
View File

@@ -9,9 +9,9 @@ import (
"github.com/gin-gonic/gin"
"github.com/joho/godotenv"
"example.com/gin/test/controllers"
"example.com/gin/test/middlewares"
"example.com/gin/test/repositories"
"git.dynamicdiscord.de/kalipso/zineshop/controllers"
"git.dynamicdiscord.de/kalipso/zineshop/middlewares"
"git.dynamicdiscord.de/kalipso/zineshop/repositories"
)
var (
@@ -52,8 +52,8 @@ func main() {
server.Use(gin.Recovery())
server.Use(gin.Logger())
server.Static("/static", "./static")
server.LoadHTMLGlob("views/*.html")
server.Static("/static", os.Getenv("STATIC"))
server.LoadHTMLGlob(fmt.Sprintf("%s/*.html", os.Getenv("VIEWS")))
apiRoutes := server.Group("/api")
//apiRoutes.Use(middlewares.BasicAuth())

View File

@@ -9,8 +9,8 @@ import(
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v5"
//"example.com/gin/test/models"
"example.com/gin/test/repositories"
//"git.dynamicdiscord.de/kalipso/zineshop/models"
"git.dynamicdiscord.de/kalipso/zineshop/repositories"
)
type AuthValidator struct {

View File

@@ -4,7 +4,7 @@ import (
"gorm.io/gorm"
"strconv"
"example.com/gin/test/models"
"git.dynamicdiscord.de/kalipso/zineshop/models"
)
type OrderRepository interface {

View File

@@ -4,7 +4,7 @@ import(
"strconv"
"gorm.io/gorm"
"example.com/gin/test/models"
"git.dynamicdiscord.de/kalipso/zineshop/models"
)
type CartItemRepository interface {

View File

@@ -5,7 +5,7 @@ import (
"gorm.io/gorm"
"os"
"example.com/gin/test/models"
"git.dynamicdiscord.de/kalipso/zineshop/models"
)
var (

View File

@@ -4,7 +4,7 @@ import(
"strconv"
"gorm.io/gorm"
"example.com/gin/test/models"
"git.dynamicdiscord.de/kalipso/zineshop/models"
)
type ShopItemRepository interface {

View File

@@ -5,7 +5,7 @@ import(
"gorm.io/gorm"
"example.com/gin/test/models"
"git.dynamicdiscord.de/kalipso/zineshop/models"
)
type TagRepository interface {

View File

@@ -3,7 +3,7 @@ package repositories
import(
"gorm.io/gorm"
"example.com/gin/test/models"
"git.dynamicdiscord.de/kalipso/zineshop/models"
)
type UserRepository interface {

View File

@@ -3,8 +3,8 @@ package services
import(
"fmt"
"example.com/gin/test/models"
"example.com/gin/test/repositories"
"git.dynamicdiscord.de/kalipso/zineshop/models"
"git.dynamicdiscord.de/kalipso/zineshop/repositories"
)
var(

View File

@@ -7,8 +7,8 @@ import(
"github.com/golang-jwt/jwt/v5"
"example.com/gin/test/models"
"example.com/gin/test/repositories"
"git.dynamicdiscord.de/kalipso/zineshop/models"
"git.dynamicdiscord.de/kalipso/zineshop/repositories"
)
var(

21
test/lib.nix Normal file
View File

@@ -0,0 +1,21 @@
# tests/lib.nix
# based on https://blog.thalheim.io/2023/01/08/how-to-use-nixos-testing-framework-with-flakes/
# The first argument to this function is the test module itself
test:
# These arguments are provided by `flake.nix` on import, see checkArgs
{ pkgs, self}:
let
inherit (pkgs) lib;
# this imports the nixos library that contains our testing framework
nixos-lib = import (pkgs.path + "/nixos/lib") {};
in
(nixos-lib.runTest {
hostPkgs = pkgs;
# This speeds up the evaluation by skipping evaluating documentation (optional)
defaults.documentation.enable = lib.mkDefault false;
# This makes `self` available in the NixOS configuration of our virtual machines.
# This is useful for referencing modules or packages from your own flake
# as well as importing from other flakes.
node.specialArgs = { inherit self; };
imports = [ test ];
}).config.result

21
test/test.nix Normal file
View File

@@ -0,0 +1,21 @@
# ./tests/hello-world-server.nix
(import ./lib.nix) {
name = "from-nixos";
nodes = {
# `self` here is set by using specialArgs in `lib.nix`
node1 = { self, pkgs, ... }: {
imports = [ self.nixosModules.zineshop ];
services.zineshop.enable = true;
environment.systemPackages = [ pkgs.curl ];
};
};
testScript = ''
start_all() # wait for our service to start
node1.wait_for_unit("zineshop.service")
output = node1.succeed("curl localhost:8080")
# Check if our webserver returns the expected result
assert "Zine Shop" in output, f"'{output}' does not contain 'Zine Shop'"
'';
}

38
views/editorders.html Normal file
View File

@@ -0,0 +1,38 @@
{{ template "header.html" . }}
<div class="flex min-h-full flex-col justify-center px-6 py-12 lg:px-8">
<div class="sm:mx-auto sm:w-full sm:max-w-sm">
<img class="mx-auto h-10 w-auto" src="/static/img/circlea.png" alt="Your Company">
<h2 class="mt-10 text-center text-2xl/9 font-bold tracking-tight text-gray-900">Edit Orders</h2>
</div>
<div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
{{ range .data.orders }}
<form action="/order/{{ .Token }}/edit" method="POST">
<div class="max-w-md mx-auto mt-4">
<div class="flex">
<input type="text" id="name" name="name" value="{{ .Token }}" readonly="readonly" class="flex-grow border border-gray-300 rounded-md p-2 focus:outline-none focus:ring focus:ring-blue-500">
<div>
<select name="order-status" required class="bg-gray-50 border ml-4 border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
<option selected value="{{ .Status }}">{{ .Status }}</option>
<option value="AwaitingConfirmation">AwaitingConfirmation</option>
<option value="Received">Received</option>
<option value="AwaitingPayment">AwaitingPayment</option>
<option value="Payed">Payed</option>
<option value="ReadyForPickup">ReadyForPickup</option>
<option value="Shipped">Shipped</option>
<option value="Cancelled">Cancelled</option>
</select>
</div>
<button type="submit" name="action" value="update" class="bg-blue-600 text-white ml-4 rounded px-4 hover:bg-blue-700">Update</button>
<button type="button" class="bg-blue-600 text-white ml-4 mr-4 rounded px-4 hover:bg-blue-700"><a
href="/order/{{ .Token }}/print">Print</a></button>
<button type="button" class="bg-blue-600 text-white mr-4 rounded px-4 hover:bg-blue-700"><a
href="/order/{{ .Token }}">View</a></button>
<button type="submit" name="action" value="delete" class="bg-red-800 text-white rounded px-4 hover:bg-red-900">Delete</button>
</div>
</form>
{{ end }}
</div>
{{ template "footer.html" . }}

View File

@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>FreiRaum</title>
<title>Zine Shop</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="/static/output.css" rel="stylesheet">