This commit is contained in:
blankhex committed 2026-10-16 01:06:20 +03:00
1 parent fd2e7f6cd8
commit 65534ecfd5
4 files changed
+17 -14

No files matched your search

+5 -5
View File
@@ -44,16 +44,16 @@ RUN chmod +x /app/server
COPY --from=builder /build/static /app/static COPY --from=builder /build/static /app/static
COPY --from=builder /build/templates /app/templates COPY --from=builder /build/templates /app/templates
# Ensure the app user owns the working dir (DB file created here at runtime) # Ensure the app user owns the working dir
RUN chown -R app:app /app RUN chown -R app:app /app
# Create a dedicated subdirectory for persistable data (mounted as a volume) # Create data directory owned by app user (for named volume mount)
RUN mkdir -p /app/data RUN mkdir -p /data && chown app:app /data
USER app USER app
# Expose the HTTP port # Expose the HTTP port
EXPOSE 8080 EXPOSE 8080
# Default command # Default command (runs as 'app' user, DB stored in named volume)
CMD ["/app/server", "-addr", ":8080", "-db", "/app/data/state.db"] CMD ["/app/server", "-addr", ":8080", "-db", "/data/state.db"]
+3 -2
View File
@@ -8,8 +8,7 @@ services:
ports: ports:
- "8080:8080" - "8080:8080"
volumes: volumes:
# Bind mount only the data subdirectory, so /app/server and assets are NOT overwritten - uportal_data:/data
- ./data:/app/data
environment: environment:
LOG_LEVEL: info LOG_LEVEL: info
# Optional configuration (uncomment as needed): # Optional configuration (uncomment as needed):
@@ -20,3 +19,5 @@ services:
# TRUSTED_DOMAINS: example.com # TRUSTED_DOMAINS: example.com
restart: unless-stopped restart: unless-stopped
volumes:
uportal_data:
-2
View File
@@ -274,8 +274,6 @@ func (s *WebService) HandleExternalRedirect(w http.ResponseWriter, r *http.Reque
if !ok { if !ok {
// Not authenticated is fine — just show the warning without nav // Not authenticated is fine — just show the warning without nav
data = &ViewData{Title: "External Redirect"} data = &ViewData{Title: "External Redirect"}
token, _ := auth.SetCsrfCookie(w, r, CsrfCookieName)
data.FormToken = token
} }
data.Redirect = target data.Redirect = target
+9 -5
View File
@@ -185,17 +185,21 @@ func (lrw *loggingResponseWriter) WriteHeader(code int) {
lrw.ResponseWriter.WriteHeader(code) lrw.ResponseWriter.WriteHeader(code)
} }
// render mints a CSRF token, fills ViewData defaults, and writes the response. // render fills ViewData defaults and writes the response.
// If data.FormToken is empty (e.g. for call sites that don't use
// basicViewData), a CSRF token is minted as a fallback.
func (s *WebService) render(w http.ResponseWriter, r *http.Request, page string, data *ViewData) { func (s *WebService) render(w http.ResponseWriter, r *http.Request, page string, data *ViewData) {
if data == nil {
data = &ViewData{}
}
if data.FormToken == "" {
token, err := auth.SetCsrfCookie(w, r, CsrfCookieName) token, err := auth.SetCsrfCookie(w, r, CsrfCookieName)
if err != nil { if err != nil {
http.Error(w, "Internal Server Error", http.StatusInternalServerError) http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return return
} }
if data == nil {
data = &ViewData{}
}
data.FormToken = token data.FormToken = token
}
if data.Title == "" { if data.Title == "" {
data.Title = page data.Title = page
} }
@@ -228,7 +232,7 @@ func (s *WebService) currentUser(r *http.Request) (*user.User, error) {
return s.getUserInfo(r) return s.getUserInfo(r)
} }
// basicViewData builds a ViewData with the current user and a CSRF token. // basicViewData builds a ViewData with the current user and CSRF token.
func (s *WebService) basicViewData(w http.ResponseWriter, r *http.Request, title string) (*ViewData, bool) { func (s *WebService) basicViewData(w http.ResponseWriter, r *http.Request, title string) (*ViewData, bool) {
user, err := s.getUserInfo(r) user, err := s.getUserInfo(r)
if err != nil { if err != nil {