fix(ui): styled 403 Access Denied page matching 404 layout #424

Merged
jmiller merged 1 commits from dev into main 2026-06-02 15:06:08 +00:00
4 changed files with 40 additions and 2 deletions
+1
View File
@@ -110,6 +110,7 @@
"loading": "Loading…",
"files": "Files",
"error_title": "Error",
"error403": "You do not have permission to access this resource. If you believe this is an error, contact the repository owner.",
"error404": "The page you are trying to reach either <strong>does not exist</strong> or <strong>you are not authorized</strong> to view it.",
"error503": "The server could not complete your request. Please try again later.",
"go_back": "Go Back",
+20
View File
@@ -169,6 +169,26 @@ func (ctx *Context) notFoundInternal(logMsg string, logErr error) {
ctx.HTML(http.StatusNotFound, "status/404")
}
// Forbidden displays a styled 403 (Access Denied) page, matching the 404 page layout.
func (ctx *Context) Forbidden() {
showHTML := false
for _, part := range ctx.Req.Header["Accept"] {
if strings.Contains(part, "text/html") {
showHTML = true
break
}
}
if !showHTML {
ctx.plainTextInternal(3, http.StatusForbidden, []byte("Access denied.\n"))
return
}
ctx.Data["IsRepo"] = ctx.Repo.Repository != nil
ctx.Data["Title"] = "Access Denied"
ctx.HTML(http.StatusForbidden, "status/403")
}
// ServerError displays a 500 (Internal Server Error) page and prints the given error, if any.
// If the error is controlled by our error system, a related 404 page can be displayed instead.
func (ctx *Context) ServerError(logMsg string, logErr error) {
+2 -2
View File
@@ -451,11 +451,11 @@ func repoAssignmentLegacy(ctx *Context, data *repoAssignmentPrepareDataStruct) {
ctx.Data["LicensedReadOnly"] = true
// Continue — don't block access.
} else {
ctx.HTTPError(http.StatusForbidden, "You do not have permission to access this repository")
ctx.Forbidden()
return
}
} else {
ctx.HTTPError(http.StatusForbidden, "You do not have permission to access this repository")
ctx.Forbidden()
return
}
}
+17
View File
@@ -0,0 +1,17 @@
{{template "base/head" .}}
<div role="main" aria-label="{{.Title}}" class="page-content {{if .IsRepo}}repository{{end}}">
{{if .IsRepo}}{{template "repo/header" .}}{{end}}
<div class="ui container">
{{template "base/alert" .}}
<div class="status-page-error">
<div class="status-page-error-title">403 Access Denied</div>
<div class="tw-text-center">
<div class="tw-my-4">{{if .AccessDeniedPrompt}}{{.AccessDeniedPrompt}}{{else}}{{ctx.Locale.Tr "error403"}}{{end}}</div>
{{if not .IsSigned}}
<a class="ui primary button tw-my-4" href="{{AppSubUrl}}/user/login">{{ctx.Locale.Tr "sign_in"}}</a>
{{end}}
</div>
</div>
</div>
</div>
{{template "base/footer" .}}