error page

This commit is contained in:
rxdn 2020-06-21 14:57:08 +01:00
parent 04969f7532
commit c1373242bb
10 changed files with 105 additions and 36 deletions

View File

@ -3,9 +3,7 @@ package manage
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/TicketsBot/GoPanel/config"
"github.com/TicketsBot/GoPanel/database" "github.com/TicketsBot/GoPanel/database"
"github.com/TicketsBot/GoPanel/rpc/cache"
"github.com/TicketsBot/GoPanel/utils" "github.com/TicketsBot/GoPanel/utils"
"github.com/TicketsBot/archiverclient" "github.com/TicketsBot/archiverclient"
"github.com/TicketsBot/common/permission" "github.com/TicketsBot/common/permission"
@ -27,50 +25,39 @@ func ModmailLogViewHandler(ctx *gin.Context) {
// Verify the guild exists // Verify the guild exists
guildId, err := strconv.ParseUint(ctx.Param("id"), 10, 64) guildId, err := strconv.ParseUint(ctx.Param("id"), 10, 64)
if err != nil { if err != nil {
ctx.Redirect(302, config.Conf.Server.BaseUrl) // TODO: 404 Page utils.ErrorPage(ctx, 404, "Couldn't find a server with the ID provided")
return return
} }
// Get object for selected guild
guild, _ := cache.Instance.GetGuild(guildId, false)
// get ticket UUID // get ticket UUID
archiveUuid, err := uuid.FromString(ctx.Param("uuid")) archiveUuid, err := uuid.FromString(ctx.Param("uuid"))
if err != nil { if err != nil {
// TODO: 404 error page utils.ErrorPage(ctx, 404, "Modmail archive with provided UUID not found")
ctx.AbortWithStatusJSON(404, gin.H{
"success": false,
"error": "Modmail archive not found",
})
return return
} }
// get ticket object // get ticket object
archive, err := database.Client.ModmailArchive.Get(archiveUuid) archive, err := database.Client.ModmailArchive.Get(archiveUuid)
if err != nil { if err != nil {
// TODO: 500 error page utils.ErrorPage(ctx, 500, err.Error())
ctx.AbortWithStatusJSON(500, gin.H{
"success": false,
"error": err.Error(),
})
return return
} }
// Verify this is a valid ticket and it is closed // Verify this is a valid ticket and it is closed
if archive.Uuid == uuid.Nil{ if archive.Uuid == uuid.Nil {
ctx.Redirect(302, fmt.Sprintf("/manage/%d/logs/modmail", guild.Id)) utils.ErrorPage(ctx, 404, "Modmail archive with provided UUID not found")
return return
} }
// Verify this modmail ticket was for this guild // Verify this modmail ticket was for this guild
if archive.GuildId != guildId { if archive.GuildId != guildId {
ctx.Redirect(302, fmt.Sprintf("/manage/%d/logs/modmail", guild.Id)) utils.ErrorPage(ctx, 403, "Modmail archive does not belong to this server")
return return
} }
// Verify the user has permissions to be here // Verify the user has permissions to be here
if utils.GetPermissionLevel(guildId, userId) < permission.Support && archive.UserId != userId { if utils.GetPermissionLevel(guildId, userId) < permission.Support && archive.UserId != userId {
ctx.Redirect(302, config.Conf.Server.BaseUrl) // TODO: 403 Page utils.ErrorPage(ctx, 403, "You do not have permission to view this archive")
return return
} }
@ -78,18 +65,18 @@ func ModmailLogViewHandler(ctx *gin.Context) {
messages, err := Archiver.GetModmail(guildId, archiveUuid.String()) messages, err := Archiver.GetModmail(guildId, archiveUuid.String())
if err != nil { if err != nil {
if errors.Is(err, archiverclient.ErrExpired) { if errors.Is(err, archiverclient.ErrExpired) {
ctx.String(200, "Archives expired: Purchase premium for permanent log storage") // TODO: Actual error page utils.ErrorPage(ctx, 404, "Archive expired - purchase premium for permanent log storage")
return } else {
utils.ErrorPage(ctx, 500, err.Error())
} }
ctx.String(500, fmt.Sprintf("Failed to retrieve archive - please contact the developers: %s", err.Error()))
return return
} }
// format to html // format to html
html, err := Archiver.Encode(messages, fmt.Sprintf("modmail-%s", archiveUuid)) html, err := Archiver.Encode(messages, fmt.Sprintf("modmail-%s", archiveUuid))
if err != nil { if err != nil {
ctx.String(500, fmt.Sprintf("Failed to retrieve archive - please contact the developers: %s", err.Error())) utils.ErrorPage(ctx, 500, err.Error())
return return
} }

View File

@ -50,13 +50,14 @@ func CallbackHandler(ctx *gin.Context) {
code, ok := ctx.GetQuery("code") code, ok := ctx.GetQuery("code")
if !ok { if !ok {
ctx.String(400, "Discord provided an invalid Oauth2 code") utils.ErrorPage(ctx, 400, "Discord provided invalid Oauth2 code")
return return
} }
res, err := discord.AccessToken(code) res, err := discord.AccessToken(code)
if err != nil { if err != nil {
ctx.String(500, err.Error()) utils.ErrorPage(ctx, 500, err.Error())
return
} }
store.Set("access_token", res.AccessToken) store.Set("access_token", res.AccessToken)

View File

@ -17,14 +17,15 @@ func AuthenticateGuild(isApiMethod bool) gin.HandlerFunc {
parsed, err := strconv.ParseUint(guildId, 10, 64) parsed, err := strconv.ParseUint(guildId, 10, 64)
if err != nil { if err != nil {
if isApiMethod { if isApiMethod {
ctx.AbortWithStatusJSON(400, gin.H{ ctx.JSON(400, gin.H{
"success": false, "success": false,
"error": "Invalid guild ID", "error": "Invalid guild ID",
}) })
} else { } else {
ctx.Redirect(302, config.Conf.Server.BaseUrl) // TODO: 404 Page utils.ErrorPage(ctx, 400, "Invalid server ID")
ctx.Abort() ctx.Abort()
} }
ctx.Abort()
return return
} }
@ -35,7 +36,7 @@ func AuthenticateGuild(isApiMethod bool) gin.HandlerFunc {
if isApiMethod { if isApiMethod {
ctx.Redirect(302, fmt.Sprintf("https://invite.ticketsbot.net/?guild_id=%d&disable_guild_select=true&response_type=code&scope=bot%%20identify&redirect_uri=%s", parsed, config.Conf.Server.BaseUrl)) ctx.Redirect(302, fmt.Sprintf("https://invite.ticketsbot.net/?guild_id=%d&disable_guild_select=true&response_type=code&scope=bot%%20identify&redirect_uri=%s", parsed, config.Conf.Server.BaseUrl))
} else { } else {
ctx.Redirect(302, config.Conf.Server.BaseUrl) // TODO: 404 Page utils.ErrorPage(ctx, 404, "Couldn't find server with the provided ID")
} }
ctx.Abort() ctx.Abort()
return return
@ -52,20 +53,20 @@ func AuthenticateGuild(isApiMethod bool) gin.HandlerFunc {
"error": "Unauthorized", "error": "Unauthorized",
}) })
} else { } else {
ctx.Redirect(302, config.Conf.Server.BaseUrl) // TODO: 403 Page utils.ErrorPage(ctx, 403, "You don't have permission to be here - make sure the server owner has added you as an admin with t!addadmin")
ctx.Abort() ctx.Abort()
} }
} }
} else { } else {
if isApiMethod { if isApiMethod {
ctx.AbortWithStatusJSON(400, gin.H{ ctx.JSON(400, gin.H{
"success": false, "success": false,
"error": "Invalid guild ID", "error": "Invalid guild ID",
}) })
} else { } else {
ctx.Redirect(302, config.Conf.Server.BaseUrl) // TODO: 404 Page utils.ErrorPage(ctx, 400, "Invalid server ID")
ctx.Abort()
} }
ctx.Abort()
} }
} }
} }

