mirror of
https://github.com/phishingclub/phishingclub.git
synced 2026-10-03 22:16:49 +02:00
139 lines
3.6 KiB
Go
139 lines
3.6 KiB
Go
package controller
|
|
|
|
import (
|
|
"io"
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/phishingclub/phishingclub/data"
|
|
"github.com/phishingclub/phishingclub/service"
|
|
)
|
|
|
|
// Branding is the controller for install wide UI branding.
|
|
type Branding struct {
|
|
Common
|
|
BrandingService *service.Branding
|
|
}
|
|
|
|
// GetState returns the branding mode of each slot. It is public so the login
|
|
// screen can read it before authentication.
|
|
func (c *Branding) GetState(g *gin.Context) {
|
|
state, err := c.BrandingService.GetState(g.Request.Context())
|
|
if err != nil {
|
|
c.Response.ServerError(g)
|
|
return
|
|
}
|
|
// never cache the state so an admin change is picked up on the next load
|
|
g.Header("Cache-Control", "no-store")
|
|
c.Response.OK(g, state)
|
|
}
|
|
|
|
// GetImage streams the uploaded PNG for a slot. It is public so the login
|
|
// screen can show a custom logo and side image before authentication. When no
|
|
// custom image is stored it returns 404 so the frontend falls back to the
|
|
// built in default.
|
|
func (c *Branding) GetImage(g *gin.Context) {
|
|
slot := g.Param("slot")
|
|
content, found, err := c.BrandingService.GetImage(slot)
|
|
if err != nil {
|
|
c.Response.ServerError(g)
|
|
return
|
|
}
|
|
if !found {
|
|
c.Response.NotFound(g)
|
|
return
|
|
}
|
|
g.Header("Cache-Control", "no-cache")
|
|
g.Header("X-Content-Type-Options", "nosniff")
|
|
g.Data(http.StatusOK, "image/png", content)
|
|
}
|
|
|
|
// Upload validates and stores an uploaded PNG for a slot.
|
|
func (c *Branding) Upload(g *gin.Context) {
|
|
session, _, ok := c.handleSession(g)
|
|
if !ok {
|
|
return
|
|
}
|
|
slot := g.Param("slot")
|
|
fileHeader, err := g.FormFile("file")
|
|
if err != nil {
|
|
c.Response.BadRequestMessage(g, "No file selected")
|
|
return
|
|
}
|
|
// reject an oversized upload before reading it into memory
|
|
if fileHeader.Size > data.BrandingMaxUploadBytes {
|
|
c.Response.BadRequestMessage(g, "File is too large")
|
|
return
|
|
}
|
|
f, err := fileHeader.Open()
|
|
if err != nil {
|
|
c.Response.BadRequest(g)
|
|
return
|
|
}
|
|
defer f.Close()
|
|
// cap the read so an oversized upload can not exhaust memory, one byte over
|
|
// the limit so the size validation still rejects it
|
|
content, err := io.ReadAll(io.LimitReader(f, data.BrandingMaxUploadBytes+1))
|
|
if err != nil {
|
|
c.Response.BadRequest(g)
|
|
return
|
|
}
|
|
err = c.BrandingService.SetImage(g.Request.Context(), session, slot, content)
|
|
if ok := c.handleErrors(g, err); !ok {
|
|
return
|
|
}
|
|
c.Response.OK(g, gin.H{})
|
|
}
|
|
|
|
// Reset removes the uploaded image for a slot, returning it to the default.
|
|
func (c *Branding) Reset(g *gin.Context) {
|
|
session, _, ok := c.handleSession(g)
|
|
if !ok {
|
|
return
|
|
}
|
|
slot := g.Param("slot")
|
|
err := c.BrandingService.Reset(g.Request.Context(), session, slot)
|
|
if ok := c.handleErrors(g, err); !ok {
|
|
return
|
|
}
|
|
c.Response.OK(g, gin.H{})
|
|
}
|
|
|
|
// SetDisplay stores the display fit settings for a slot.
|
|
func (c *Branding) SetDisplay(g *gin.Context) {
|
|
session, _, ok := c.handleSession(g)
|
|
if !ok {
|
|
return
|
|
}
|
|
slot := g.Param("slot")
|
|
var req service.BrandingDisplay
|
|
if ok := c.handleParseRequest(g, &req); !ok {
|
|
return
|
|
}
|
|
err := c.BrandingService.SetDisplay(g.Request.Context(), session, slot, req)
|
|
if ok := c.handleErrors(g, err); !ok {
|
|
return
|
|
}
|
|
c.Response.OK(g, gin.H{})
|
|
}
|
|
|
|
// SetSideImageVisibility shows or hides the login side image. Hiding centers
|
|
// the login form.
|
|
func (c *Branding) SetSideImageVisibility(g *gin.Context) {
|
|
session, _, ok := c.handleSession(g)
|
|
if !ok {
|
|
return
|
|
}
|
|
var req struct {
|
|
Hidden bool `json:"hidden"`
|
|
}
|
|
if ok := c.handleParseRequest(g, &req); !ok {
|
|
return
|
|
}
|
|
err := c.BrandingService.SetSideImageHidden(g.Request.Context(), session, req.Hidden)
|
|
if ok := c.handleErrors(g, err); !ok {
|
|
return
|
|
}
|
|
c.Response.OK(g, gin.H{})
|
|
}
|