web

package
v2.22.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 29, 2023 License: MIT Imports: 58 Imported by: 17

README

Web

This is the core webserver for YAGPDB, it handles general stuff like authentication.

Currently it only uses 2 HTTP methods: GET for everything that does not change state, and POST for everything else.

The web package is responsible for handling all the core features of the web suite for yagpdb, authentication, adding the bot to servers, and the other basic core functionality.

It also houses a small form validation toolkit through struct tags (this is all kinda messy but one day i hope to improve everything and make it a lot cleaner and easy to work with).

Documentation

Index

Constants

View Source
const (
	AlertDanger  = "danger"
	AlertSuccess = "success"
	AlertInfo    = "info"
	AlertWarning = "warning"
)
View Source
const (
	SidebarCategoryTopLevel = "Top"
	SidebarCategoryFeeds    = "Feeds"
	SidebarCategoryTools    = "Tools"
	SidebarCategoryFun      = "Fun"
	SidebarCategoryCore     = "Core"
)

Variables

View Source
var (
	SessionCookieName = "yagpdb-session-3"
	OauthConf         *oauth2.Config
)
View Source
var (
	ErrChannelNotFound = errors.New("channel not found")
	ErrRoleNotFound    = errors.New("role not found")
)
View Source
var (
	// Core template files
	Templates *template.Template

	Debug              = true // Turns on debug mode
	ListenAddressHTTP  = ":5000"
	ListenAddressHTTPS = ":5001"

	// Muxers
	RootMux            *goji.Mux
	CPMux              *goji.Mux
	ServerPublicMux    *goji.Mux
	ServerPublicAPIMux *goji.Mux

	StartedAt = time.Now()

	CurrentAd *Advertisement

	ConfAdVideos = config.RegisterOption("yagpdb.ad.video_paths", "Comma seperated list of video paths in different formats", "")

	ConfAdsTxt = config.RegisterOption("yagpdb.ads.ads_txt", "Path to the ads.txt file for monetization using ad networks", "")

	// can be overriden by plugins
	// main prurpose is to plug in a onboarding process through a properietary plugin
	SelectServerHomePageHandler http.Handler = RenderHandler(HandleSelectServer, "cp_selectserver")
)
View Source
var (
	ErrDuplicateToken = errors.New("somehow a duplicate token was found")
)
View Source
var ErrNotLoggedIn = errors.New("not logged in")
View Source
var ErrTokenExpired = errors.New("OAUTH2 Token expired")
View Source
var StaticFilesFS fs.FS = frontend.StaticFiles
View Source
var WidgetCache = cache.New(time.Second*10, time.Second*10)

Functions

func APIHandler

func APIHandler(inner CustomHandlerFunc) http.Handler

A helper wrapper that json encodes the returned value

func ActiveServerMW

func ActiveServerMW(inner http.Handler) http.Handler

Sets the active guild context and template data It will only attempt to fetch full guild if not logged in

func AddGlobalTemplateData

func AddGlobalTemplateData(key string, data interface{})

func AddHTMLTemplate

func AddHTMLTemplate(name, contents string)

func AddSidebarItem

func AddSidebarItem(category string, sItem *SidebarItem)

func BaseTemplateDataMiddleware

func BaseTemplateDataMiddleware(inner http.Handler) http.Handler

Fills the template data in the context with basic data such as clientid and redirects

func BaseURL

func BaseURL() string

func CSRFProtectionMW

func CSRFProtectionMW(inner http.Handler) http.Handler

func CheckCSRFToken

func CheckCSRFToken(token string) (bool, error)

CheckCSRFToken returns true if it matched and false if not, an error if something bad happened

func CheckErr

func CheckErr(t TemplateData, err error, errMsg string, logger func(...interface{})) bool

Checks and error and logs it aswell as adding it to the alerts returns true if an error occured

func ContextGuild

func ContextGuild(ctx context.Context) *dstate.GuildSet

func ContextIsAdmin

