init - add project files

This commit is contained in:
2025-03-06 23:54:11 -05:00
commit e724ff1120
1363 changed files with 897467 additions and 0 deletions

View File

@@ -0,0 +1,167 @@
package main
import (
"fmt"
"os"
"path/filepath"
"maxwarden/basic"
"maxwarden/security"
"regexp"
"strings"
)
var dedupMap = make(map[string]bool)
// Walk the FS tree and search for `.go` files containing calls to `InlineStyle()`
// Collect the inputs to each call (they must be string literals), expand shorthand macros, and
func generateInlineStyles() {
fmt.Printf("Compiling Inline Styles")
inlineStyleRegex := regexp.MustCompile("InlineStyle\\((((?:'[^']*')|(?:\"[^\"]*\")|(`(?:[^`]|[\r\n])*?`)))\\)")
// these are the directories that get scanned
var dirs = [2]string{"handlers", "ui"}
var matches []string
for _, dir := range dirs {
err := filepath.Walk(dir, func(pathStr string, info os.FileInfo, err error) error {
if strings.HasSuffix(info.Name(), ".go") {
pathStr = filepath.ToSlash(pathStr)
handleErr(err)
file, err := os.Open(pathStr)
handleErr(err)
defer file.Close()
content, contentErr := os.ReadFile(pathStr)
if contentErr != nil {
return contentErr
}
s := string(content)
// only pre-process page & component files
inlineStyleRegex.ReplaceAllStringFunc(s, func(match string) string {
submatch := inlineStyleRegex.FindStringSubmatch(match)
if len(submatch) > 1 {
submatch[1] = strings.TrimPrefix(submatch[1], "\"")
submatch[1] = strings.TrimPrefix(submatch[1], "'")
submatch[1] = strings.TrimPrefix(submatch[1], "`")
submatch[1] = strings.TrimSuffix(submatch[1], "\"")
submatch[1] = strings.TrimSuffix(submatch[1], "'")
submatch[1] = strings.TrimSuffix(submatch[1], "`")
submatch[1] = strings.ReplaceAll(submatch[1], "\n", " ")
submatch[1] = strings.ReplaceAll(submatch[1], "\t", "")
rawInput := submatch[1] // this is the input before we process it
// Skip duplicates
_, found := dedupMap[rawInput]
if !found {
cssHash, _ := security.HighwayHash58(rawInput)
cssHash = basic.GetFirstNChars(cssHash, 8)
// Expand custom css macros (see comments below for details)
submatch[1] = expandMe(submatch[1], cssHash)
submatch[1] = expandMedia(submatch[1])
submatch[1] = expandColor(submatch[1])
submatch[1] = expandSpacing(submatch[1])
matches = append(matches, submatch[1])
dedupMap[rawInput] = true
}
}
// We aren't actually replacing anything in the src file, we just needed to iterate over the regex matches
return ""
})
}
return nil
})
handleErr(err)
}
outputCSS := "/* " + METAGEN_AUTO_COMMENT + " */\n"
outputCSS += strings.Join(matches, "")
os.WriteFile("./wwwroot/css/style.metagen.css", []byte(outputCSS), 0664)
printStatus(true)
}
// Expand spacing macro
// Ex:
//
// padding: $5;
//
// => padding: calc(var(--spacing) * 5);
func expandSpacing(input string) string {
re := regexp.MustCompile(`\$([0-9]+(?:\.[0-9]+)?)`)
transformed := re.ReplaceAllStringFunc(input, func(match string) string {
if len(re.FindStringSubmatch(match)) >= 2 {
number := re.FindStringSubmatch(match)[1]
return fmt.Sprintf("calc(var(--spacing) * %s)", number)
}
return ""
})
return transformed
}
// Expand color macros:
func expandColor(input string) string {
re := regexp.MustCompile(`\$color\((.*?)(?:\/(0*(?:[1-9][0-9]?|100)))?\)`)
transformed := re.ReplaceAllStringFunc(input, func(match string) string {
if len(re.FindStringSubmatch(match)) == 3 {
if re.FindStringSubmatch(match)[2] == "" {
return fmt.Sprintf("var(--color-%s)", re.FindStringSubmatch(match)[1])
} else {
return fmt.Sprintf("oklch(from var(--color-%s) l c h / %s%%)", re.FindStringSubmatch(match)[1], re.FindStringSubmatch(match)[2])
}
}
return ""
})
return transformed
}
// Expand shorthand media queries.
// Ex:
//
// media md { ... }
//
// => media screen and (min-width: 768px) { ... }
func expandMedia(input string) string {
input = strings.ReplaceAll(input, "$dark", "(prefers-color-scheme: dark)")
input = strings.ReplaceAll(input, "$light", "(prefers-color-scheme: light)")
input = strings.ReplaceAll(input, "$xs-", "screen and (max-width: 639px)")
input = strings.ReplaceAll(input, "$sm-", "screen and (max-width: 767px)")
input = strings.ReplaceAll(input, "$md-", "screen and (max-width: 1023px)")
input = strings.ReplaceAll(input, "$lg-", "screen and (max-width: 1279px)")
input = strings.ReplaceAll(input, "$xl-", "screen and (max-width: 1535px)")
input = strings.ReplaceAll(input, "$sm", "screen and (min-width: 640px)")
input = strings.ReplaceAll(input, "$md", "screen and (min-width: 768px)")
input = strings.ReplaceAll(input, "$lg", "screen and (min-width: 1024px)")
input = strings.ReplaceAll(input, "$xl", "screen and (min-width: 1280px)")
input = strings.ReplaceAll(input, "$xx", "screen and (min-width: 1536px)")
return input
}
// Expand "$me" macro with inline style attribute
// Ex:
//
// $me { ... }
//
// => [__inlinecss_{REPLACEMENT_ID}] { ... }
func expandMe(input string, replacementId string) string {
return strings.ReplaceAll(input, "$me", fmt.Sprintf("[__inlinecss_%s]", replacementId))
}

View File

@@ -0,0 +1,52 @@
package main
import (
"fmt"
"os"
"os/exec"
"runtime"
)
func compileJet() {
fmt.Printf("Compiling Jet generator")
os.Setenv("CGO_ENABLED", "1")
cmd := exec.Command("go", "build", "./cmd/jet")
cmd.Dir = "./tools/jet-2.12.0"
handleCmdOutput(cmd.CombinedOutput())
}
func generateJetModels() {
bin := ""
jetdir := ".jet"
if runtime.GOOS == "windows" {
bin = "./tools/jet-2.12.0/jet.exe"
} else {
bin = "./tools/jet-2.12.0/jet"
}
os.RemoveAll(jetdir)
// compile bin if not exists
if _, err := os.Stat(bin); err != nil {
compileJet()
}
fmt.Printf("Generating SQL models (jet)")
if _, err := os.Stat("passwords.db"); err != nil {
printStatus(false)
fmt.Println("\n" + err.Error())
os.Exit(1)
}
databaseType := "sqlite"
cmd := exec.Command(bin, "-source="+databaseType, "-dsn=file:passwords.db", "-schema=maxwarden", "-path="+jetdir)
handleCmdOutput(cmd.CombinedOutput())
printStatus(true)
}

View File

@@ -0,0 +1,29 @@
package main
import (
"fmt"
"os"
)
// set debug constant inside the "config" package
func generateDebugConfig() {
fmt.Printf("Generating DEBUG/RELEASE config")
code := METAGEN_AUTO_COMMENT + "\npackage config\n\nconst (\n"
if envtype == ENVIRONMENT_DEV {
code += " DEBUG = true"
} else {
code += " DEBUG = false"
}
code += "\n)\n"
// open file and write code to it
in := []byte(code)
err := os.WriteFile("./config/debug.metagen.go", in, 0644)
handleErr(err)
printStatus(true)
}

