| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- package middleware
- import (
- "strings"
- "github.com/Wei-Shaw/sub2api/internal/pkg/response"
- "github.com/Wei-Shaw/sub2api/internal/service"
- "github.com/gin-gonic/gin"
- )
- // BackendModeUserGuard blocks non-admin users from accessing user routes when backend mode is enabled.
- // Must be placed AFTER JWT auth middleware so that the user role is available in context.
- func BackendModeUserGuard(settingService *service.SettingService) gin.HandlerFunc {
- return func(c *gin.Context) {
- if settingService == nil || !settingService.IsBackendModeEnabled(c.Request.Context()) {
- c.Next()
- return
- }
- role, _ := GetUserRoleFromContext(c)
- if service.IsAdminRole(role) {
- c.Next()
- return
- }
- response.Forbidden(c, "Backend mode is active. User self-service is disabled.")
- c.Abort()
- }
- }
- func backendModeAllowsAuthPath(path string) bool {
- path = strings.ToLower(strings.TrimSpace(path))
- for _, suffix := range []string{
- "/auth/login",
- "/auth/login/2fa",
- "/auth/passkey/login/begin",
- "/auth/passkey/login/finish",
- "/auth/logout",
- "/auth/refresh",
- } {
- if strings.HasSuffix(path, suffix) {
- return true
- }
- }
- for _, suffix := range []string{
- "/auth/oauth/linuxdo/callback",
- "/auth/oauth/wechat/callback",
- "/auth/oauth/wechat/payment/callback",
- "/auth/oauth/oidc/callback",
- "/auth/oauth/github/callback",
- "/auth/oauth/google/callback",
- "/auth/oauth/dingtalk/callback",
- "/auth/oauth/github/complete-registration",
- "/auth/oauth/google/complete-registration",
- "/auth/oauth/linuxdo/complete-registration",
- "/auth/oauth/wechat/complete-registration",
- "/auth/oauth/oidc/complete-registration",
- "/auth/oauth/dingtalk/complete-registration",
- "/auth/oauth/linuxdo/create-account",
- "/auth/oauth/wechat/create-account",
- "/auth/oauth/oidc/create-account",
- "/auth/oauth/dingtalk/create-account",
- "/auth/oauth/linuxdo/bind-login",
- "/auth/oauth/wechat/bind-login",
- "/auth/oauth/oidc/bind-login",
- "/auth/oauth/dingtalk/bind-login",
- } {
- if strings.HasSuffix(path, suffix) {
- return true
- }
- }
- return strings.Contains(path, "/auth/oauth/pending/")
- }
- // BackendModeAuthGuard selectively blocks auth endpoints when backend mode is enabled.
- // Allows the minimal auth surface admins still need in backend mode, including
- // OAuth callbacks and pending continuations. Handler-level backend mode checks
- // still enforce admin-only login and forbid self-service registration.
- func BackendModeAuthGuard(settingService *service.SettingService) gin.HandlerFunc {
- return func(c *gin.Context) {
- if settingService == nil || !settingService.IsBackendModeEnabled(c.Request.Context()) {
- c.Next()
- return
- }
- if backendModeAllowsAuthPath(c.Request.URL.Path) {
- c.Next()
- return
- }
- response.Forbidden(c, "Backend mode is active. Registration and self-service auth flows are disabled.")
- c.Abort()
- }
- }
|