From 1e877613bf941ae9bed17e5b6c5b118bd3107777 Mon Sep 17 00:00:00 2001
From: a1012112796 <1012112796@qq.com>
Date: Wed, 28 Apr 2021 20:35:06 +0800
Subject: [PATCH] add `/assets` as root dir of public files (#15219)

* add `/assets` as root dir of public files

Signed-off-by: a1012112796 <1012112796@qq.com>

* move serviceworker.js

* make fmt

* fix some link

* fix test

* Apply suggestions from code review

Co-authored-by: silverwind <me@silverwind.io>

* Apply suggestions from code review

Co-authored-by: silverwind <me@silverwind.io>

Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Co-authored-by: zeripath <art27@cantab.net>
---
 integrations/links_test.go           |  2 +-
 models/avatar.go                     |  2 +-
 models/avatar_test.go                |  2 +-
 models/oauth2.go                     | 26 +++++++++++++-------------
 models/user.go                       |  6 +++---
 modules/public/public.go             |  1 -
 modules/setting/picture.go           |  2 +-
 modules/setting/setting.go           |  4 ++--
 modules/templates/helper.go          |  2 +-
 routers/routes/web.go                |  1 +
 routers/user/profile.go              |  5 ++++-
 web_src/js/features/serviceworker.js |  2 +-
 12 files changed, 29 insertions(+), 26 deletions(-)

diff --git a/integrations/links_test.go b/integrations/links_test.go
index e16b688c8..3b9c245fc 100644
--- a/integrations/links_test.go
+++ b/integrations/links_test.go
@@ -51,7 +51,7 @@ func TestRedirectsNoLogin(t *testing.T) {
 		"/user2/repo1/src/master":                    "/user2/repo1/src/branch/master",
 		"/user2/repo1/src/master/file.txt":           "/user2/repo1/src/branch/master/file.txt",
 		"/user2/repo1/src/master/directory/file.txt": "/user2/repo1/src/branch/master/directory/file.txt",
-		"/user/avatar/Ghost/-1":                      "/img/avatar_default.png",
+		"/user/avatar/Ghost/-1":                      "/assets/img/avatar_default.png",
 		"/api/v1/swagger":                            "/api/swagger",
 	}
 	for link, redirectLink := range redirects {
diff --git a/models/avatar.go b/models/avatar.go
index de416a1db..4f02fe508 100644
--- a/models/avatar.go
+++ b/models/avatar.go
@@ -32,7 +32,7 @@ func DefaultAvatarLink() string {
 		return ""
 	}
 
-	u.Path = path.Join(u.Path, "/img/avatar_default.png")
+	u.Path = path.Join(u.Path, "/assets/img/avatar_default.png")
 	return u.String()
 }
 
diff --git a/models/avatar_test.go b/models/avatar_test.go
index 89540705a..bf99897d8 100644
--- a/models/avatar_test.go
+++ b/models/avatar_test.go
@@ -41,7 +41,7 @@ func TestHashEmail(t *testing.T) {
 
 func TestSizedAvatarLink(t *testing.T) {
 	disableGravatar()
-	assert.Equal(t, "/suburl/img/avatar_default.png",
+	assert.Equal(t, "/suburl/assets/img/avatar_default.png",
 		SizedAvatarLink("gitea@example.com", 100))
 
 	enableGravatar(t)
diff --git a/models/oauth2.go b/models/oauth2.go
index 83e2e8c43..cc9de74f8 100644
--- a/models/oauth2.go
+++ b/models/oauth2.go
@@ -23,11 +23,11 @@ type OAuth2Provider struct {
 // key is used to map the OAuth2Provider with the goth provider type (also in LoginSource.OAuth2Config.Provider)
 // value is used to store display data
 var OAuth2Providers = map[string]OAuth2Provider{
-	"bitbucket": {Name: "bitbucket", DisplayName: "Bitbucket", Image: "/img/auth/bitbucket.png"},
-	"dropbox":   {Name: "dropbox", DisplayName: "Dropbox", Image: "/img/auth/dropbox.png"},
-	"facebook":  {Name: "facebook", DisplayName: "Facebook", Image: "/img/auth/facebook.png"},
+	"bitbucket": {Name: "bitbucket", DisplayName: "Bitbucket", Image: "/assets/img/auth/bitbucket.png"},
+	"dropbox":   {Name: "dropbox", DisplayName: "Dropbox", Image: "/assets/img/auth/dropbox.png"},
+	"facebook":  {Name: "facebook", DisplayName: "Facebook", Image: "/assets/img/auth/facebook.png"},
 	"github": {
-		Name: "github", DisplayName: "GitHub", Image: "/img/auth/github.png",
+		Name: "github", DisplayName: "GitHub", Image: "/assets/img/auth/github.png",
 		CustomURLMapping: &oauth2.CustomURLMapping{
 			TokenURL:   oauth2.GetDefaultTokenURL("github"),
 			AuthURL:    oauth2.GetDefaultAuthURL("github"),
@@ -36,19 +36,19 @@ var OAuth2Providers = map[string]OAuth2Provider{
 		},
 	},
 	"gitlab": {
-		Name: "gitlab", DisplayName: "GitLab", Image: "/img/auth/gitlab.png",
+		Name: "gitlab", DisplayName: "GitLab", Image: "/assets/img/auth/gitlab.png",
 		CustomURLMapping: &oauth2.CustomURLMapping{
 			TokenURL:   oauth2.GetDefaultTokenURL("gitlab"),
 			AuthURL:    oauth2.GetDefaultAuthURL("gitlab"),
 			ProfileURL: oauth2.GetDefaultProfileURL("gitlab"),
 		},
 	},
-	"gplus":         {Name: "gplus", DisplayName: "Google", Image: "/img/auth/google.png"},
-	"openidConnect": {Name: "openidConnect", DisplayName: "OpenID Connect", Image: "/img/auth/openid_connect.svg"},
-	"twitter":       {Name: "twitter", DisplayName: "Twitter", Image: "/img/auth/twitter.png"},
-	"discord":       {Name: "discord", DisplayName: "Discord", Image: "/img/auth/discord.png"},
+	"gplus":         {Name: "gplus", DisplayName: "Google", Image: "/assets/img/auth/google.png"},
+	"openidConnect": {Name: "openidConnect", DisplayName: "OpenID Connect", Image: "/assets/img/auth/openid_connect.svg"},
+	"twitter":       {Name: "twitter", DisplayName: "Twitter", Image: "/assets/img/auth/twitter.png"},
+	"discord":       {Name: "discord", DisplayName: "Discord", Image: "/assets/img/auth/discord.png"},
 	"gitea": {
-		Name: "gitea", DisplayName: "Gitea", Image: "/img/auth/gitea.png",
+		Name: "gitea", DisplayName: "Gitea", Image: "/assets/img/auth/gitea.png",
 		CustomURLMapping: &oauth2.CustomURLMapping{
 			TokenURL:   oauth2.GetDefaultTokenURL("gitea"),
 			AuthURL:    oauth2.GetDefaultAuthURL("gitea"),
@@ -56,16 +56,16 @@ var OAuth2Providers = map[string]OAuth2Provider{
 		},
 	},
 	"nextcloud": {
-		Name: "nextcloud", DisplayName: "Nextcloud", Image: "/img/auth/nextcloud.png",
+		Name: "nextcloud", DisplayName: "Nextcloud", Image: "/assets/img/auth/nextcloud.png",
 		CustomURLMapping: &oauth2.CustomURLMapping{
 			TokenURL:   oauth2.GetDefaultTokenURL("nextcloud"),
 			AuthURL:    oauth2.GetDefaultAuthURL("nextcloud"),
 			ProfileURL: oauth2.GetDefaultProfileURL("nextcloud"),
 		},
 	},
-	"yandex": {Name: "yandex", DisplayName: "Yandex", Image: "/img/auth/yandex.png"},
+	"yandex": {Name: "yandex", DisplayName: "Yandex", Image: "/assets/img/auth/yandex.png"},
 	"mastodon": {
-		Name: "mastodon", DisplayName: "Mastodon", Image: "/img/auth/mastodon.png",
+		Name: "mastodon", DisplayName: "Mastodon", Image: "/assets/img/auth/mastodon.png",
 		CustomURLMapping: &oauth2.CustomURLMapping{
 			AuthURL: oauth2.GetDefaultAuthURL("mastodon"),
 		},
diff --git a/models/user.go b/models/user.go
index 53a8ac348..6665782d3 100644
--- a/models/user.go
+++ b/models/user.go
@@ -25,7 +25,6 @@ import (
 	"code.gitea.io/gitea/modules/generate"
 	"code.gitea.io/gitea/modules/git"
 	"code.gitea.io/gitea/modules/log"
-	"code.gitea.io/gitea/modules/public"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/storage"
 	"code.gitea.io/gitea/modules/structs"
@@ -772,7 +771,7 @@ func (u *User) IsGhost() bool {
 }
 
 var (
-	reservedUsernames = append([]string{
+	reservedUsernames = []string{
 		".",
 		"..",
 		".well-known",
@@ -807,7 +806,8 @@ var (
 		"stars",
 		"template",
 		"user",
-	}, public.KnownPublicEntries...)
+		"favicon.ico",
+	}
 
 	reservedUserPatterns = []string{"*.keys", "*.gpg"}
 )
diff --git a/modules/public/public.go b/modules/public/public.go
index 14525cfa0..c68f98035 100644
--- a/modules/public/public.go
+++ b/modules/public/public.go
@@ -32,7 +32,6 @@ var KnownPublicEntries = []string{
 	"js",
 	"serviceworker.js",
 	"vendor",
-	"favicon.ico",
 }
 
 // Custom implements the static handler for serving custom assets.
diff --git a/modules/setting/picture.go b/modules/setting/picture.go
index fa97245aa..415552d7c 100644
--- a/modules/setting/picture.go
+++ b/modules/setting/picture.go
@@ -110,5 +110,5 @@ func newRepoAvatarService() {
 	RepoAvatar.Storage = getStorage("repo-avatars", storageType, repoAvatarSec)
 
 	RepoAvatar.Fallback = sec.Key("REPOSITORY_AVATAR_FALLBACK").MustString("none")
-	RepoAvatar.FallbackImage = sec.Key("REPOSITORY_AVATAR_FALLBACK_IMAGE").MustString("/img/repo_default.png")
+	RepoAvatar.FallbackImage = sec.Key("REPOSITORY_AVATAR_FALLBACK_IMAGE").MustString("/assets/img/repo_default.png")
 }
diff --git a/modules/setting/setting.go b/modules/setting/setting.go
index 7963776fd..aef0d8670 100644
--- a/modules/setting/setting.go
+++ b/modules/setting/setting.go
@@ -1139,12 +1139,12 @@ func MakeManifestData(appName string, appURL string, absoluteAssetURL string) []
 		StartURL:  appURL,
 		Icons: []manifestIcon{
 			{
-				Src:   absoluteAssetURL + "/img/logo.png",
+				Src:   absoluteAssetURL + "/assets/img/logo.png",
 				Type:  "image/png",
 				Sizes: "512x512",
 			},
 			{
-				Src:   absoluteAssetURL + "/img/logo.svg",
+				Src:   absoluteAssetURL + "/assets/img/logo.svg",
 				Type:  "image/svg+xml",
 				Sizes: "512x512",
 			},
diff --git a/modules/templates/helper.go b/modules/templates/helper.go
index 7b175bfab..8f1362afc 100644
--- a/modules/templates/helper.go
+++ b/modules/templates/helper.go
@@ -61,7 +61,7 @@ func NewFuncMap() []template.FuncMap {
 			return setting.AppSubURL
 		},
 		"StaticUrlPrefix": func() string {
-			return setting.StaticURLPrefix
+			return setting.StaticURLPrefix + "/assets"
 		},
 		"AppUrl": func() string {
 			return setting.AppURL
diff --git a/routers/routes/web.go b/routers/routes/web.go
index cedab7843..ceb024249 100644
--- a/routers/routes/web.go
+++ b/routers/routes/web.go
@@ -152,6 +152,7 @@ func WebRoutes() *web.Route {
 		&public.Options{
 			Directory:   path.Join(setting.StaticRootPath, "public"),
 			SkipLogging: setting.DisableRouterLog,
+			Prefix:      "/assets",
 		},
 	))
 
diff --git a/routers/user/profile.go b/routers/user/profile.go
index bb4c0cd5b..8ff1ee24a 100644
--- a/routers/user/profile.go
+++ b/routers/user/profile.go
@@ -46,11 +46,14 @@ func GetUserByParams(ctx *context.Context) *models.User {
 // Profile render user's profile page
 func Profile(ctx *context.Context) {
 	uname := ctx.Params(":username")
+
 	// Special handle for FireFox requests favicon.ico.
 	if uname == "favicon.ico" {
 		ctx.ServeFile(path.Join(setting.StaticRootPath, "public/img/favicon.png"))
 		return
-	} else if strings.HasSuffix(uname, ".png") {
+	}
+
+	if strings.HasSuffix(uname, ".png") {
 		ctx.Error(http.StatusNotFound)
 		return
 	}
diff --git a/web_src/js/features/serviceworker.js b/web_src/js/features/serviceworker.js
index fa415866c..400a33140 100644
--- a/web_src/js/features/serviceworker.js
+++ b/web_src/js/features/serviceworker.js
@@ -35,7 +35,7 @@ export default async function initServiceWorker() {
       // the spec strictly requires it to be same-origin so it has to be AppSubUrl to work
       await Promise.all([
         checkCacheValidity(),
-        navigator.serviceWorker.register(`${AppSubUrl}/serviceworker.js`),
+        navigator.serviceWorker.register(`${AppSubUrl}/assets/serviceworker.js`),
       ]);
     } catch (err) {
       console.error(err);