111
cmd/metagen/main.go Normal file
View File

@@ -0,0 +1,111 @@
package main
import (
"flag"
"fmt"
"os"
"os/exec"
)
var envtype int // set by user with cli flag
const (
ENVIRONMENT_DEV = iota
ENVIRONMENT_STAGING = iota
ENVIRONMENT_PRODUCTION = iota
)
const METAGEN_AUTO_COMMENT = "// @Metagen -- THIS FILE WAS AUTOGENERATED OR PREPROCESSED BY METAGEN - DO NOT EDIT BY HAND"
// metagen - code generator application
//
// Generates code for other applications, such as the server application
func main() {
env := flag.String("env", "dev", "The environment to run in: dev, staging, or production")
// Parse command-line flags
flag.Parse()
switch *env {
case "dev":
envtype = ENVIRONMENT_DEV
case "staging":
envtype = ENVIRONMENT_STAGING
case "production":
envtype = ENVIRONMENT_PRODUCTION
default:
fmt.Printf("Invalid environment specified: %s\n", *env)
fmt.Println("Allowed values are: dev, staging, or production")
os.Exit(1)
}
args := flag.Args()
for _, arg := range args {
switch arg {
case "build-all":
preBuild()
build()
goto End
case "build":
preBuild()
goto End
case "migrate":
migrations(args)
goto End
default:
helpmsg()
goto End
}
}
End:
if len(args) == 0 {
helpmsg()
}
}
func helpmsg() {
fmt.Println("Usage: metagen [options...]")
fmt.Println("build :: Build dependencies, generate code, then build final executables.")
fmt.Println("migrate [up, down, goto {V}, create {migration name}] :: Deploy and create SQL migrations.")
os.Exit(1)
}
func preBuild() {
if envtype == ENVIRONMENT_DEV {
fmt.Println("[DEBUG ENVIRONMENT]")
} else if envtype == ENVIRONMENT_STAGING || envtype == ENVIRONMENT_PRODUCTION {
fmt.Println("[RELEASE ENVIRONMENT]")
}
// db creation
maybeCreateSqliteDb()
// code generation
generateInlineStyles()
generateDebugConfig()
generateJetModels()
}
func build() {
compileServer()
}
func compileServer() {
var out []byte
var err error
fmt.Printf("Compiling Server Binary")
if envtype == ENVIRONMENT_DEV {
// include extra flags for the GC
out, err = exec.Command("go", "build", "-gcflags=all=-N -l", "./cmd/server").CombinedOutput()
} else {
out, err = exec.Command("go", "build", "./cmd/server").CombinedOutput()
}
handleCmdOutput(out, err)
printStatus(true)
}

242
cmd/metagen/migrations.go Normal file
View File