func ContextIsAdmin(ctx context.Context) bool

func ContextMember

func ContextMember(ctx context.Context) *discordgo.Member

func ContextMemberPerms

func ContextMemberPerms(ctx context.Context) int64

func ContextUser

func ContextUser(ctx context.Context) *discordgo.User

func ControllerHandler

func ControllerHandler(f ControllerHandlerFunc, templateName string) http.Handler

Handlers can return templatedata and an erro. If error is not nil and publicerror it will be added as an alert, if error is not a publicerror it will render a error page

func ControllerPostHandler

func ControllerPostHandler(mainHandler ControllerHandlerFunc, extraHandler http.Handler, formData interface{}) http.Handler

Uses the FormParserMW to parse and validate the form, then saves it

func CreateCSRFToken

func CreateCSRFToken() (string, error)

CreateCSRFToken creates a csrf token and adds it the list

func CreateCookieSession

func CreateCookieSession(token *oauth2.Token) (cookie *http.Cookie, err error)

CreateCookieSession creates a session cookie where the value is the access token itself, this way we don't have to store it on our end anywhere.

func CtxLogger

func CtxLogger(ctx context.Context) *logrus.Entry

CtxLogger Returns an always non nil entry either from the context or standard logger

func DiscordSessionFromContext

func DiscordSessionFromContext(ctx context.Context) *discordgo.Session

func EnabledDisabledSpanStatus

func EnabledDisabledSpanStatus(enabled bool) (str string)

func FormParserMW

func FormParserMW(inner http.Handler, dst interface{}) http.Handler

Parses a form

func GenSessionCookie

func GenSessionCookie() *http.Cookie

func GetIsReadOnly

func GetIsReadOnly(ctx context.Context) bool

func GetRequestIP

func GetRequestIP(r *http.Request) string

func GetUserAccessLevel

func GetUserAccessLevel(userID int64, g *common.GuildWithConnected, config *models.CoreConfig, roleProvider func(guildID, userID int64) []int64) (hasRead bool, hasWrite bool)

func GetUserGuilds

func GetUserGuilds(ctx context.Context) ([]*common.GuildWithConnected, error)

func GuildScopeCacheMW

func GuildScopeCacheMW(plugin common.Plugin, inner http.Handler) http.Handler

Writes the request log into logger, returns a new middleware

func HandleCPLogs

func HandleCPLogs(w http.ResponseWriter, r *http.Request) interface{}

func HandleChanenlPermissions

func HandleChanenlPermissions(w http.ResponseWriter, r *http.Request) interface{}

func HandleConfirmLogin

func HandleConfirmLogin(w http.ResponseWriter, r *http.Request)

func HandleLogin

func HandleLogin(w http.ResponseWriter, r *http.Request)

func HandleLogout

func HandleLogout(w http.ResponseWriter, r *http.Request)

func HandleSelectServer

func HandleSelectServer(w http.ResponseWriter, r *http.Request) interface{}

func HandleStatusJSON

func HandleStatusJSON(w http.ResponseWriter, r *http.Request) interface{}

HandleStatusJSON handles GET /status.json

func HasAccesstoGuildSettings

func HasAccesstoGuildSettings(userID int64, g *common.GuildWithConnected, config *models.CoreConfig, roleProvider func(guildID, userID int64) []int64, write bool) bool

HasAccesstoGuildSettings retrusn true if the specified user (or 0 if not logged in or not on the server) has access

func HasPermissionCTX

func HasPermissionCTX(ctx context.Context, aperms int64) bool

func Indicator

func Indicator(enabled bool) string

func InitOauth

func InitOauth()

func IsAcceptingRequests

func IsAcceptingRequests() bool

func IsAdminRequest

func IsAdminRequest(ctx context.Context, r *http.Request) (read bool, write bool)

Checks the context if there is a logged in user and if so if he's and admin or not

func IsRequestPartial

func IsRequestPartial(ctx context.Context) bool

