mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-10-29 04:52:24 -05:00
[feature] Allow users to set custom css for their profiles + threads (#808)
* add custom css account property + db func to fetch * allow account to get/set custom css * serve custom css for an account * go fmt * use monospace for customcss, add link * add custom css to account cache * fix broken field * add custom css docs to user guide * add `accounts-allow-custom-css` config flag * add allow custom css to /api/v1/instance response * only show/set custom css if allowed to do so * only set/serve custom account css if enabled * update swagger docs * chain promise * make bool a bit clearer * use cache for GetAccountCustomCSSByUsername
This commit is contained in:
parent
268f252e0d
commit
b42469e4e0
40 changed files with 458 additions and 39 deletions
60
internal/web/customcss.go
Normal file
60
internal/web/customcss.go
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
GoToSocial
|
||||
Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package web
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/api"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
)
|
||||
|
||||
func (m *Module) customCSSGETHandler(c *gin.Context) {
|
||||
if !config.GetAccountsAllowCustomCSS() {
|
||||
err := errors.New("accounts-allow-custom-css is not enabled on this instance")
|
||||
api.ErrorHandler(c, gtserror.NewErrorNotFound(err), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
if _, err := api.NegotiateAccept(c, api.TextCSS); err != nil {
|
||||
api.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
// usernames on our instance will always be lowercase
|
||||
username := strings.ToLower(c.Param(usernameKey))
|
||||
if username == "" {
|
||||
err := errors.New("no account username specified")
|
||||
api.ErrorHandler(c, gtserror.NewErrorBadRequest(err, err.Error()), m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
customCSS, errWithCode := m.processor.AccountGetCustomCSSForUsername(c.Request.Context(), username)
|
||||
if errWithCode != nil {
|
||||
api.ErrorHandler(c, errWithCode, m.processor.InstanceGet)
|
||||
return
|
||||
}
|
||||
|
||||
c.Header("Cache-Control", "no-cache")
|
||||
c.Data(http.StatusOK, "text/css; charset=utf-8", []byte(customCSS))
|
||||
}
|
||||
|
|
@ -99,6 +99,15 @@ func (m *Module) profileGETHandler(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
stylesheets := []string{
|
||||
"/assets/Fork-Awesome/css/fork-awesome.min.css",
|
||||
"/assets/dist/status.css",
|
||||
"/assets/dist/profile.css",
|
||||
}
|
||||
if config.GetAccountsAllowCustomCSS() {
|
||||
stylesheets = append(stylesheets, "/@"+account.Username+"/custom.css")
|
||||
}
|
||||
|
||||
c.HTML(http.StatusOK, "profile.tmpl", gin.H{
|
||||
"instance": instance,
|
||||
"account": account,
|
||||
|
|
@ -106,11 +115,7 @@ func (m *Module) profileGETHandler(c *gin.Context) {
|
|||
"statuses": statusResp.Items,
|
||||
"statuses_next": statusResp.NextLink,
|
||||
"show_back_to_top": showBackToTop,
|
||||
"stylesheets": []string{
|
||||
"/assets/Fork-Awesome/css/fork-awesome.min.css",
|
||||
"/assets/dist/status.css",
|
||||
"/assets/dist/profile.css",
|
||||
},
|
||||
"stylesheets": stylesheets,
|
||||
"javascript": []string{
|
||||
"/assets/dist/frontend.js",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -104,15 +104,20 @@ func (m *Module) threadGETHandler(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
stylesheets := []string{
|
||||
"/assets/Fork-Awesome/css/fork-awesome.min.css",
|
||||
"/assets/dist/status.css",
|
||||
}
|
||||
if config.GetAccountsAllowCustomCSS() {
|
||||
stylesheets = append(stylesheets, "/@"+username+"/custom.css")
|
||||
}
|
||||
|
||||
c.HTML(http.StatusOK, "thread.tmpl", gin.H{
|
||||
"instance": instance,
|
||||
"status": status,
|
||||
"context": context,
|
||||
"ogMeta": ogBase(instance).withStatus(status),
|
||||
"stylesheets": []string{
|
||||
"/assets/Fork-Awesome/css/fork-awesome.min.css",
|
||||
"/assets/dist/status.css",
|
||||
},
|
||||
"instance": instance,
|
||||
"status": status,
|
||||
"context": context,
|
||||
"ogMeta": ogBase(instance).withStatus(status),
|
||||
"stylesheets": stylesheets,
|
||||
"javascript": []string{
|
||||
"/assets/dist/frontend.js",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import (
|
|||
const (
|
||||
confirmEmailPath = "/" + uris.ConfirmEmailPath
|
||||
profilePath = "/@:" + usernameKey
|
||||
customCSSPath = profilePath + "/custom.css"
|
||||
statusPath = profilePath + "/statuses/:" + statusIDKey
|
||||
adminPanelPath = "/admin"
|
||||
userPanelpath = "/user"
|
||||
|
|
@ -91,6 +92,9 @@ func (m *Module) Route(s router.Router) error {
|
|||
// serve profile pages at /@username
|
||||
s.AttachHandler(http.MethodGet, profilePath, m.profileGETHandler)
|
||||
|
||||
// serve custom css at /@username/custom.css
|
||||
s.AttachHandler(http.MethodGet, customCSSPath, m.customCSSGETHandler)
|
||||
|
||||
// serve statuses
|
||||
s.AttachHandler(http.MethodGet, statusPath, m.threadGETHandler)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue