refactor(10.2-01): nest framework packages under modules

- Move remaining beach packages and embedded admin assets\n- Rewrite framework, example, build, and gate paths
This commit is contained in:
Jakub Zych
2026-09-28 02:21:02 +02:00
parent ac1f6d14f4
commit 5e50b166ef
277 changed files with 303 additions and 303 deletions

78
modules/bouncer/mint.go Normal file
View File

@@ -0,0 +1,78 @@
package bouncer
import (
"crypto/rand"
"encoding/hex"
"fmt"
"strings"
"time"
"github.com/golang-jwt/jwt/v5"
)
// prvHash is sha1("Golem15\User\Models\User"), the lock-subject PHP jwt-auth
// stamps on every frontend user token. Backend tokens do not carry it.
const prvHash = "a867434cbc213adfbe78a02bed7082a6bd99c883"
const (
// AudienceUser is the frontend jwt-guard audience.
AudienceUser = "user"
// AudienceBackend is the admin jwt-guard audience.
AudienceBackend = "backend"
)
type registeredClaims struct {
jwt.RegisteredClaims
Prv string `json:"prv,omitempty"`
}
// Mint signs a frontend-audience HS256 token. iss is the minting endpoint URL.
// The returned jti is the token's own jti claim.
func Mint(secret, sub, issuerURL string, ttl time.Duration) (string, string, error) {
return MintAudience(secret, sub, issuerURL, ttl, AudienceUser)
}
// MintAudience signs an HS256 token for audience. Frontend tokens keep the PHP
// prv lock-subject; backend tokens omit it.
func MintAudience(secret, sub, issuerURL string, ttl time.Duration, audience string) (string, string, error) {
if strings.TrimSpace(secret) == "" {
return "", "", fmt.Errorf("bouncer: jwt secret is empty")
}
if strings.TrimSpace(audience) == "" {
return "", "", fmt.Errorf("bouncer: jwt audience is empty")
}
jti, err := newJTI()
if err != nil {
return "", "", err
}
now := time.Now()
prv := ""
if audience == AudienceUser {
prv = prvHash
}
claims := registeredClaims{
RegisteredClaims: jwt.RegisteredClaims{
Issuer: issuerURL,
Subject: sub,
Audience: jwt.ClaimStrings{audience},
ExpiresAt: jwt.NewNumericDate(now.Add(ttl)),
NotBefore: jwt.NewNumericDate(now),
IssuedAt: jwt.NewNumericDate(now),
ID: jti,
},
Prv: prv,
}
signed, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString([]byte(secret))
if err != nil {
return "", "", err
}
return signed, jti, nil
}
func newJTI() (string, error) {
buf := make([]byte, 16)
if _, err := rand.Read(buf); err != nil {
return "", err
}
return hex.EncodeToString(buf), nil
}