func LoadCoreConfigMiddleware

func LoadCoreConfigMiddleware(inner http.Handler) http.Handler

LoadCoreConfigMiddleware ensures that the core config is available

func LogIgnoreErr

func LogIgnoreErr(err error)

func ManageServerURL added in v2.15.0

func ManageServerURL(guild *dcmd.GuildContextData) string

func MiscMiddleware

func MiscMiddleware(inner http.Handler) http.Handler

Misc mw that adds some headers, (Strict-Transport-Security) And discards requests when shutting down And a logger

func NewLogEntryFromContext

func NewLogEntryFromContext(ctx context.Context, action string, params ...*cplogs.Param) *cplogs.LogEntry

func NewPublicError

func NewPublicError(a ...interface{}) error

func ParamOrEmpty

func ParamOrEmpty(r *http.Request, key string) string

func RandBase64

func RandBase64(size int) string

func RenderHandler

func RenderHandler(inner CustomHandlerFunc, tmpl string) http.Handler

A helper wrapper that renders a template

func RequestLogger

func RequestLogger(logger io.Writer) func(http.Handler) http.Handler

Writes the request log into logger, returns a new middleware

func RequireActiveServer

func RequireActiveServer(inner http.Handler) http.Handler

RequireActiveServer ensures that were accessing a guild specific page, and guild information is available (e.g a valid guild)

func RequireBotMemberMW

func RequireBotMemberMW(inner http.Handler) http.Handler

RequireBotMemberMW ensures that the bot member for the curreng guild is available, mostly used for checking the bot's roles

func RequireBotOwnerMW

func RequireBotOwnerMW(inner http.Handler) http.Handler

RequireBotOwnerMW requires the user to be logged in and that they're a bot owner

func RequirePermMW

func RequirePermMW(perms ...int64) func(http.Handler) http.Handler

func RequireServerAdminMiddleware

func RequireServerAdminMiddleware(inner http.Handler) http.Handler

RequireServerAdminMiddleware restricts access to guild admins only (or bot admins)

func RequireSessionMiddleware

func RequireSessionMiddleware(inner http.Handler) http.Handler

RequireSessionMiddleware ensures that a session is available, and otherwise refuse to continue down the chain of handlers Also validates the origin header if present (on POST requests that is)

func Run

func Run()

func SessionMiddleware

func SessionMiddleware(inner http.Handler) http.Handler

SessionMiddleware retrieves a session from the request using the session cookie which is actually just a B64 encoded version of the oatuh2 token from discord for the user

func SetContextTemplateData

func SetContextTemplateData(ctx context.Context, data map[string]interface{}) context.Context

func SetGuildMemberMiddleware

func SetGuildMemberMiddleware(inner http.Handler) http.Handler

func SimpleConfigSaverHandler

func SimpleConfigSaverHandler(t SimpleConfigSaver, extraHandler http.Handler, key string) http.Handler

Uses the FormParserMW to parse and validate the form, then saves it

func SkipStaticMW

func SkipStaticMW(maybeSkip func(http.Handler) http.Handler, alwaysRunSuffixes ...string) func(http.Handler) http.Handler

SkipStaticMW skips the "maybeSkip" handler if this is a static link

func StaticRoleProvider

func StaticRoleProvider(roles []int64) func(guildID, userID int64) []int64

func Stop

func Stop()

func UserInfoMiddleware

func UserInfoMiddleware(inner http.Handler) http.Handler

UserInfoMiddleware fills the context with user information and the guilds it's on guilds if possible

func ValidateChannelField

func ValidateChannelField(s int64, channels []dstate.ChannelState, allowEmpty bool) error

func ValidateFloatField

func ValidateFloatField(f float64, min, max float64, onlyMin bool) error

func ValidateForm

func ValidateForm(guild *dstate.GuildSet, tmpl TemplateData, form interface{}) bool

Probably needs some cleaning up

func ValidateIntField