@@ -0,0 +1,242 @@
package main
import (
"errors"
"fmt"
"log"
"os"
"path/filepath"
"strconv"
"strings"
"time"
"github.com/golang-migrate/migrate/v4"
_ "github.com/golang-migrate/migrate/v4/database/sqlite3"
_ "github.com/golang-migrate/migrate/v4/source/file"
)
// create
func maybeCreateSqliteDb() {
if _, err := os.Stat("./passwords.db"); err != nil {
fmt.Printf("Creating new sqlite database")
err := os.WriteFile("./passwords.db", nil, 0755)
if err != nil {
fmt.Printf("Error creating Sqlite database.")
os.Exit(1)
}
m, err := migrate.New(
"file://./migrations",
"sqlite3://passwords.db",
)
if err != nil {
printStatus(false)
fmt.Println(err.Error())
os.Exit(1)
}
mErr := m.Up()
if mErr != nil {
printStatus(false)
fmt.Println(mErr.Error())
os.Exit(1)
}
printStatus(true)
}
}
// handle the running and creation of migrations
func migrations(args []string) {
if len(args) < 2 {
fmt.Println("Usage: metagen migrate [up, down, goto {V}, create {migration name}]")
os.Exit(1)
}
maybeCreateSqliteDb()
m, err := migrate.New(
"file://./migrations",
"sqlite3://passwords.db",
)
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
migrateNum := 0
if len(args) >= 3 && args[1] != "create" {
var parseErr error
migrateNum, parseErr = strconv.Atoi(args[2])
if parseErr != nil {
fmt.Println("Please provide a valid migration number.")
os.Exit(1)
}
}
m.PrefetchMigrations = migrate.DefaultPrefetchMigrations
switch args[1] {
case "up":
err := m.Up()
if err != nil {
fmt.Println(err.Error())
}
case "down":
err := m.Down()
if err != nil {
fmt.Println(err.Error())
}
case "goto":
err := m.Migrate(uint(migrateNum))
if err != nil {
fmt.Println(err.Error())
}
case "create":
if len(args) < 3 {
fmt.Println("Please provide a name for the new migration.")
os.Exit(1)
}
createCmd("./migrations", time.Now(), defaultTimeFormat, args[2], "sql", true, 7, true)
}
}
const (
defaultTimeFormat = "20060102150405"
defaultTimezone = "UTC"
)
var (
errInvalidSequenceWidth = errors.New("Digits must be positive")
errIncompatibleSeqAndFormat = errors.New("The seq and format options are mutually exclusive")
errInvalidTimeFormat = errors.New("Time format may not be empty")
)
func createFile(filename string) error {
// create exclusive (fails if file already exists)
// os.Create() specifies 0666 as the FileMode, so we're doing the same
f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
if err != nil {
return err
}
return f.Close()
}
func nextSeqVersion(matches []string, seqDigits int) (string, error) {
if seqDigits <= 0 {
return "", errInvalidSequenceWidth
}
nextSeq := uint64(1)
if len(matches) > 0 {
filename := matches[len(matches)-1]
matchSeqStr := filepath.Base(filename)
idx := strings.Index(matchSeqStr, "_")
if idx < 1 { // Using 1 instead of 0 since there should be at least 1 digit
return "", fmt.Errorf("Malformed migration filename: %s", filename)
}
var err error
matchSeqStr = matchSeqStr[0:idx]
nextSeq, err = strconv.ParseUint(matchSeqStr, 10, 64)
if err != nil {
return "", err
}
nextSeq++
}
version := fmt.Sprintf("%0[2]*[1]d", nextSeq, seqDigits)
if len(version) > seqDigits {
return "", fmt.Errorf("Next sequence number %s too large. At most %d digits are allowed", version, seqDigits)
}
return version, nil
}
func timeVersion(startTime time.Time, format string) (version string, err error) {
switch format {
case "":
err = errInvalidTimeFormat
case "unix":
version = strconv.FormatInt(startTime.Unix(), 10)
case "unixNano":
version = strconv.FormatInt(startTime.UnixNano(), 10)
default:
version = startTime.Format(format)
}
return
}
func createCmd(dir string, startTime time.Time, format string, name string, ext string, seq bool, seqDigits int, print bool) error {
if seq && format != defaultTimeFormat {
return errIncompatibleSeqAndFormat
}
var version string
var err error
dir = filepath.Clean(dir)
ext = "." + strings.TrimPrefix(ext, ".")
if seq {
matches, err := filepath.Glob(filepath.Join(dir, "*"+ext))
if err != nil {
return err
}
version, err = nextSeqVersion(matches, seqDigits)
if err != nil {
return err
}
} else {
version, err = timeVersion(startTime, format)
if err != nil {
return err
}
}
versionGlob := filepath.Join(dir, version+"_*"+ext)
matches, err := filepath.Glob(versionGlob)
if err != nil {
return err
}
if len(matches) > 0 {
return fmt.Errorf("duplicate migration version: %s", version)
}
if err = os.MkdirAll(dir, os.ModePerm); err != nil {
return err
}
for _, direction := range []string{"up", "down"} {
basename := fmt.Sprintf("%s_%s.%s%s", version, name, direction, ext)
filename := filepath.Join(dir, basename)
if err = createFile(filename); err != nil {
return err
}
if print {
absPath, _ := filepath.Abs(filename)
log.Println(absPath)
}
}
return nil
}

