Skip to content

Commit

Permalink
✨ feat: update from litecart cli
Browse files Browse the repository at this point in the history
  • Loading branch information
shurco committed Sep 28, 2023
1 parent 626ab1d commit 34bc1f0
Show file tree
Hide file tree
Showing 14 changed files with 648 additions and 14 deletions.
1 change: 1 addition & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"program": "${workspaceFolder}/cmd",
"args": ["serve", "--dev"]
//"args": ["init"]
//"args": ["update"]
//"args": ["serve", "--no-site"]
//"args": ["serve"]
//"args": ["serve", "--help"]
Expand Down
31 changes: 31 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/spf13/cobra"

app "github.com/shurco/litecart/internal"
"github.com/shurco/litecart/pkg/update"
)

var (
Expand All @@ -25,13 +26,20 @@ var rootCmd = &cobra.Command{
}

func main() {
update.SetVersion(&update.Version{
CurrentVersion: version,
GitCommit: gitCommit,
BuildDate: buildDate,
})

rootCmd.SetHelpCommand(&cobra.Command{
Use: "no-help",
Hidden: true,
})

rootCmd.AddCommand(cmdInit())
rootCmd.AddCommand(cmdServe())
rootCmd.AddCommand(cmdUpdate())

if err := rootCmd.Execute(); err != nil {
os.Exit(1)
Expand All @@ -46,6 +54,7 @@ func cmdServe() *cobra.Command {
Short: "Starts the web server (default to 0.0.0.0:8080)",
Run: func(serveCmd *cobra.Command, args []string) {
if err := app.NewApp(httpAddr, httpsAddr, noSite, devMode); err != nil {
fmt.Print(err)
os.Exit(1)
}
},
Expand Down Expand Up @@ -87,3 +96,25 @@ func cmdInit() *cobra.Command {

return cmd
}

func cmdUpdate() *cobra.Command {
cmd := &cobra.Command{
Use: "update",
Short: "Update app to the latest version",
Run: func(serveCmd *cobra.Command, args []string) {
cfg := &update.Config{
Owner: "shurco",
Repo: "litecart",
CurrentVersion: version,
ArchiveExecutable: "litecart",
}
err := update.Init(cfg)
if err != nil {
fmt.Print(err)
os.Exit(1)
}
},
}

return cmd
}
6 changes: 3 additions & 3 deletions internal/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ import (
)

var (
DevMode bool
MainDomain string
log zerolog.Logger
DevMode bool
//MainDomain string
log zerolog.Logger
)

// NewApp is ...
Expand Down
47 changes: 47 additions & 0 deletions internal/handlers/private/setting.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,63 @@
package handlers

import (
"context"
"database/sql"
"encoding/json"
"time"

"github.com/gofiber/fiber/v2"

"github.com/shurco/litecart/internal/models"
"github.com/shurco/litecart/internal/queries"
"github.com/shurco/litecart/pkg/errors"
"github.com/shurco/litecart/pkg/update"
"github.com/shurco/litecart/pkg/webutil"
)

// Version is ...
// [get] /api/_/version
func Version(c *fiber.Ctx) error {
db := queries.DB()

session, err := db.GetSession("update")
if err != nil && err != sql.ErrNoRows {
return webutil.StatusBadRequest(c, err.Error())
}

version := (*update.Version)(nil)
if err == sql.ErrNoRows {
version = update.VersionInfo()

release, err := update.FetchLatestRelease(context.Background(), "shurco", "litecart")
if err != nil {
return webutil.StatusBadRequest(c, err.Error())
}

if version.CurrentVersion != release.Name {
version.NewVersion = release.Name
version.ReleaseURL = release.GetUrl()
}

if err := db.DeleteSession("update"); err != nil {
return webutil.StatusBadRequest(c, err.Error())
}

json, _ := json.Marshal(version)
expires := time.Now().Add(24 * time.Hour).Unix()
if err := db.AddSession("update", string(json), expires); err != nil {
return webutil.StatusBadRequest(c, err.Error())
}
}

if session != "" {
version = new(update.Version)
json.Unmarshal([]byte(session), version)
}

return webutil.Response(c, fiber.StatusOK, "Version", version)
}

// Settings is ...
// [get] /api/_/settings
func Settings(c *fiber.Ctx) error {
Expand Down
4 changes: 4 additions & 0 deletions internal/handlers/private/setting.http
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ Content-Type: application/json
"password":"Pass123"
}

###
# @name version
GET {{host}}/api/_/version

###
# @name settings
GET {{host}}/api/_/settings
Expand Down
3 changes: 2 additions & 1 deletion internal/queries/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,8 @@ func (q *SettingQueries) CheckSubdomain(name string) bool {
// GetSession is ...
func (q *SettingQueries) GetSession(key string) (string, error) {
var value string
err := q.DB.QueryRowContext(context.TODO(), `SELECT value FROM session WHERE key = ?`, key).Scan(&value)
expires := time.Now().Unix()
err := q.DB.QueryRowContext(context.TODO(), `SELECT value FROM session WHERE key = ? AND expires > ?`, key, expires).Scan(&value)
if err != nil {
return "", err
}
Expand Down
2 changes: 2 additions & 0 deletions internal/routes/api_private_routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
func ApiPrivateRoutes(c *fiber.App) {
c.Post("/api/install", handlers.Install)

c.Get("/api/_/version", middleware.JWTProtected(), handlers.Version)

sign := c.Group("/api/sign")
sign.Post("/in", handlers.SignIn)
sign.Post("/out", middleware.JWTProtected(), handlers.SignOut)
Expand Down
38 changes: 38 additions & 0 deletions pkg/archive/archive.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package archive

import (
"fmt"
"io"
"os"
"path/filepath"
"strings"
)

// Archive is ...
type Archive interface {
Directory(name string) error
Header(os.FileInfo) (io.Writer, error)
Close() error
}

func extractFile(path string, mode os.FileMode, data io.Reader, dest string) error {
target := filepath.Join(dest, filepath.FromSlash(path))
if !strings.HasPrefix(target, filepath.Clean(dest)+string(os.PathSeparator)) {
return fmt.Errorf("path %q escapes archive destination", target)
}

if err := os.MkdirAll(filepath.Dir(target), 0755); err != nil {
return err
}

file, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, mode)
if err != nil {
return err
}
if _, err := io.Copy(file, data); err != nil {
file.Close()
os.Remove(target)
return err
}
return file.Close()
}
93 changes: 93 additions & 0 deletions pkg/archive/tar.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package archive

import (
"archive/tar"
"compress/gzip"
"fmt"
"io"
"os"
"time"
)

// TarArchive is ...
type TarArchive struct {
dir string
tarw *tar.Writer
gzw *gzip.Writer
file io.Closer
}

// NewTarArchive is ...
func NewTarArchive(w io.WriteCloser) Archive {
gzw := gzip.NewWriter(w)
tarw := tar.NewWriter(gzw)
return &TarArchive{"", tarw, gzw, w}
}

// Directory is ...
func (a *TarArchive) Directory(name string) error {
a.dir = name + "/"
return a.tarw.WriteHeader(&tar.Header{
Name: a.dir,
Mode: 0755,
Typeflag: tar.TypeDir,
ModTime: time.Now(),
})
}

// Header is ...
func (a *TarArchive) Header(fi os.FileInfo) (io.Writer, error) {
head, err := tar.FileInfoHeader(fi, "")
if err != nil {
return nil, fmt.Errorf("can't make tar header: %v", err)
}
head.Name = a.dir + head.Name
if err := a.tarw.WriteHeader(head); err != nil {
return nil, fmt.Errorf("can't add tar header: %v", err)
}
return a.tarw, nil
}

// Close is ...
func (a *TarArchive) Close() error {
if err := a.tarw.Close(); err != nil {
return err
}
if err := a.gzw.Close(); err != nil {
return err
}
return a.file.Close()
}

// Extract extracts the tar archive at src to dest.
func ExtractTar(src, dest string) error {
ar, err := os.Open(src)
if err != nil {
return err
}
defer ar.Close()

gzr, err := gzip.NewReader(ar)
if err != nil {
return err
}
defer gzr.Close()

tr := tar.NewReader(gzr)
for {
header, err := tr.Next()
if err != nil {
if err == io.EOF {
return nil
}
return err
}
if header.Typeflag == tar.TypeReg {
mode := header.FileInfo().Mode()
err := extractFile(header.Name, mode, tr, dest)
if err != nil {
return fmt.Errorf("extract %s: %v", header.Name, err)
}
}
}
}
83 changes: 83 additions & 0 deletions pkg/archive/zip.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package archive

import (
"archive/zip"
"fmt"
"io"
"os"
)

type ZipArchive struct {
dir string
zipw *zip.Writer
file io.Closer
}

// NewZipArchive is ...
func NewZipArchive(w io.WriteCloser) Archive {
return &ZipArchive{"", zip.NewWriter(w), w}
}

// Directory is ...
func (a *ZipArchive) Directory(name string) error {
a.dir = name + "/"
return nil
}

// Header is ...
func (a *ZipArchive) Header(fi os.FileInfo) (io.Writer, error) {
head, err := zip.FileInfoHeader(fi)
if err != nil {
return nil, fmt.Errorf("can't make zip header: %v", err)
}
head.Name = a.dir + head.Name
head.Method = zip.Deflate
w, err := a.zipw.CreateHeader(head)
if err != nil {
return nil, fmt.Errorf("can't add zip header: %v", err)
}
return w, nil
}

// Close is ...
func (a *ZipArchive) Close() error {
if err := a.zipw.Close(); err != nil {
return err
}
return a.file.Close()
}

// Extract extracts the zip archive at src to dest.
func ExtractZip(src, dest string) error {
ar, err := os.Open(src)
if err != nil {
return err
}
defer ar.Close()

info, err := ar.Stat()
if err != nil {
return err
}
zr, err := zip.NewReader(ar, info.Size())
if err != nil {
return err
}

for _, zf := range zr.File {
if !zf.Mode().IsRegular() {
continue
}

data, err := zf.Open()
if err != nil {
return err
}
err = extractFile(zf.Name, zf.Mode(), data, dest)
data.Close()
if err != nil {
return fmt.Errorf("extract %s: %v", zf.Name, err)
}
}
return nil
}
Loading

0 comments on commit 34bc1f0

Please sign in to comment.