func ValidateIntField(i int64, tags *ValidationTag, guild *dstate.GuildSet, forceAllowEmpty bool) (keep bool, err error)

func ValidateIntMinMaxField

func ValidateIntMinMaxField(i int64, min, max int64, onlyMin bool) error

func ValidateIntSliceField

func ValidateIntSliceField(is []int64, tags *ValidationTag, guild *dstate.GuildSet) (filtered []int64, err error)

func ValidateNormalStringField

func ValidateNormalStringField(s string, min, max int) error

func ValidateRegexField

func ValidateRegexField(s string, max int) error

func ValidateRoleField

func ValidateRoleField(s int64, roles []discordgo.Role, allowEmpty bool) error

func ValidateStringField

func ValidateStringField(s string, tags *ValidationTag, guild *dstate.GuildSet) (str string, err error)

func ValidateTemplateField

func ValidateTemplateField(s string, max int) error

func WriteErrorResponse

func WriteErrorResponse(w http.ResponseWriter, r *http.Request, err string, statusCode int)

Types

type APIError

type APIError struct {
	Message string
}
type Advertisement struct {
	Path       template.URL
	VideoUrls  []template.URL
	VideoTypes []string
	LinkURL    template.URL
	Width      int
	Height     int
}

type Alert

type Alert struct {
	Style   string
	Message string
}

func ErrorAlert

func ErrorAlert(args ...interface{}) *Alert

func SucessAlert

func SucessAlert(args ...interface{}) *Alert

func WarningAlert

func WarningAlert(args ...interface{}) *Alert

type BotStatus

type BotStatus struct {
	// Invidual statuses
	HostStatuses []*HostStatus `json:"host_statuses"`
	NumNodes     int           `json:"num_nodes"`
	TotalShards  int           `json:"total_shards"`

	UnavailableGuilds int   `json:"unavailable_guilds"`
	OfflineShards     []int `json:"offline_shards"`

	EventsPerSecondAverage float64 `json:"events_per_second_average"`
	EventsPerSecondMin     float64 `json:"events_per_second_min"`
	EventsPerSecondMax     float64 `json:"events_per_second_max"`

	UptimeMax time.Duration `json:"uptim_emax"`
	UptimeMin time.Duration `json:"uptime_min"`
}

BotStatus represents the bot's full status

type ControlPanelPlugin

type ControlPanelPlugin struct{}

func (*ControlPanelPlugin) LoadServerHomeWidget

func (p *ControlPanelPlugin) LoadServerHomeWidget(w http.ResponseWriter, r *http.Request) (TemplateData, error)

func (*ControlPanelPlugin) PluginInfo

func (p *ControlPanelPlugin) PluginInfo() *common.PluginInfo

func (*ControlPanelPlugin) ServerHomeWidgetOrder

func (p *ControlPanelPlugin) ServerHomeWidgetOrder() int

type ControllerHandlerFunc

type ControllerHandlerFunc func(w http.ResponseWriter, r *http.Request) (TemplateData, error)

type ControllerHandlerFuncJson

type ControllerHandlerFuncJson func(w http.ResponseWriter, r *http.Request) (interface{}, error)

type CoreConfigPostForm

type CoreConfigPostForm struct {
	AllowedReadOnlyRoles    []int64 `valid:"role,true"`
	AllowedWriteRoles       []int64 `valid:"role,true"`
	AllowAllMembersReadOnly bool
	AllowNonMembersReadOnly bool
}

type CustomHandlerFunc

type CustomHandlerFunc func(w http.ResponseWriter, r *http.Request) interface{}

type CustomResponseWriter

type CustomResponseWriter struct {
	// contains filtered or unexported fields
}

func (*CustomResponseWriter) Header

func (c *CustomResponseWriter) Header() http.Header

func (*CustomResponseWriter) Write

func (c *CustomResponseWriter) Write(b []byte) (int, error)

func (*CustomResponseWriter) WriteHeader