View File

@ -149,6 +149,8 @@ func createRenderer() multitemplate.Renderer {
r = addManageTemplate(r, "panels", "./public/templates/includes/substitutionmodal.tmpl", "./public/templates/includes/paneleditmodal.tmpl") r = addManageTemplate(r, "panels", "./public/templates/includes/substitutionmodal.tmpl", "./public/templates/includes/paneleditmodal.tmpl")
r = addManageTemplate(r, "tags") r = addManageTemplate(r, "tags")
r = addErrorTemplate(r)
return r return r
} }
@ -183,6 +185,16 @@ func addManageTemplate(renderer multitemplate.Renderer, name string, extra ...st
return renderer return renderer
} }
func addErrorTemplate(renderer multitemplate.Renderer) multitemplate.Renderer {
files := []string{
"./public/templates/layouts/error.tmpl",
"./public/templates/includes/head.tmpl",
}
renderer.AddFromFiles("error", files...)
return renderer
}
func createLimiter(limit int64, period time.Duration) func(*gin.Context) { func createLimiter(limit int64, period time.Duration) func(*gin.Context) {
store := memory.NewStore() store := memory.NewStore()
rate := limiter.Rate{ rate := limiter.Rate{

View File

@ -1,5 +1,12 @@
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans&display=swap');
body, h1, .h1, h2, .h2, h3, .h3, h4, .h4, h5, .h5, h6, .h6, p, .navbar, .brand, .btn-simple, .alert, a, .td-name, td, button.close {
font-family: 'Noto Sans', sans-serif !important;
font-weight: 400 !important;
}
body { body {
font-family: 'Open Sans',sans-serif !important;
font-size: 1rem; font-size: 1rem;
font-weight: 400; font-weight: 400;
line-height: 1.5; line-height: 1.5;

View File

@ -18,6 +18,10 @@ async function getToken() {
return token; return token;
} }
function clearLocalStorage() {
window.localStorage.clear();
}
async function setDefaultHeader() { async function setDefaultHeader() {
const token = await getToken(); const token = await getToken();
axios.defaults.headers.common['Authorization'] = token; axios.defaults.headers.common['Authorization'] = token;

View File

@ -28,7 +28,7 @@
<a class="nav-link" href="/"><i class="fas fa-server icon"></i>Servers</a> <a class="nav-link" href="/"><i class="fas fa-server icon"></i>Servers</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="/logout"><i class="fas fa-sign-out-alt icon"></i>Logout</a> <a class="nav-link" href="/logout" onclick="clearLocalStorage();"><i class="fas fa-sign-out-alt icon"></i>Logout</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="#">{{.name}}<img class="avatar" src="{{.avatar}}?size=256" alt="Avatar"/></a> <a class="nav-link" href="#">{{.name}}<img class="avatar" src="{{.avatar}}?size=256" alt="Avatar"/></a>

View File

@ -16,7 +16,7 @@
</li> </li>
<li class="nav-item sidebar-bottom" style="bottom: 60px"> <li class="nav-item sidebar-bottom" style="bottom: 60px">
<a href="/logout"> <a href="/logout" onclick="clearLocalStorage();">
<i class="fas fa-sign-out-alt"></i> <i class="fas fa-sign-out-alt"></i>
<p>Logout</p> <p>Logout</p>
</a> </a>

View File

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html lang="en">
<head>
{{template "head" .}}
</head>
<body>
<div class="wrapper">
<div class="main-panel" style="width: 100% !important;">
<div class="container-fluid" style="height: 100%;">
<div class="row" style="padding-top: 10%">
<div class="col-md-6 offset-md-3">
<div class="card">
<div class="card-header">
<h4 class="card-title">Error {{.status}}</h4>
</div>
<div class="card-body">
<p class="white">{{.error}}</p>
</div>
<div class="card-footer">
<div class="container-fluid">
<div class="row">
<div class="col-md-2 offset-md-8">
<button type="button" class="btn btn-info btn-fill" onclick="back();" style="width: 100%">Back</button>
</div>
<div class="col-md-2">
<button type="button" class="btn btn-primary btn-fill" onclick="home()" style="width: 100%">Home</button>
</div>
</div>
</div>
</div>
</div>
<script>
function back() {
window.history.back();
}
function home() {
window.location.href = '/'
}
</script>
</div>
</div>
</div>
</div>
</div>
</body>
</html>

10
utils/errorpage.go Normal file
View File

@ -0,0 +1,10 @@
package utils
import "github.com/gin-gonic/gin"
func ErrorPage(ctx *gin.Context, statusCode int, error string) {
ctx.HTML(statusCode, "error", gin.H{
"status": statusCode,
"error": error,
})
}