feat: refactor for using app config
This commit is contained in:
@ -7,6 +7,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"gitea.local/admin/hspguard/internal/auth"
|
"gitea.local/admin/hspguard/internal/auth"
|
||||||
|
"gitea.local/admin/hspguard/internal/config"
|
||||||
imiddleware "gitea.local/admin/hspguard/internal/middleware"
|
imiddleware "gitea.local/admin/hspguard/internal/middleware"
|
||||||
"gitea.local/admin/hspguard/internal/oauth"
|
"gitea.local/admin/hspguard/internal/oauth"
|
||||||
"gitea.local/admin/hspguard/internal/repository"
|
"gitea.local/admin/hspguard/internal/repository"
|
||||||
@ -20,9 +21,10 @@ type APIServer struct {
|
|||||||
addr string
|
addr string
|
||||||
repo *repository.Queries
|
repo *repository.Queries
|
||||||
storage *storage.FileStorage
|
storage *storage.FileStorage
|
||||||
|
cfg *config.AppConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAPIServer(addr string, db *repository.Queries, minio *storage.FileStorage) *APIServer {
|
func NewAPIServer(addr string, db *repository.Queries, minio *storage.FileStorage, cfg *config.AppConfig) *APIServer {
|
||||||
return &APIServer{
|
return &APIServer{
|
||||||
addr: addr,
|
addr: addr,
|
||||||
repo: db,
|
repo: db,
|
||||||
@ -38,10 +40,10 @@ func (s *APIServer) Run() error {
|
|||||||
// staticDir := http.Dir(filepath.Join(workDir, "static"))
|
// staticDir := http.Dir(filepath.Join(workDir, "static"))
|
||||||
// FileServer(router, "/static", staticDir)
|
// FileServer(router, "/static", staticDir)
|
||||||
|
|
||||||
oauthHandler := oauth.NewOAuthHandler(s.repo)
|
oauthHandler := oauth.NewOAuthHandler(s.repo, s.cfg)
|
||||||
|
|
||||||
router.Route("/api/v1", func(r chi.Router) {
|
router.Route("/api/v1", func(r chi.Router) {
|
||||||
r.Use(imiddleware.WithSkipper(imiddleware.AuthMiddleware, "/api/v1/login", "/api/v1/register", "/api/v1/oauth/token"))
|
r.Use(imiddleware.WithSkipper(imiddleware.AuthMiddleware(s.cfg), "/api/v1/login", "/api/v1/register", "/api/v1/oauth/token"))
|
||||||
|
|
||||||
userHandler := user.NewUserHandler(s.repo, s.storage)
|
userHandler := user.NewUserHandler(s.repo, s.storage)
|
||||||
userHandler.RegisterRoutes(r)
|
userHandler.RegisterRoutes(r)
|
||||||
@ -52,8 +54,8 @@ func (s *APIServer) Run() error {
|
|||||||
oauthHandler.RegisterRoutes(r)
|
oauthHandler.RegisterRoutes(r)
|
||||||
})
|
})
|
||||||
|
|
||||||
router.Get("/.well-known/jwks.json", auth.WriteJWKS)
|
router.Get("/.well-known/jwks.json", oauthHandler.WriteJWKS)
|
||||||
router.Get("/.well-known/openid-configuration", auth.OpenIdConfiguration)
|
router.Get("/.well-known/openid-configuration", oauth.OpenIdConfiguration)
|
||||||
|
|
||||||
router.Get("/*", func(w http.ResponseWriter, r *http.Request) {
|
router.Get("/*", func(w http.ResponseWriter, r *http.Request) {
|
||||||
path := "./dist" + r.URL.Path
|
path := "./dist" + r.URL.Path
|
||||||
|
@ -4,9 +4,9 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
|
|
||||||
"gitea.local/admin/hspguard/cmd/hspguard/api"
|
"gitea.local/admin/hspguard/cmd/hspguard/api"
|
||||||
|
"gitea.local/admin/hspguard/internal/config"
|
||||||
"gitea.local/admin/hspguard/internal/repository"
|
"gitea.local/admin/hspguard/internal/repository"
|
||||||
"gitea.local/admin/hspguard/internal/storage"
|
"gitea.local/admin/hspguard/internal/storage"
|
||||||
"gitea.local/admin/hspguard/internal/user"
|
"gitea.local/admin/hspguard/internal/user"
|
||||||
@ -21,9 +21,17 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var cfg config.AppConfig
|
||||||
|
|
||||||
|
err = config.LoadEnv(&cfg)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
||||||
conn, err := pgx.Connect(ctx, os.Getenv("DATABASE_URL"))
|
conn, err := pgx.Connect(ctx, cfg.DatabaseURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalln("ERR: Failed to connect to db:", err)
|
log.Fatalln("ERR: Failed to connect to db:", err)
|
||||||
return
|
return
|
||||||
@ -31,21 +39,11 @@ func main() {
|
|||||||
|
|
||||||
repo := repository.New(conn)
|
repo := repository.New(conn)
|
||||||
|
|
||||||
fStorage := storage.New()
|
fStorage := storage.New(&cfg)
|
||||||
|
|
||||||
user.EnsureAdminUser(ctx, repo)
|
user.EnsureAdminUser(ctx, &cfg, repo)
|
||||||
|
|
||||||
host := os.Getenv("HOST")
|
server := api.NewAPIServer(fmt.Sprintf("%s:%s", cfg.Host, cfg.Port), repo, fStorage, &cfg)
|
||||||
if host == "" {
|
|
||||||
host = "127.0.0.1"
|
|
||||||
}
|
|
||||||
|
|
||||||
port := os.Getenv("PORT")
|
|
||||||
if port == "" {
|
|
||||||
port = "3000"
|
|
||||||
}
|
|
||||||
|
|
||||||
server := api.NewAPIServer(fmt.Sprintf("%s:%s", host, port), repo, fStorage)
|
|
||||||
if err := server.Run(); err != nil {
|
if err := server.Run(); err != nil {
|
||||||
log.Fatalln("ERR: Failed to start server:", err)
|
log.Fatalln("ERR: Failed to start server:", err)
|
||||||
}
|
}
|
||||||
|
@ -4,71 +4,13 @@ import (
|
|||||||
"crypto/rsa"
|
"crypto/rsa"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"gitea.local/admin/hspguard/internal/types"
|
"gitea.local/admin/hspguard/internal/types"
|
||||||
"gitea.local/admin/hspguard/internal/web"
|
|
||||||
"github.com/golang-jwt/jwt/v5"
|
"github.com/golang-jwt/jwt/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
func WriteJWKS(w http.ResponseWriter, r *http.Request) {
|
func ParseBase64PrivateKey(b64 string) (*rsa.PrivateKey, error) {
|
||||||
pubKey, err := parseBase64PublicKey("JWT_PUBLIC_KEY")
|
|
||||||
if err != nil {
|
|
||||||
web.Error(w, "failed to parse public key", http.StatusInternalServerError)
|
|
||||||
}
|
|
||||||
|
|
||||||
n := base64.RawURLEncoding.EncodeToString(pubKey.N.Bytes())
|
|
||||||
e := base64.RawURLEncoding.EncodeToString([]byte{1, 0, 1}) // 65537 = 0x010001
|
|
||||||
|
|
||||||
jwks := map[string]interface{}{
|
|
||||||
"keys": []map[string]string{
|
|
||||||
{
|
|
||||||
"kty": "RSA",
|
|
||||||
"kid": "my-rsa-key-1",
|
|
||||||
"use": "sig",
|
|
||||||
"alg": "RS256",
|
|
||||||
"n": n,
|
|
||||||
"e": e,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
json.NewEncoder(w).Encode(jwks)
|
|
||||||
}
|
|
||||||
|
|
||||||
func OpenIdConfiguration(w http.ResponseWriter, r *http.Request) {
|
|
||||||
type Response struct {
|
|
||||||
TokenEndpoint string `json:"token_endpoint"`
|
|
||||||
AuthorizationEndpoint string `json:"authorization_endpoint"`
|
|
||||||
JwksURI string `json:"jwks_uri"`
|
|
||||||
Issuer string `json:"issuer"`
|
|
||||||
EndSessionEndpoint string `json:"end_session_endpoint"`
|
|
||||||
}
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
|
|
||||||
encoder := json.NewEncoder(w)
|
|
||||||
if err := encoder.Encode(Response{
|
|
||||||
TokenEndpoint: "https://cb5f-2a00-10-5b00-c801-e955-5c68-63d0-b777.ngrok-free.app/api/v1/oauth/token",
|
|
||||||
AuthorizationEndpoint: "https://cb5f-2a00-10-5b00-c801-e955-5c68-63d0-b777.ngrok-free.app/authorize",
|
|
||||||
JwksURI: "https://cb5f-2a00-10-5b00-c801-e955-5c68-63d0-b777.ngrok-free.app/.well-known/jwks.json",
|
|
||||||
Issuer: "https://cb5f-2a00-10-5b00-c801-e955-5c68-63d0-b777.ngrok-free.app",
|
|
||||||
EndSessionEndpoint: "https://cb5f-2a00-10-5b00-c801-e955-5c68-63d0-b777.ngrok-free.app/api/v1/oauth/logout",
|
|
||||||
}); err != nil {
|
|
||||||
web.Error(w, "failed to encode response", http.StatusInternalServerError)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseBase64PrivateKey(envVar string) (*rsa.PrivateKey, error) {
|
|
||||||
b64 := os.Getenv(envVar)
|
|
||||||
if b64 == "" {
|
|
||||||
return nil, fmt.Errorf("env var %s is empty", envVar)
|
|
||||||
}
|
|
||||||
|
|
||||||
decoded, err := base64.StdEncoding.DecodeString(b64)
|
decoded, err := base64.StdEncoding.DecodeString(b64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to decode base64 key: %v", err)
|
return nil, fmt.Errorf("failed to decode base64 key: %v", err)
|
||||||
@ -78,12 +20,7 @@ func parseBase64PrivateKey(envVar string) (*rsa.PrivateKey, error) {
|
|||||||
return key.(*rsa.PrivateKey), err
|
return key.(*rsa.PrivateKey), err
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseBase64PublicKey(envVar string) (*rsa.PublicKey, error) {
|
func ParseBase64PublicKey(b64 string) (*rsa.PublicKey, error) {
|
||||||
b64 := os.Getenv(envVar)
|
|
||||||
if b64 == "" {
|
|
||||||
return nil, fmt.Errorf("env var %s is empty", envVar)
|
|
||||||
}
|
|
||||||
|
|
||||||
decoded, err := base64.StdEncoding.DecodeString(b64)
|
decoded, err := base64.StdEncoding.DecodeString(b64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to decode base64 key: %v", err)
|
return nil, fmt.Errorf("failed to decode base64 key: %v", err)
|
||||||
@ -102,8 +39,8 @@ func parseBase64PublicKey(envVar string) (*rsa.PublicKey, error) {
|
|||||||
return pubKey, nil
|
return pubKey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func SignJwtToken(claims jwt.Claims) (string, error) {
|
func SignJwtToken(claims jwt.Claims, key string) (string, error) {
|
||||||
privateKey, err := parseBase64PrivateKey("JWT_PRIVATE_KEY")
|
privateKey, err := ParseBase64PrivateKey(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -120,8 +57,8 @@ func SignJwtToken(claims jwt.Claims) (string, error) {
|
|||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func VerifyToken(token string) (*jwt.Token, *types.UserClaims, error) {
|
func VerifyToken(token string, key string) (*jwt.Token, *types.UserClaims, error) {
|
||||||
publicKey, err := parseBase64PublicKey("JWT_PUBLIC_KEY")
|
publicKey, err := ParseBase64PublicKey(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"gitea.local/admin/hspguard/internal/config"
|
||||||
"gitea.local/admin/hspguard/internal/repository"
|
"gitea.local/admin/hspguard/internal/repository"
|
||||||
"gitea.local/admin/hspguard/internal/types"
|
"gitea.local/admin/hspguard/internal/types"
|
||||||
"gitea.local/admin/hspguard/internal/util"
|
"gitea.local/admin/hspguard/internal/util"
|
||||||
@ -17,6 +18,7 @@ import (
|
|||||||
|
|
||||||
type AuthHandler struct {
|
type AuthHandler struct {
|
||||||
repo *repository.Queries
|
repo *repository.Queries
|
||||||
|
cfg *config.AppConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAuthHandler(repo *repository.Queries) *AuthHandler {
|
func NewAuthHandler(repo *repository.Queries) *AuthHandler {
|
||||||
@ -89,6 +91,7 @@ func (h *AuthHandler) login(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
accessClaims := types.UserClaims{
|
accessClaims := types.UserClaims{
|
||||||
UserEmail: user.Email,
|
UserEmail: user.Email,
|
||||||
|
IsAdmin: user.IsAdmin,
|
||||||
RegisteredClaims: jwt.RegisteredClaims{
|
RegisteredClaims: jwt.RegisteredClaims{
|
||||||
Issuer: "hspguard",
|
Issuer: "hspguard",
|
||||||
Subject: user.ID.String(),
|
Subject: user.ID.String(),
|
||||||
@ -97,7 +100,7 @@ func (h *AuthHandler) login(w http.ResponseWriter, r *http.Request) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
accessToken, err := SignJwtToken(accessClaims)
|
accessToken, err := SignJwtToken(accessClaims, h.cfg.Jwt.PrivateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
web.Error(w, fmt.Sprintf("failed to generate access token: %v", err), http.StatusBadRequest)
|
web.Error(w, fmt.Sprintf("failed to generate access token: %v", err), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
@ -105,6 +108,7 @@ func (h *AuthHandler) login(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
refreshClaims := types.UserClaims{
|
refreshClaims := types.UserClaims{
|
||||||
UserEmail: user.Email,
|
UserEmail: user.Email,
|
||||||
|
IsAdmin: user.IsAdmin,
|
||||||
RegisteredClaims: jwt.RegisteredClaims{
|
RegisteredClaims: jwt.RegisteredClaims{
|
||||||
Issuer: "hspguard",
|
Issuer: "hspguard",
|
||||||
Subject: user.ID.String(),
|
Subject: user.ID.String(),
|
||||||
@ -113,7 +117,7 @@ func (h *AuthHandler) login(w http.ResponseWriter, r *http.Request) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
refreshToken, err := SignJwtToken(refreshClaims)
|
refreshToken, err := SignJwtToken(refreshClaims, h.cfg.Jwt.PrivateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
web.Error(w, fmt.Sprintf("failed to generate refresh token: %v", err), http.StatusBadRequest)
|
web.Error(w, fmt.Sprintf("failed to generate refresh token: %v", err), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
|
@ -7,11 +7,13 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"gitea.local/admin/hspguard/internal/auth"
|
"gitea.local/admin/hspguard/internal/auth"
|
||||||
|
"gitea.local/admin/hspguard/internal/config"
|
||||||
"gitea.local/admin/hspguard/internal/types"
|
"gitea.local/admin/hspguard/internal/types"
|
||||||
"gitea.local/admin/hspguard/internal/web"
|
"gitea.local/admin/hspguard/internal/web"
|
||||||
)
|
)
|
||||||
|
|
||||||
func AuthMiddleware(next http.Handler) http.Handler {
|
func AuthMiddleware(cfg *config.AppConfig) func(http.Handler) http.Handler {
|
||||||
|
return func(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
authHeader := r.Header.Get("Authorization")
|
authHeader := r.Header.Get("Authorization")
|
||||||
if authHeader == "" {
|
if authHeader == "" {
|
||||||
@ -26,7 +28,7 @@ func AuthMiddleware(next http.Handler) http.Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tokenStr := parts[1]
|
tokenStr := parts[1]
|
||||||
token, userClaims, err := auth.VerifyToken(tokenStr)
|
token, userClaims, err := auth.VerifyToken(tokenStr, cfg.Jwt.PublicKey)
|
||||||
if err != nil || !token.Valid {
|
if err != nil || !token.Valid {
|
||||||
http.Error(w, fmt.Sprintf("invalid token: %v", err), http.StatusUnauthorized)
|
http.Error(w, fmt.Sprintf("invalid token: %v", err), http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
@ -36,6 +38,7 @@ func AuthMiddleware(next http.Handler) http.Handler {
|
|||||||
next.ServeHTTP(w, r.WithContext(ctx))
|
next.ServeHTTP(w, r.WithContext(ctx))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func WithSkipper(mw func(http.Handler) http.Handler, excludedPaths ...string) func(http.Handler) http.Handler {
|
func WithSkipper(mw func(http.Handler) http.Handler, excludedPaths ...string) func(http.Handler) http.Handler {
|
||||||
return func(next http.Handler) http.Handler {
|
return func(next http.Handler) http.Handler {
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gitea.local/admin/hspguard/internal/auth"
|
"gitea.local/admin/hspguard/internal/auth"
|
||||||
|
"gitea.local/admin/hspguard/internal/config"
|
||||||
"gitea.local/admin/hspguard/internal/repository"
|
"gitea.local/admin/hspguard/internal/repository"
|
||||||
"gitea.local/admin/hspguard/internal/types"
|
"gitea.local/admin/hspguard/internal/types"
|
||||||
"gitea.local/admin/hspguard/internal/util"
|
"gitea.local/admin/hspguard/internal/util"
|
||||||
@ -21,11 +22,13 @@ import (
|
|||||||
|
|
||||||
type OAuthHandler struct {
|
type OAuthHandler struct {
|
||||||
repo *repository.Queries
|
repo *repository.Queries
|
||||||
|
cfg *config.AppConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewOAuthHandler(repo *repository.Queries) *OAuthHandler {
|
func NewOAuthHandler(repo *repository.Queries, cfg *config.AppConfig) *OAuthHandler {
|
||||||
return &OAuthHandler{
|
return &OAuthHandler{
|
||||||
repo,
|
repo,
|
||||||
|
cfg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,6 +38,55 @@ func (h *OAuthHandler) RegisterRoutes(r chi.Router) {
|
|||||||
r.Post("/oauth/code", h.getAuthCode)
|
r.Post("/oauth/code", h.getAuthCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *OAuthHandler) WriteJWKS(w http.ResponseWriter, r *http.Request) {
|
||||||
|
pubKey, err := auth.ParseBase64PublicKey(h.cfg.Jwt.PublicKey)
|
||||||
|
if err != nil {
|
||||||
|
web.Error(w, "failed to parse public key", http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
|
||||||
|
n := base64.RawURLEncoding.EncodeToString(pubKey.N.Bytes())
|
||||||
|
e := base64.RawURLEncoding.EncodeToString([]byte{1, 0, 1}) // 65537 = 0x010001
|
||||||
|
|
||||||
|
jwks := map[string]interface{}{
|
||||||
|
"keys": []map[string]string{
|
||||||
|
{
|
||||||
|
"kty": "RSA",
|
||||||
|
"kid": "my-rsa-key-1",
|
||||||
|
"use": "sig",
|
||||||
|
"alg": "RS256",
|
||||||
|
"n": n,
|
||||||
|
"e": e,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
json.NewEncoder(w).Encode(jwks)
|
||||||
|
}
|
||||||
|
|
||||||
|
func OpenIdConfiguration(w http.ResponseWriter, r *http.Request) {
|
||||||
|
type Response struct {
|
||||||
|
TokenEndpoint string `json:"token_endpoint"`
|
||||||
|
AuthorizationEndpoint string `json:"authorization_endpoint"`
|
||||||
|
JwksURI string `json:"jwks_uri"`
|
||||||
|
Issuer string `json:"issuer"`
|
||||||
|
EndSessionEndpoint string `json:"end_session_endpoint"`
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
encoder := json.NewEncoder(w)
|
||||||
|
if err := encoder.Encode(Response{
|
||||||
|
TokenEndpoint: "https://cb5f-2a00-10-5b00-c801-e955-5c68-63d0-b777.ngrok-free.app/api/v1/oauth/token",
|
||||||
|
AuthorizationEndpoint: "https://cb5f-2a00-10-5b00-c801-e955-5c68-63d0-b777.ngrok-free.app/authorize",
|
||||||
|
JwksURI: "https://cb5f-2a00-10-5b00-c801-e955-5c68-63d0-b777.ngrok-free.app/.well-known/jwks.json",
|
||||||
|
Issuer: "https://cb5f-2a00-10-5b00-c801-e955-5c68-63d0-b777.ngrok-free.app",
|
||||||
|
EndSessionEndpoint: "https://cb5f-2a00-10-5b00-c801-e955-5c68-63d0-b777.ngrok-free.app/api/v1/oauth/logout",
|
||||||
|
}); err != nil {
|
||||||
|
web.Error(w, "failed to encode response", http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (h *OAuthHandler) getAuthCode(w http.ResponseWriter, r *http.Request) {
|
func (h *OAuthHandler) getAuthCode(w http.ResponseWriter, r *http.Request) {
|
||||||
userId, ok := util.GetRequestUserId(r.Context())
|
userId, ok := util.GetRequestUserId(r.Context())
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -155,7 +207,7 @@ func (h *OAuthHandler) tokenEndpoint(w http.ResponseWriter, r *http.Request) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
idToken, err := auth.SignJwtToken(claims)
|
idToken, err := auth.SignJwtToken(claims, h.cfg.Jwt.PrivateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
web.Error(w, "failed to sign id token", http.StatusInternalServerError)
|
web.Error(w, "failed to sign id token", http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
@ -5,8 +5,8 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
|
||||||
|
|
||||||
|
"gitea.local/admin/hspguard/internal/config"
|
||||||
"github.com/minio/minio-go/v7"
|
"github.com/minio/minio-go/v7"
|
||||||
"github.com/minio/minio-go/v7/pkg/credentials"
|
"github.com/minio/minio-go/v7/pkg/credentials"
|
||||||
)
|
)
|
||||||
@ -15,27 +15,9 @@ type FileStorage struct {
|
|||||||
client *minio.Client
|
client *minio.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() *FileStorage {
|
func New(cfg *config.AppConfig) *FileStorage {
|
||||||
endpoint := os.Getenv("MINIO_ENDPOINT")
|
client, err := minio.New(cfg.Minio.Endpoint, &minio.Options{
|
||||||
if endpoint == "" {
|
Creds: credentials.NewStaticV4(cfg.Minio.AccessKey, cfg.Minio.SecretKey, ""),
|
||||||
log.Fatalln("MINIO_ENDPOINT env var is required")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
accessKey := os.Getenv("MINIO_ACCESS_KEY")
|
|
||||||
if accessKey == "" {
|
|
||||||
log.Fatalln("MINIO_ACCESS_KEY env var is required")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
secretKey := os.Getenv("MINIO_SECRET_KEY")
|
|
||||||
if secretKey == "" {
|
|
||||||
log.Fatalln("MINIO_SECRET_KEY env var is required")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
client, err := minio.New(endpoint, &minio.Options{
|
|
||||||
Creds: credentials.NewStaticV4(accessKey, secretKey, ""),
|
|
||||||
Secure: false,
|
Secure: false,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -4,6 +4,7 @@ import "github.com/golang-jwt/jwt/v5"
|
|||||||
|
|
||||||
type UserClaims struct {
|
type UserClaims struct {
|
||||||
UserEmail string `json:"user_email"`
|
UserEmail string `json:"user_email"`
|
||||||
|
IsAdmin bool `json:"is_admin"`
|
||||||
jwt.RegisteredClaims
|
jwt.RegisteredClaims
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,33 +4,21 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
|
|
||||||
|
"gitea.local/admin/hspguard/internal/config"
|
||||||
"gitea.local/admin/hspguard/internal/repository"
|
"gitea.local/admin/hspguard/internal/repository"
|
||||||
"gitea.local/admin/hspguard/internal/util"
|
"gitea.local/admin/hspguard/internal/util"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func EnsureAdminUser(ctx context.Context, repo *repository.Queries) {
|
func EnsureAdminUser(ctx context.Context, cfg *config.AppConfig, repo *repository.Queries) {
|
||||||
adminName := os.Getenv("ADMIN_NAME")
|
_, err := repo.FindUserEmail(ctx, cfg.Admin.Email)
|
||||||
if adminName == "" {
|
|
||||||
adminName = "admin"
|
|
||||||
}
|
|
||||||
|
|
||||||
adminEmail := os.Getenv("ADMIN_EMAIL")
|
|
||||||
adminPassword := os.Getenv("ADMIN_PASSWORD")
|
|
||||||
|
|
||||||
if adminEmail == "" {
|
|
||||||
log.Fatalln("ERR: ADMIN_EMAIL env variable is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := repo.FindUserEmail(ctx, adminEmail)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if adminPassword == "" {
|
if cfg.Admin.Password == "" {
|
||||||
log.Fatalln("ERR: ADMIN_PASSWORD env variable is required")
|
log.Fatalln("ERR: ADMIN_PASSWORD env variable is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := createAdmin(ctx, adminName, adminEmail, adminPassword, repo); err != nil {
|
if _, err := createAdmin(ctx, cfg.Admin.Name, cfg.Admin.Email, cfg.Admin.Password, repo); err != nil {
|
||||||
log.Fatalln("ERR: Failed to create admin account:", err)
|
log.Fatalln("ERR: Failed to create admin account:", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 6.9 MiB After Width: | Height: | Size: 416 KiB |
Reference in New Issue
Block a user