func (c *CustomResponseWriter) WriteHeader(statusCode int)

type CustomValidator

type CustomValidator interface {
	Validate(tmplData TemplateData) (ok bool)
}

type HostStatus

type HostStatus struct {
	Name string

	EventsPerSecond float64
	TotalEvents     int64

	Nodes []*botrest.NodeStatus
}

type Plugin

type Plugin interface {
	common.Plugin

	// Parse the templates and set up the http routes here
	// mainMuxer is the root and cpmuxer handles the /cp/ route
	// the cpmuxer requires a session and to be a admin of the server
	// being managed, otherwise it will redirect to the homepage
	InitWeb()
}

Plugin represents a web plugin

type PluginWithServerHomeWidget

type PluginWithServerHomeWidget interface {
	LoadServerHomeWidget(w http.ResponseWriter, r *http.Request) (TemplateData, error)
}

type PluginWithServerHomeWidgetMiddlewares

type PluginWithServerHomeWidgetMiddlewares interface {
	PluginWithServerHomeWidget
	ServerHomeWidgetApplyMiddlewares(inner http.Handler) http.Handler
}

type PublicError

type PublicError struct {
	// contains filtered or unexported fields
}

func (*PublicError) Error

func (p *PublicError) Error() string

type RenderedServerHomeWidget

type RenderedServerHomeWidget struct {
	Body    template.HTML
	Title   template.HTML
	Enabled bool
}

type ServerHomeWidgetWithOrder

type ServerHomeWidgetWithOrder interface {
	ServerHomeWidgetOrder() int
}

type SidebarItem

type SidebarItem struct {
	Name            string
	URL             string
	Icon            string
	CustomIconImage string
	New             bool
	External        bool
}

type SimpleConfigSaver

type SimpleConfigSaver interface {
	Save(guildID int64) error
	Name() string // Returns this config's name, as it will be logged in the server's control panel log
}

type TemplateData

type TemplateData map[string]interface{}

func GetBaseCPContextData

func GetBaseCPContextData(ctx context.Context) (*dstate.GuildSet, TemplateData)

Returns base context data for control panel plugins

func GetCreateTemplateData

func GetCreateTemplateData(ctx context.Context) (context.Context, TemplateData)

func HandleGetManagedGuilds

func HandleGetManagedGuilds(w http.ResponseWriter, r *http.Request) (TemplateData, error)

func HandleLandingPage

func HandleLandingPage(w http.ResponseWriter, r *http.Request) (TemplateData, error)

func HandlePostCoreSettings

func HandlePostCoreSettings(w http.ResponseWriter, r *http.Request) (TemplateData, error)

func HandleReconnectShard

func HandleReconnectShard(w http.ResponseWriter, r *http.Request) (TemplateData, error)

func HandleServerHome

func HandleServerHome(w http.ResponseWriter, r *http.Request) (TemplateData, error)

func HandleStatusHTML

func HandleStatusHTML(w http.ResponseWriter, r *http.Request) (TemplateData, error)

HandleStatusHTML handles GET /status

func (TemplateData) AddAlerts

func (t TemplateData) AddAlerts(alerts ...*Alert) TemplateData

func (TemplateData) Alerts

func (t TemplateData) Alerts() []*Alert

type ValidationTag

type ValidationTag struct {
	// contains filtered or unexported fields
}

func ParseValidationTag

func ParseValidationTag(tag string) *ValidationTag

func (*ValidationTag) Float

func (p *ValidationTag) Float(index int) (float64, bool)

func (*ValidationTag) Int

func (p *ValidationTag) Int(index int) (int, bool)

func (*ValidationTag) Len

func (p *ValidationTag) Len() int

func (*ValidationTag) Str

func (p *ValidationTag) Str(index int) (string, bool)

type WidgetCacheItem

type WidgetCacheItem struct {
	RawResponse []byte
	Header      http.Header
}

Directories

Path Synopsis
Simple blog
Simple blog

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL