From 356c4ebaf2d5420f7af2313a655a854bfa87d68e Mon Sep 17 00:00:00 2001
From: haturatu
Date: Sun, 12 Oct 2025 21:04:21 +0900
Subject: feat(register): register option
---
README.ja.md | 1 +
README.md | 1 +
cmd/server/main.go | 14 +++++++++-----
config/config.go | 1 +
handlers/auth.go | 13 +++++++++++--
templates/login.html | 2 ++
types/types.go | 1 +
7 files changed, 26 insertions(+), 7 deletions(-)
diff --git a/README.ja.md b/README.ja.md
index 2c101ed..255c1fb 100644
--- a/README.ja.md
+++ b/README.ja.md
@@ -356,5 +356,6 @@ Authorization: Bearer
| `PROTECT_API` | `true`の場合、すべてのAPIパスをベアラートークン認証経由でプロキシします。 | `false` |
| `FRONT_PATH` | `PROTECT_FRONTEND`で保護されるフロントエンドのベースパス。 | `/` |
| `API_PATH` | `PROTECT_API`で保護されるAPIルートのベースパス。 | `/api/` |
+| `REGISTER` | `false`に設定すると、新規ユーザー登録を無効にします。 | `true` |
| `AUTH_PATH_*` | ログイン、管理者ページなどの内部URLをカスタマイズするための変数セット。 | 様々、例: `/login`|
| `AUTH_ASSETS_PATH` | 内部静的アセット(CSS, JS)を提供するためのURLパス。 | `/assets` |
diff --git a/README.md b/README.md
index f22e873..a99af8c 100644
--- a/README.md
+++ b/README.md
@@ -354,5 +354,6 @@ The `refresh_token` is a long-lived token that can be used to obtain a new acces
| `PROTECT_API` | If `true`, proxies all API paths through bearer token authentication. | `false` |
| `FRONT_PATH` | The base path for frontend routes to be protected by `PROTECT_FRONTEND`. | `/` |
| `API_PATH` | The base path for API routes to be protected by `PROTECT_API`. | `/api/` |
+| `REGISTER` | If set to `false`, disables new user registration. | `true` |
| `AUTH_PATH_*` | A set of variables to customize the internal URLs for login, admin, etc. | Various, e.g., `/login`|
| `AUTH_ASSETS_PATH` | The URL path for serving internal static assets (CSS, JS). | `/assets` |
\ No newline at end of file
diff --git a/cmd/server/main.go b/cmd/server/main.go
index 7d2fa25..89d17bc 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -79,10 +79,12 @@ func main() {
loginHandler := methodSwitch(loginPageHandler, http.HandlerFunc(handlers.LoginHandler))
mux.Handle(config.Paths.Login, loginHandler)
- // For /register, GET goes to PHP, POST goes to Go's register logic
- registerPostHandler := middleware.RateLimitMiddleware(rateLimiter)(http.HandlerFunc(handlers.RegisterHandler))
- registerHandler := methodSwitch(registerPageHandler, registerPostHandler)
- mux.Handle(config.Paths.Register, registerHandler)
+ if config.Paths.RegisterEnabled {
+ // For /register, GET goes to PHP, POST goes to Go's register logic
+ registerPostHandler := middleware.RateLimitMiddleware(rateLimiter)(http.HandlerFunc(handlers.RegisterHandler))
+ registerHandler := methodSwitch(registerPageHandler, registerPostHandler)
+ mux.Handle(config.Paths.Register, registerHandler)
+ }
// For account pages, GET goes to PHP, POST (for password change) goes to Go
accountPasswordPostHandler := http.HandlerFunc(handlers.ChangePasswordHandler)
@@ -95,7 +97,9 @@ func main() {
} else {
// --- Public Auth Routes (Go templates) ---
mux.HandleFunc(config.Paths.Login, handlers.LoginHandler)
- mux.Handle(config.Paths.Register, middleware.RateLimitMiddleware(rateLimiter)(http.HandlerFunc(handlers.RegisterHandler)))
+ if config.Paths.RegisterEnabled {
+ mux.Handle(config.Paths.Register, middleware.RateLimitMiddleware(rateLimiter)(http.HandlerFunc(handlers.RegisterHandler)))
+ }
// --- Auth HTML pages (Protected by SessionAuth, Go templates) ---
mux.Handle(config.Paths.Account, middleware.SessionAuth(http.HandlerFunc(handlers.AccountPageHandler)))
mux.Handle(config.Paths.Admin, middleware.SessionAuth(middleware.AdminMiddleware(http.HandlerFunc(handlers.AdminPageHandler))))
diff --git a/config/config.go b/config/config.go
index a73bf23..2de3c36 100644
--- a/config/config.go
+++ b/config/config.go
@@ -47,5 +47,6 @@ func Init() {
ProtectAPI: getEnvAsBool("PROTECT_API", false),
FrontPath: getEnv("FRONT_PATH", "/"),
APIPath: getEnv("API_PATH", "/api/"),
+ RegisterEnabled: getEnvAsBool("REGISTER", true),
}
}
diff --git a/handlers/auth.go b/handlers/auth.go
index 2d5eb68..f7773a8 100644
--- a/handlers/auth.go
+++ b/handlers/auth.go
@@ -17,8 +17,9 @@ var templates = template.Must(template.ParseGlob("templates/*.html"))
func renderLoginWithError(w http.ResponseWriter, message string) {
data := map[string]interface{}{
- "Paths": config.Paths,
- "Error": message,
+ "Paths": config.Paths,
+ "Error": message,
+ "RegisterEnabled": config.Paths.RegisterEnabled,
}
w.WriteHeader(http.StatusUnauthorized) // Set status to indicate failure
if err := templates.ExecuteTemplate(w, "login.html", data); err != nil {
@@ -34,6 +35,10 @@ func LoginHandler(w http.ResponseWriter, r *http.Request) {
}
if r.Method == http.MethodGet {
+ data := map[string]interface{}{
+ "Paths": config.Paths,
+ "RegisterEnabled": config.Paths.RegisterEnabled,
+ }
if err := templates.ExecuteTemplate(w, "login.html", data); err != nil {
logging.AppLog.Error("Failed to execute login template", "error", err, "ip", ip)
}
@@ -192,6 +197,10 @@ func renderRegisterWithError(w http.ResponseWriter, message string) {
// RegisterHandler handles displaying and processing the user registration form.
func RegisterHandler(w http.ResponseWriter, r *http.Request) {
+ if !config.Paths.RegisterEnabled {
+ http.Error(w, "User registration is disabled.", http.StatusForbidden)
+ return
+ }
ip := logging.GetClientIP(r)
data := map[string]interface{}{
"Paths": config.Paths,
diff --git a/templates/login.html b/templates/login.html
index 8875cb1..12f27eb 100644
--- a/templates/login.html
+++ b/templates/login.html
@@ -26,7 +26,9 @@
{{end}}
diff --git a/types/types.go b/types/types.go
index a91fbcd..b94d89a 100644
--- a/types/types.go
+++ b/types/types.go
@@ -20,6 +20,7 @@ type PathConfig struct {
ProtectAPI bool
FrontPath string
APIPath string
+ RegisterEnabled bool
}
// ContextKey is a custom type for context keys to avoid collisions.
--
cgit v1.2.3