mirror of
https://github.com/lordmathis/lemma.git
synced 2025-11-06 07:54:22 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c450b4ae2f | |||
| eb98f801a1 | |||
| f1f622cda3 | |||
| 5079f3c96d | |||
| 2861b1a719 | |||
| 9bc1b2ecd4 |
@@ -17,6 +17,8 @@ RUN CGO_ENABLED=1 GOOS=linux go build -o lemma ./cmd/server
|
|||||||
|
|
||||||
# Stage 3: Final stage
|
# Stage 3: Final stage
|
||||||
FROM debian:bookworm-slim
|
FROM debian:bookworm-slim
|
||||||
|
RUN apt-get update && apt-get install -y ca-certificates
|
||||||
|
RUN update-ca-certificates
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=backend-builder /app/lemma .
|
COPY --from=backend-builder /app/lemma .
|
||||||
COPY --from=frontend-builder /app/dist ./dist
|
COPY --from=frontend-builder /app/dist ./dist
|
||||||
|
|||||||
@@ -37,9 +37,10 @@ Lemma can be configured using environment variables. Here are the available conf
|
|||||||
- `LEMMA_WORKDIR`: Working directory for application data (default: "./data")
|
- `LEMMA_WORKDIR`: Working directory for application data (default: "./data")
|
||||||
- `LEMMA_STATIC_PATH`: Path to static files (default: "../app/dist")
|
- `LEMMA_STATIC_PATH`: Path to static files (default: "../app/dist")
|
||||||
- `LEMMA_PORT`: Port to run the server on (default: "8080")
|
- `LEMMA_PORT`: Port to run the server on (default: "8080")
|
||||||
- `LEMMA_APP_URL`: Full URL where the application is hosted
|
- `LEMMA_DOMAIN`: Domain name where the application is hosted for cookie authentication
|
||||||
- `LEMMA_CORS_ORIGINS`: Comma-separated list of allowed CORS origins
|
- `LEMMA_CORS_ORIGINS`: Comma-separated list of allowed CORS origins
|
||||||
- `LEMMA_JWT_SIGNING_KEY`: Key used for signing JWT tokens (autogenerated if not set)
|
- `LEMMA_JWT_SIGNING_KEY`: Key used for signing JWT tokens
|
||||||
|
- `LEMMA_LOG_LEVEL`: Logging level (defaults to DEBUG in development mode, INFO in production)
|
||||||
- `LEMMA_RATE_LIMIT_REQUESTS`: Number of allowed requests per window (default: 100)
|
- `LEMMA_RATE_LIMIT_REQUESTS`: Number of allowed requests per window (default: 100)
|
||||||
- `LEMMA_RATE_LIMIT_WINDOW`: Duration of the rate limit window (default: 15m)
|
- `LEMMA_RATE_LIMIT_WINDOW`: Duration of the rate limit window (default: 15m)
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
Generated documentation for all packages in the Lemma project.
|
Generated documentation for all packages in the Lemma project.
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
- [cmd/server](#cmd-server)
|
- [cmd/server](#cmd-server)
|
||||||
- [docs](#docs)
|
- [docs](#docs)
|
||||||
- [internal/app](#internal-app)
|
- [internal/app](#internal-app)
|
||||||
@@ -12,9 +11,11 @@ Generated documentation for all packages in the Lemma project.
|
|||||||
- [internal/db](#internal-db)
|
- [internal/db](#internal-db)
|
||||||
- [internal/git](#internal-git)
|
- [internal/git](#internal-git)
|
||||||
- [internal/handlers](#internal-handlers)
|
- [internal/handlers](#internal-handlers)
|
||||||
|
- [internal/logging](#internal-logging)
|
||||||
- [internal/models](#internal-models)
|
- [internal/models](#internal-models)
|
||||||
- [internal/secrets](#internal-secrets)
|
- [internal/secrets](#internal-secrets)
|
||||||
- [internal/storage](#internal-storage)
|
- [internal/storage](#internal-storage)
|
||||||
|
- [internal/testenv](#internal-testenv)
|
||||||
|
|
||||||
## cmd/server
|
## cmd/server
|
||||||
|
|
||||||
@@ -73,6 +74,7 @@ type Config struct {
|
|||||||
RateLimitRequests int
|
RateLimitRequests int
|
||||||
RateLimitWindow time.Duration
|
RateLimitWindow time.Duration
|
||||||
IsDevelopment bool
|
IsDevelopment bool
|
||||||
|
LogLevel logging.LogLevel
|
||||||
}
|
}
|
||||||
Config holds the configuration for the application
|
Config holds the configuration for the application
|
||||||
|
|
||||||
@@ -83,6 +85,9 @@ func LoadConfig() (*Config, error)
|
|||||||
LoadConfig creates a new Config instance with values from environment
|
LoadConfig creates a new Config instance with values from environment
|
||||||
variables
|
variables
|
||||||
|
|
||||||
|
func (c *Config) Redact() *Config
|
||||||
|
Redact redacts sensitive fields from a Config instance
|
||||||
|
|
||||||
type Options struct {
|
type Options struct {
|
||||||
Config *Config
|
Config *Config
|
||||||
Database db.Database
|
Database db.Database
|
||||||
@@ -547,11 +552,10 @@ func (h *Handler) DeleteFile() http.HandlerFunc
|
|||||||
DeleteFile godoc @Summary Delete file @Description Deletes a file in
|
DeleteFile godoc @Summary Delete file @Description Deletes a file in
|
||||||
the user's workspace @Tags files @ID deleteFile @Security CookieAuth
|
the user's workspace @Tags files @ID deleteFile @Security CookieAuth
|
||||||
@Param workspace_name path string true "Workspace name" @Param
|
@Param workspace_name path string true "Workspace name" @Param
|
||||||
file_path path string true "File path" @Success 204 "No Content
|
file_path path string true "File path" @Success 204 "No Content - File
|
||||||
- File deleted successfully" @Failure 400 {object} ErrorResponse
|
deleted successfully" @Failure 400 {object} ErrorResponse "Invalid
|
||||||
"Invalid file path" @Failure 404 {object} ErrorResponse "File not
|
file path" @Failure 404 {object} ErrorResponse "File not found"
|
||||||
found" @Failure 500 {object} ErrorResponse "Failed to delete file"
|
@Failure 500 {object} ErrorResponse "Failed to delete file" @Router
|
||||||
@Failure 500 {object} ErrorResponse "Failed to write response" @Router
|
|
||||||
/workspaces/{workspace_name}/files/{file_path} [delete]
|
/workspaces/{workspace_name}/files/{file_path} [delete]
|
||||||
|
|
||||||
func (h *Handler) DeleteWorkspace() http.HandlerFunc
|
func (h *Handler) DeleteWorkspace() http.HandlerFunc
|
||||||
@@ -822,6 +826,65 @@ type WorkspaceStats struct {
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## internal/logging
|
||||||
|
|
||||||
|
```go
|
||||||
|
package logging // import "lemma/internal/logging"
|
||||||
|
|
||||||
|
Package logging provides a simple logging interface for the server.
|
||||||
|
|
||||||
|
FUNCTIONS
|
||||||
|
|
||||||
|
func Debug(msg string, args ...any)
|
||||||
|
Debug logs a debug message
|
||||||
|
|
||||||
|
func Error(msg string, args ...any)
|
||||||
|
Error logs an error message
|
||||||
|
|
||||||
|
func Info(msg string, args ...any)
|
||||||
|
Info logs an info message
|
||||||
|
|
||||||
|
func Setup(minLevel LogLevel)
|
||||||
|
Setup initializes the logger with the given minimum log level
|
||||||
|
|
||||||
|
func Warn(msg string, args ...any)
|
||||||
|
Warn logs a warning message
|
||||||
|
|
||||||
|
|
||||||
|
TYPES
|
||||||
|
|
||||||
|
type LogLevel slog.Level
|
||||||
|
LogLevel represents the log level
|
||||||
|
|
||||||
|
const (
|
||||||
|
DEBUG LogLevel = LogLevel(slog.LevelDebug)
|
||||||
|
INFO LogLevel = LogLevel(slog.LevelInfo)
|
||||||
|
WARN LogLevel = LogLevel(slog.LevelWarn)
|
||||||
|
ERROR LogLevel = LogLevel(slog.LevelError)
|
||||||
|
)
|
||||||
|
Log levels
|
||||||
|
|
||||||
|
func ParseLogLevel(level string) LogLevel
|
||||||
|
ParseLogLevel converts a string to a LogLevel
|
||||||
|
|
||||||
|
type Logger interface {
|
||||||
|
Debug(msg string, args ...any)
|
||||||
|
Info(msg string, args ...any)
|
||||||
|
Warn(msg string, args ...any)
|
||||||
|
Error(msg string, args ...any)
|
||||||
|
WithGroup(name string) Logger
|
||||||
|
With(args ...any) Logger
|
||||||
|
}
|
||||||
|
Logger represents the interface for logging operations
|
||||||
|
|
||||||
|
func With(args ...any) Logger
|
||||||
|
With adds key-value pairs to the logger context
|
||||||
|
|
||||||
|
func WithGroup(name string) Logger
|
||||||
|
WithGroup adds a group to the logger context
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
## internal/models
|
## internal/models
|
||||||
|
|
||||||
```go
|
```go
|
||||||
@@ -933,9 +996,8 @@ func NewService(key string) (Service, error)
|
|||||||
```go
|
```go
|
||||||
package storage // import "lemma/internal/storage"
|
package storage // import "lemma/internal/storage"
|
||||||
|
|
||||||
Package storage provides functionalities to interact with the file system,
|
Package storage provides functionalities to interact with the storage system
|
||||||
including listing files, finding files by name, getting file content, saving
|
(filesystem).
|
||||||
files, and deleting files.
|
|
||||||
|
|
||||||
FUNCTIONS
|
FUNCTIONS
|
||||||
|
|
||||||
@@ -1091,3 +1153,12 @@ type WorkspaceManager interface {
|
|||||||
storage.
|
storage.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## internal/testenv
|
||||||
|
|
||||||
|
```go
|
||||||
|
package testenv // import "lemma/internal/testenv"
|
||||||
|
|
||||||
|
Package testenv provides a setup for testing the application.
|
||||||
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,50 +1,34 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# Function to generate anchor from package path
|
|
||||||
generate_anchor() {
|
generate_anchor() {
|
||||||
echo "$1" | tr '/' '-'
|
echo "$1" | tr '/' '-'
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create documentation file
|
echo "# Lemma Package Documentation"
|
||||||
echo "# Lemma Package Documentation
|
echo ""
|
||||||
|
echo "Generated documentation for all packages in the Lemma project."
|
||||||
|
echo ""
|
||||||
|
echo "## Table of Contents"
|
||||||
|
|
||||||
Generated documentation for all packages in the Lemma project.
|
|
||||||
|
|
||||||
## Table of Contents
|
|
||||||
" > documentation.md
|
|
||||||
|
|
||||||
# Find all directories containing .go files (excluding test files)
|
|
||||||
# Sort them for consistent output
|
|
||||||
PACKAGES=$(find . -type f -name "*.go" ! -name "*_test.go" -exec dirname {} \; | sort -u | grep -v "/\.")
|
PACKAGES=$(find . -type f -name "*.go" ! -name "*_test.go" -exec dirname {} \; | sort -u | grep -v "/\.")
|
||||||
|
|
||||||
# Generate table of contents
|
|
||||||
for PKG in $PACKAGES; do
|
for PKG in $PACKAGES; do
|
||||||
# Strip leading ./
|
|
||||||
PKG_PATH=${PKG#./}
|
PKG_PATH=${PKG#./}
|
||||||
# Skip if empty
|
|
||||||
[ -z "$PKG_PATH" ] && continue
|
[ -z "$PKG_PATH" ] && continue
|
||||||
|
|
||||||
ANCHOR=$(generate_anchor "$PKG_PATH")
|
ANCHOR=$(generate_anchor "$PKG_PATH")
|
||||||
echo "- [$PKG_PATH](#$ANCHOR)" >> documentation.md
|
echo "- [$PKG_PATH](#$ANCHOR)"
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "" >> documentation.md
|
echo ""
|
||||||
|
|
||||||
# Generate documentation for each package
|
|
||||||
for PKG in $PACKAGES; do
|
for PKG in $PACKAGES; do
|
||||||
# Strip leading ./
|
|
||||||
PKG_PATH=${PKG#./}
|
PKG_PATH=${PKG#./}
|
||||||
# Skip if empty
|
|
||||||
[ -z "$PKG_PATH" ] && continue
|
[ -z "$PKG_PATH" ] && continue
|
||||||
|
echo "## $PKG_PATH"
|
||||||
echo "## $PKG_PATH" >> documentation.md
|
echo ""
|
||||||
echo "" >> documentation.md
|
echo '```go'
|
||||||
echo '```go' >> documentation.md
|
go doc -all "./$PKG_PATH" | cat
|
||||||
go doc -all "./$PKG_PATH" >> documentation.md
|
echo '```'
|
||||||
echo '```' >> documentation.md
|
echo ""
|
||||||
echo "" >> documentation.md
|
|
||||||
done
|
done
|
||||||
|
|
||||||
echo "Documentation generated in documentation.md"
|
|
||||||
@@ -16,7 +16,6 @@ type Config struct {
|
|||||||
WorkDir string
|
WorkDir string
|
||||||
StaticPath string
|
StaticPath string
|
||||||
Port string
|
Port string
|
||||||
RootURL string
|
|
||||||
Domain string
|
Domain string
|
||||||
CORSOrigins []string
|
CORSOrigins []string
|
||||||
AdminEmail string
|
AdminEmail string
|
||||||
@@ -90,10 +89,6 @@ func LoadConfig() (*Config, error) {
|
|||||||
config.Port = port
|
config.Port = port
|
||||||
}
|
}
|
||||||
|
|
||||||
if rootURL := os.Getenv("LEMMA_ROOT_URL"); rootURL != "" {
|
|
||||||
config.RootURL = rootURL
|
|
||||||
}
|
|
||||||
|
|
||||||
if domain := os.Getenv("LEMMA_DOMAIN"); domain != "" {
|
if domain := os.Getenv("LEMMA_DOMAIN"); domain != "" {
|
||||||
config.Domain = domain
|
config.Domain = domain
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ func TestLoad(t *testing.T) {
|
|||||||
"LEMMA_WORKDIR",
|
"LEMMA_WORKDIR",
|
||||||
"LEMMA_STATIC_PATH",
|
"LEMMA_STATIC_PATH",
|
||||||
"LEMMA_PORT",
|
"LEMMA_PORT",
|
||||||
"LEMMA_ROOT_URL",
|
|
||||||
"LEMMA_DOMAIN",
|
"LEMMA_DOMAIN",
|
||||||
"LEMMA_CORS_ORIGINS",
|
"LEMMA_CORS_ORIGINS",
|
||||||
"LEMMA_ADMIN_EMAIL",
|
"LEMMA_ADMIN_EMAIL",
|
||||||
@@ -127,7 +126,6 @@ func TestLoad(t *testing.T) {
|
|||||||
{"WorkDir", cfg.WorkDir, "/custom/work/dir"},
|
{"WorkDir", cfg.WorkDir, "/custom/work/dir"},
|
||||||
{"StaticPath", cfg.StaticPath, "/custom/static/path"},
|
{"StaticPath", cfg.StaticPath, "/custom/static/path"},
|
||||||
{"Port", cfg.Port, "3000"},
|
{"Port", cfg.Port, "3000"},
|
||||||
{"AppURL", cfg.RootURL, "http://localhost:3000"},
|
|
||||||
{"AdminEmail", cfg.AdminEmail, "admin@example.com"},
|
{"AdminEmail", cfg.AdminEmail, "admin@example.com"},
|
||||||
{"AdminPassword", cfg.AdminPassword, "password123"},
|
{"AdminPassword", cfg.AdminPassword, "password123"},
|
||||||
{"JWTSigningKey", cfg.JWTSigningKey, "secret-key"},
|
{"JWTSigningKey", cfg.JWTSigningKey, "secret-key"},
|
||||||
|
|||||||
Reference in New Issue
Block a user