114
cmd/metagen/util.go Normal file
View File

@@ -0,0 +1,114 @@
package main
import (
"fmt"
"go/ast"
. "maxwarden/basic"
"net/url"
"os"
"reflect"
"regexp"
)
func printStatus(b bool) {
var status string
if b {
status = "SUCCESS"
} else {
status = "FAILED"
}
fmt.Printf("... %s\n", status)
}
func handleCmdOutput(out []byte, err error) {
if err != nil {
fmt.Printf("\n%s\n", out)
fmt.Printf("%s\n", err.Error())
os.Exit(1)
}
}
func handleErr(err error) {
if err != nil {
printStatus(false)
fmt.Println(err.Error())
os.Exit(1)
}
}
// convert an sqlite DSN to a file name
func parseSQLiteFilename(dsn string) (string, error) {
u, err := url.Parse(dsn)
if err != nil {
return "", err
}
// For simple file paths
if u.Scheme == "" {
return u.Path, nil
}
// For more complex DSNs
if u.Scheme == "file" {
return u.Opaque, nil
}
return "", fmt.Errorf("invalid DSN format: %s", dsn)
}
// given an ast.Decl, and destination struct, look at the struct for any
// boolean fields with the struct tag `Note`. If valid notes are found in the given Decl doc string
// set the tagged booleans to true on the input struct.
// file is the file that the decl originated from.
func parseNotesFromDocComment(decl ast.Decl, file *os.File, dest any) error {
re := regexp.MustCompile(`@(\w+)`)
var identifier string
var docstring string
var docNotes []string
var validNotes []string
// check if decl is a function
if funcDecl, ok := decl.(*ast.FuncDecl); ok {
identifier = funcDecl.Name.Name
docstring = funcDecl.Doc.Text()
}
matches := re.FindAllStringSubmatch(docstring, -1)
for _, match := range matches {
// match[1] contains the first capture group (the word after '@')
docNotes = append(docNotes, match[1])
}
v := reflect.ValueOf(dest).Elem()
t := v.Type()
if v.Kind() != reflect.Struct {
return fmt.Errorf("\ndestination struct must be a pointer to a struct")
}
for i := 0; i < v.NumField(); i++ {
field := t.Field(i)
// Look for the `Note` tag in the struct field
if field.Tag == "note:\"true\"" {
if Contains(docNotes, field.Name) {
v.Field(i).SetBool(true)
}
validNotes = append(validNotes, field.Name)
}
}
for _, v := range docNotes {
if !Contains(validNotes, v) {
return fmt.Errorf("\n`%s`: Unknown note `@%s`, Identifier: `%s`\n\tValid values are: %v", file.Name(), v, identifier, validNotes)
}
}
return nil
}

28
cmd/passgen/main.go Normal file
View File

@@ -0,0 +1,28 @@
package main
import (
"maxwarden/entries"
"maxwarden/security"
"os"
)
func main() {
if len(os.Args) == 2 {
passHash, _ := security.HashPassword(os.Args[1])
testData := []entries.Secret{}
for range 10 {
dummyData := entries.Secret{ID: security.RandBase58String(32), Description: "Twitter / X.com", URL: "https://x.com", Notes: "2fa is enabled for this account.", Username: "@johntwitter", Password: "##CORRECT_HORSE_BATTERY_STAPLE_51"}
testData = append(testData, dummyData)
}
masterKey := security.SHA512_58(os.Args[1])
cryptData, _ := security.EncryptDataWithKey(&testData, masterKey)
println(passHash)
println(cryptData)
} else {
println("Please input a password as first program argument")
}
}