From 5eff3c38b48746d432f49016cc1ef9704688bd00 Mon Sep 17 00:00:00 2001 From: Ben Visness Date: Tue, 26 Oct 2021 19:45:11 -0500 Subject: [PATCH] Tweak routing middleware, add socials to banner Instead of doing project nav, which I am actively avoiding --- src/hmnurl/hmnurl_test.go | 29 ++-- src/hmnurl/urls.go | 45 ++++--- src/templates/mapping.go | 12 +- src/templates/src/include/header.html | 6 +- src/templates/svg/discord.svg | 7 + src/templates/svg/twitter.svg | 5 + src/website/landing.go | 2 +- src/website/podcast.go | 30 ++--- src/website/routes.go | 184 +++++++++++++------------- 9 files changed, 165 insertions(+), 155 deletions(-) create mode 100644 src/templates/svg/discord.svg create mode 100644 src/templates/svg/twitter.svg diff --git a/src/hmnurl/hmnurl_test.go b/src/hmnurl/hmnurl_test.go index 4f70ca2..4ba4461 100644 --- a/src/hmnurl/hmnurl_test.go +++ b/src/hmnurl/hmnurl_test.go @@ -140,30 +140,27 @@ func TestProjectEdit(t *testing.T) { } func TestPodcast(t *testing.T) { - AssertRegexMatch(t, BuildPodcast(""), RegexPodcast, nil) - AssertSubdomain(t, BuildPodcast(""), "") - AssertSubdomain(t, BuildPodcast("hmn"), "") - AssertSubdomain(t, BuildPodcast("hero"), "hero") + AssertRegexMatch(t, BuildPodcast(), RegexPodcast, nil) } func TestPodcastEdit(t *testing.T) { - AssertRegexMatch(t, BuildPodcastEdit(""), RegexPodcastEdit, nil) + AssertRegexMatch(t, BuildPodcastEdit(), RegexPodcastEdit, nil) } func TestPodcastEpisode(t *testing.T) { - AssertRegexMatch(t, BuildPodcastEpisode("", "test"), RegexPodcastEpisode, map[string]string{"episodeid": "test"}) + AssertRegexMatch(t, BuildPodcastEpisode("test"), RegexPodcastEpisode, map[string]string{"episodeid": "test"}) } func TestPodcastEpisodeNew(t *testing.T) { - AssertRegexMatch(t, BuildPodcastEpisodeNew(""), RegexPodcastEpisodeNew, nil) + AssertRegexMatch(t, BuildPodcastEpisodeNew(), RegexPodcastEpisodeNew, nil) } func TestPodcastEpisodeEdit(t *testing.T) { - AssertRegexMatch(t, BuildPodcastEpisodeEdit("", "test"), RegexPodcastEpisodeEdit, map[string]string{"episodeid": "test"}) + AssertRegexMatch(t, BuildPodcastEpisodeEdit("test"), RegexPodcastEpisodeEdit, map[string]string{"episodeid": "test"}) } func TestPodcastRSS(t *testing.T) { - AssertRegexMatch(t, BuildPodcastRSS(""), RegexPodcastRSS, nil) + AssertRegexMatch(t, BuildPodcastRSS(), RegexPodcastRSS, nil) } func TestForum(t *testing.T) { @@ -265,23 +262,19 @@ func TestBlogPostReply(t *testing.T) { } func TestLibrary(t *testing.T) { - AssertRegexMatch(t, BuildLibrary(""), RegexLibrary, nil) - AssertSubdomain(t, BuildLibrary("hero"), "hero") + AssertRegexMatch(t, BuildLibrary(), RegexLibrary, nil) } func TestLibraryAll(t *testing.T) { - AssertRegexMatch(t, BuildLibraryAll(""), RegexLibraryAll, nil) - AssertSubdomain(t, BuildLibraryAll("hero"), "hero") + AssertRegexMatch(t, BuildLibraryAll(), RegexLibraryAll, nil) } func TestLibraryTopic(t *testing.T) { - AssertRegexMatch(t, BuildLibraryTopic("", 1), RegexLibraryTopic, map[string]string{"topicid": "1"}) - AssertSubdomain(t, BuildLibraryTopic("hero", 1), "hero") + AssertRegexMatch(t, BuildLibraryTopic(1), RegexLibraryTopic, map[string]string{"topicid": "1"}) } func TestLibraryResource(t *testing.T) { - AssertRegexMatch(t, BuildLibraryResource("", 1), RegexLibraryResource, map[string]string{"resourceid": "1"}) - AssertSubdomain(t, BuildLibraryResource("hero", 1), "hero") + AssertRegexMatch(t, BuildLibraryResource(1), RegexLibraryResource, map[string]string{"resourceid": "1"}) } func TestEpisodeGuide(t *testing.T) { @@ -429,5 +422,5 @@ func AssertRegexNoMatch(t *testing.T, fullUrl string, regex *regexp.Regexp) { func TestThingsThatDontNeedCoverage(t *testing.T) { // look the other way ಠ_ಠ - BuildPodcastEpisodeFile("foo", "bar") + BuildPodcastEpisodeFile("foo") } diff --git a/src/hmnurl/urls.go b/src/hmnurl/urls.go index 9709159..68568f5 100644 --- a/src/hmnurl/urls.go +++ b/src/hmnurl/urls.go @@ -8,6 +8,7 @@ import ( "strings" "git.handmade.network/hmn/hmn/src/logging" + "git.handmade.network/hmn/hmn/src/models" "git.handmade.network/hmn/hmn/src/oops" ) @@ -316,49 +317,49 @@ func BuildProjectEdit(slug string, section string) string { var RegexPodcast = regexp.MustCompile(`^/podcast$`) -func BuildPodcast(projectSlug string) string { +func BuildPodcast() string { defer CatchPanic() - return ProjectUrl("/podcast", nil, projectSlug) + return Url("/podcast", nil) } var RegexPodcastEdit = regexp.MustCompile(`^/podcast/edit$`) -func BuildPodcastEdit(projectSlug string) string { +func BuildPodcastEdit() string { defer CatchPanic() - return ProjectUrl("/podcast/edit", nil, projectSlug) + return Url("/podcast/edit", nil) } var RegexPodcastEpisode = regexp.MustCompile(`^/podcast/ep/(?P[^/]+)$`) -func BuildPodcastEpisode(projectSlug string, episodeGUID string) string { +func BuildPodcastEpisode(episodeGUID string) string { defer CatchPanic() - return ProjectUrl(fmt.Sprintf("/podcast/ep/%s", episodeGUID), nil, projectSlug) + return Url(fmt.Sprintf("/podcast/ep/%s", episodeGUID), nil) } var RegexPodcastEpisodeNew = regexp.MustCompile(`^/podcast/ep/new$`) -func BuildPodcastEpisodeNew(projectSlug string) string { +func BuildPodcastEpisodeNew() string { defer CatchPanic() - return ProjectUrl("/podcast/ep/new", nil, projectSlug) + return Url("/podcast/ep/new", nil) } var RegexPodcastEpisodeEdit = regexp.MustCompile(`^/podcast/ep/(?P[^/]+)/edit$`) -func BuildPodcastEpisodeEdit(projectSlug string, episodeGUID string) string { +func BuildPodcastEpisodeEdit(episodeGUID string) string { defer CatchPanic() - return ProjectUrl(fmt.Sprintf("/podcast/ep/%s/edit", episodeGUID), nil, projectSlug) + return Url(fmt.Sprintf("/podcast/ep/%s/edit", episodeGUID), nil) } var RegexPodcastRSS = regexp.MustCompile(`^/podcast/podcast.xml$`) -func BuildPodcastRSS(projectSlug string) string { +func BuildPodcastRSS() string { defer CatchPanic() - return ProjectUrl("/podcast/podcast.xml", nil, projectSlug) + return Url("/podcast/podcast.xml", nil) } -func BuildPodcastEpisodeFile(projectSlug string, filename string) string { +func BuildPodcastEpisodeFile(filename string) string { defer CatchPanic() - return BuildUserFile(fmt.Sprintf("podcast/%s/%s", projectSlug, filename)) + return BuildUserFile(fmt.Sprintf("podcast/%s/%s", models.HMNProjectSlug, filename)) } /* @@ -540,21 +541,21 @@ var RegexLibraryAny = regexp.MustCompile(`^/library`) var RegexLibrary = regexp.MustCompile(`^/library$`) -func BuildLibrary(projectSlug string) string { +func BuildLibrary() string { defer CatchPanic() - return ProjectUrl("/library", nil, projectSlug) + return Url("/library", nil) } var RegexLibraryAll = regexp.MustCompile(`^/library/all$`) -func BuildLibraryAll(projectSlug string) string { +func BuildLibraryAll() string { defer CatchPanic() - return ProjectUrl("/library/all", nil, projectSlug) + return Url("/library/all", nil) } var RegexLibraryTopic = regexp.MustCompile(`^/library/topic/(?P\d+)$`) -func BuildLibraryTopic(projectSlug string, topicId int) string { +func BuildLibraryTopic(topicId int) string { defer CatchPanic() if topicId < 1 { panic(oops.New(nil, "Invalid library topic ID (%d), must be >= 1", topicId)) @@ -564,16 +565,16 @@ func BuildLibraryTopic(projectSlug string, topicId int) string { builder.WriteString("/library/topic/") builder.WriteString(strconv.Itoa(topicId)) - return ProjectUrl(builder.String(), nil, projectSlug) + return Url(builder.String(), nil) } var RegexLibraryResource = regexp.MustCompile(`^/library/resource/(?P\d+)$`) -func BuildLibraryResource(projectSlug string, resourceId int) string { +func BuildLibraryResource(resourceId int) string { defer CatchPanic() builder := buildLibraryResourcePath(resourceId) - return ProjectUrl(builder.String(), nil, projectSlug) + return Url(builder.String(), nil) } /* diff --git a/src/templates/mapping.go b/src/templates/mapping.go index e68cd56..460bcad 100644 --- a/src/templates/mapping.go +++ b/src/templates/mapping.go @@ -327,7 +327,7 @@ func TimelineItemsToJSON(items []TimelineItem) string { return builder.String() } -func PodcastToTemplate(projectSlug string, podcast *models.Podcast, imageFilename string) Podcast { +func PodcastToTemplate(podcast *models.Podcast, imageFilename string) Podcast { imageUrl := "" if imageFilename != "" { imageUrl = hmnurl.BuildUserFile(imageFilename) @@ -337,9 +337,9 @@ func PodcastToTemplate(projectSlug string, podcast *models.Podcast, imageFilenam Description: podcast.Description, Language: podcast.Language, ImageUrl: imageUrl, - Url: hmnurl.BuildPodcast(projectSlug), + Url: hmnurl.BuildPodcast(), - RSSUrl: hmnurl.BuildPodcastRSS(projectSlug), + RSSUrl: hmnurl.BuildPodcastRSS(), // TODO(asaf): Move this to the db if we want to support user podcasts AppleUrl: "https://podcasts.apple.com/us/podcast/the-handmade-network-podcast/id1507790631", GoogleUrl: "https://www.google.com/podcasts?feed=aHR0cHM6Ly9oYW5kbWFkZS5uZXR3b3JrL3BvZGNhc3QvcG9kY2FzdC54bWw%3D", @@ -347,7 +347,7 @@ func PodcastToTemplate(projectSlug string, podcast *models.Podcast, imageFilenam } } -func PodcastEpisodeToTemplate(projectSlug string, episode *models.PodcastEpisode, audioFileSize int64, imageFilename string) PodcastEpisode { +func PodcastEpisodeToTemplate(episode *models.PodcastEpisode, audioFileSize int64, imageFilename string) PodcastEpisode { imageUrl := "" if imageFilename != "" { imageUrl = hmnurl.BuildUserFile(imageFilename) @@ -358,9 +358,9 @@ func PodcastEpisodeToTemplate(projectSlug string, episode *models.PodcastEpisode Description: episode.Description, DescriptionHtml: template.HTML(episode.DescriptionHtml), EpisodeNumber: episode.EpisodeNumber, - Url: hmnurl.BuildPodcastEpisode(projectSlug, episode.GUID.String()), + Url: hmnurl.BuildPodcastEpisode(episode.GUID.String()), ImageUrl: imageUrl, - FileUrl: hmnurl.BuildPodcastEpisodeFile(projectSlug, episode.AudioFile), + FileUrl: hmnurl.BuildPodcastEpisodeFile(episode.AudioFile), FileSize: audioFileSize, PublicationDate: episode.PublicationDate, Duration: episode.Duration, diff --git a/src/templates/src/include/header.html b/src/templates/src/include/header.html index c6c96cb..549b7ce 100644 --- a/src/templates/src/include/header.html +++ b/src/templates/src/include/header.html @@ -25,7 +25,7 @@ {{ end }} - diff --git a/src/templates/svg/discord.svg b/src/templates/svg/discord.svg new file mode 100644 index 0000000..e0e05bf --- /dev/null +++ b/src/templates/svg/discord.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/templates/svg/twitter.svg b/src/templates/svg/twitter.svg new file mode 100644 index 0000000..91a3479 --- /dev/null +++ b/src/templates/svg/twitter.svg @@ -0,0 +1,5 @@ + + +twitter + + diff --git a/src/website/landing.go b/src/website/landing.go index 409389a..3878362 100644 --- a/src/website/landing.go +++ b/src/website/landing.go @@ -166,7 +166,7 @@ func Index(c *RequestContext) ResponseData { ManifestoUrl: hmnurl.BuildManifesto(), FeedUrl: hmnurl.BuildFeed(), - PodcastUrl: hmnurl.BuildPodcast(models.HMNProjectSlug), + PodcastUrl: hmnurl.BuildPodcast(), StreamsUrl: hmnurl.BuildStreams(), IRCUrl: hmnurl.BuildBlogThread(models.HMNProjectSlug, 1138, "[Tutorial] Handmade Network IRC"), DiscordUrl: "https://discord.gg/hxWxDee", diff --git a/src/website/podcast.go b/src/website/podcast.go index 40feb4a..50e2cbf 100644 --- a/src/website/podcast.go +++ b/src/website/podcast.go @@ -48,16 +48,16 @@ func PodcastIndex(c *RequestContext) ResponseData { podcastIndexData := PodcastIndexData{ BaseData: baseData, - Podcast: templates.PodcastToTemplate(c.CurrentProject.Slug, podcastResult.Podcast, podcastResult.ImageFile), + Podcast: templates.PodcastToTemplate(podcastResult.Podcast, podcastResult.ImageFile), } if canEdit { - podcastIndexData.EditUrl = hmnurl.BuildPodcastEdit(c.CurrentProject.Slug) - podcastIndexData.NewEpisodeUrl = hmnurl.BuildPodcastEpisodeNew(c.CurrentProject.Slug) + podcastIndexData.EditUrl = hmnurl.BuildPodcastEdit() + podcastIndexData.NewEpisodeUrl = hmnurl.BuildPodcastEpisodeNew() } for _, episode := range podcastResult.Episodes { - podcastIndexData.Episodes = append(podcastIndexData.Episodes, templates.PodcastEpisodeToTemplate(c.CurrentProject.Slug, episode, 0, podcastResult.ImageFile)) + podcastIndexData.Episodes = append(podcastIndexData.Episodes, templates.PodcastEpisodeToTemplate(episode, 0, podcastResult.ImageFile)) } var res ResponseData err = res.WriteTemplate("podcast_index.html", podcastIndexData, c.Perf) @@ -87,7 +87,7 @@ func PodcastEdit(c *RequestContext) ResponseData { return FourOhFour(c) } - podcast := templates.PodcastToTemplate(c.CurrentProject.Slug, podcastResult.Podcast, podcastResult.ImageFile) + podcast := templates.PodcastToTemplate(podcastResult.Podcast, podcastResult.ImageFile) baseData := getBaseData( c, fmt.Sprintf("Edit %s", podcast.Title), @@ -194,7 +194,7 @@ func PodcastEditSubmit(c *RequestContext) ResponseData { return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "Failed to commit db transaction")) } - res := c.Redirect(hmnurl.BuildPodcastEdit(c.CurrentProject.Slug), http.StatusSeeOther) + res := c.Redirect(hmnurl.BuildPodcastEdit(), http.StatusSeeOther) res.AddFutureNotice("success", "Podcast updated successfully.") return res } @@ -226,11 +226,11 @@ func PodcastEpisode(c *RequestContext) ResponseData { editUrl := "" if canEdit { - editUrl = hmnurl.BuildPodcastEpisodeEdit(c.CurrentProject.Slug, podcastResult.Episodes[0].GUID.String()) + editUrl = hmnurl.BuildPodcastEpisodeEdit(podcastResult.Episodes[0].GUID.String()) } - podcast := templates.PodcastToTemplate(c.CurrentProject.Slug, podcastResult.Podcast, podcastResult.ImageFile) - episode := templates.PodcastEpisodeToTemplate(c.CurrentProject.Slug, podcastResult.Episodes[0], 0, podcastResult.ImageFile) + podcast := templates.PodcastToTemplate(podcastResult.Podcast, podcastResult.ImageFile) + episode := templates.PodcastEpisodeToTemplate(podcastResult.Episodes[0], 0, podcastResult.ImageFile) baseData := getBaseData( c, fmt.Sprintf("%s | %s", episode.Title, podcast.Title), @@ -282,7 +282,7 @@ func PodcastEpisodeNew(c *RequestContext) ResponseData { return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "Failed to fetch podcast episode file list")) } - podcast := templates.PodcastToTemplate(c.CurrentProject.Slug, podcastResult.Podcast, "") + podcast := templates.PodcastToTemplate(podcastResult.Podcast, "") var res ResponseData baseData := getBaseData( c, @@ -326,8 +326,8 @@ func PodcastEpisodeEdit(c *RequestContext) ResponseData { } episode := podcastResult.Episodes[0] - podcast := templates.PodcastToTemplate(c.CurrentProject.Slug, podcastResult.Podcast, "") - podcastEpisode := templates.PodcastEpisodeToTemplate(c.CurrentProject.Slug, episode, 0, "") + podcast := templates.PodcastToTemplate(podcastResult.Podcast, "") + podcastEpisode := templates.PodcastEpisodeToTemplate(episode, 0, "") baseData := getBaseData( c, fmt.Sprintf("Edit episode %s | %s", podcastEpisode.Title, podcast.Title), @@ -491,7 +491,7 @@ func PodcastEpisodeSubmit(c *RequestContext) ResponseData { } } - res := c.Redirect(hmnurl.BuildPodcastEpisodeEdit(c.CurrentProject.Slug, guidStr), http.StatusSeeOther) + res := c.Redirect(hmnurl.BuildPodcastEpisodeEdit(guidStr), http.StatusSeeOther) res.AddFutureNotice("success", "Podcast episode updated successfully.") return res } @@ -519,7 +519,7 @@ func PodcastRSS(c *RequestContext) ResponseData { } podcastRSSData := PodcastRSSData{ - Podcast: templates.PodcastToTemplate(c.CurrentProject.Slug, podcastResult.Podcast, podcastResult.ImageFile), + Podcast: templates.PodcastToTemplate(podcastResult.Podcast, podcastResult.ImageFile), } for _, episode := range podcastResult.Episodes { @@ -530,7 +530,7 @@ func PodcastRSS(c *RequestContext) ResponseData { } else { filesize = stat.Size() } - podcastRSSData.Episodes = append(podcastRSSData.Episodes, templates.PodcastEpisodeToTemplate(c.CurrentProject.Slug, episode, filesize, podcastResult.ImageFile)) + podcastRSSData.Episodes = append(podcastRSSData.Episodes, templates.PodcastEpisodeToTemplate(episode, filesize, podcastResult.ImageFile)) } var res ResponseData diff --git a/src/website/routes.go b/src/website/routes.go index b5f2e3c..a66cbc8 100644 --- a/src/website/routes.go +++ b/src/website/routes.go @@ -45,8 +45,8 @@ func NewWebsiteRoutes(longRequestContext context.Context, conn *pgxpool.Pool, pe }, } - mainRoutes := routes - mainRoutes.Middleware = func(h Handler) Handler { + anyProject := routes + anyProject.Middleware = func(h Handler) Handler { return func(c *RequestContext) (res ResponseData) { c.Conn = conn @@ -67,8 +67,8 @@ func NewWebsiteRoutes(longRequestContext context.Context, conn *pgxpool.Pool, pe } } - staticPages := routes - staticPages.Middleware = func(h Handler) Handler { + hmnOnly := routes + hmnOnly.Middleware = func(h Handler) Handler { return func(c *RequestContext) (res ResponseData) { c.Conn = conn @@ -154,125 +154,125 @@ func NewWebsiteRoutes(longRequestContext context.Context, conn *pgxpool.Pool, pe return res }) - mainRoutes.GET(hmnurl.RegexHomepage, func(c *RequestContext) ResponseData { + anyProject.GET(hmnurl.RegexHomepage, func(c *RequestContext) ResponseData { if c.CurrentProject.IsHMN() { return Index(c) } else { return ProjectHomepage(c) } }) - staticPages.GET(hmnurl.RegexManifesto, Manifesto) - staticPages.GET(hmnurl.RegexAbout, About) - staticPages.GET(hmnurl.RegexCodeOfConduct, CodeOfConduct) - staticPages.GET(hmnurl.RegexCommunicationGuidelines, CommunicationGuidelines) - staticPages.GET(hmnurl.RegexContactPage, ContactPage) - staticPages.GET(hmnurl.RegexMonthlyUpdatePolicy, MonthlyUpdatePolicy) - staticPages.GET(hmnurl.RegexProjectSubmissionGuidelines, ProjectSubmissionGuidelines) - staticPages.GET(hmnurl.RegexWhenIsIt, WhenIsIt) - staticPages.GET(hmnurl.RegexJamIndex, JamIndex) - // TODO(asaf): Have separate middleware for HMN-only routes and any-project routes // NOTE(asaf): HMN-only routes: - mainRoutes.GET(hmnurl.RegexOldHome, Index) + hmnOnly.GET(hmnurl.RegexManifesto, Manifesto) + hmnOnly.GET(hmnurl.RegexAbout, About) + hmnOnly.GET(hmnurl.RegexCodeOfConduct, CodeOfConduct) + hmnOnly.GET(hmnurl.RegexCommunicationGuidelines, CommunicationGuidelines) + hmnOnly.GET(hmnurl.RegexContactPage, ContactPage) + hmnOnly.GET(hmnurl.RegexMonthlyUpdatePolicy, MonthlyUpdatePolicy) + hmnOnly.GET(hmnurl.RegexProjectSubmissionGuidelines, ProjectSubmissionGuidelines) + hmnOnly.GET(hmnurl.RegexWhenIsIt, WhenIsIt) + hmnOnly.GET(hmnurl.RegexJamIndex, JamIndex) - mainRoutes.POST(hmnurl.RegexLoginAction, securityTimerMiddleware(time.Millisecond*100, Login)) // TODO(asaf): Adjust this after launch - mainRoutes.GET(hmnurl.RegexLogoutAction, Logout) - mainRoutes.GET(hmnurl.RegexLoginPage, LoginPage) + hmnOnly.GET(hmnurl.RegexOldHome, Index) - mainRoutes.GET(hmnurl.RegexRegister, RegisterNewUser) - mainRoutes.POST(hmnurl.RegexRegister, securityTimerMiddleware(email.ExpectedEmailSendDuration, RegisterNewUserSubmit)) - mainRoutes.GET(hmnurl.RegexRegistrationSuccess, RegisterNewUserSuccess) - mainRoutes.GET(hmnurl.RegexOldEmailConfirmation, EmailConfirmation) // TODO(asaf): Delete this a bit after launch - mainRoutes.GET(hmnurl.RegexEmailConfirmation, EmailConfirmation) - mainRoutes.POST(hmnurl.RegexEmailConfirmation, EmailConfirmationSubmit) + hmnOnly.POST(hmnurl.RegexLoginAction, securityTimerMiddleware(time.Millisecond*100, Login)) // TODO(asaf): Adjust this after launch + hmnOnly.GET(hmnurl.RegexLogoutAction, Logout) + hmnOnly.GET(hmnurl.RegexLoginPage, LoginPage) - mainRoutes.GET(hmnurl.RegexRequestPasswordReset, RequestPasswordReset) - mainRoutes.POST(hmnurl.RegexRequestPasswordReset, securityTimerMiddleware(email.ExpectedEmailSendDuration, RequestPasswordResetSubmit)) - mainRoutes.GET(hmnurl.RegexPasswordResetSent, PasswordResetSent) - mainRoutes.GET(hmnurl.RegexOldDoPasswordReset, DoPasswordReset) - mainRoutes.GET(hmnurl.RegexDoPasswordReset, DoPasswordReset) - mainRoutes.POST(hmnurl.RegexDoPasswordReset, DoPasswordResetSubmit) + hmnOnly.GET(hmnurl.RegexRegister, RegisterNewUser) + hmnOnly.POST(hmnurl.RegexRegister, securityTimerMiddleware(email.ExpectedEmailSendDuration, RegisterNewUserSubmit)) + hmnOnly.GET(hmnurl.RegexRegistrationSuccess, RegisterNewUserSuccess) + hmnOnly.GET(hmnurl.RegexOldEmailConfirmation, EmailConfirmation) // TODO(asaf): Delete this a bit after launch + hmnOnly.GET(hmnurl.RegexEmailConfirmation, EmailConfirmation) + hmnOnly.POST(hmnurl.RegexEmailConfirmation, EmailConfirmationSubmit) - mainRoutes.GET(hmnurl.RegexAdminAtomFeed, AdminAtomFeed) - mainRoutes.GET(hmnurl.RegexAdminApprovalQueue, adminMiddleware(AdminApprovalQueue)) - mainRoutes.POST(hmnurl.RegexAdminApprovalQueue, adminMiddleware(csrfMiddleware(AdminApprovalQueueSubmit))) + hmnOnly.GET(hmnurl.RegexRequestPasswordReset, RequestPasswordReset) + hmnOnly.POST(hmnurl.RegexRequestPasswordReset, securityTimerMiddleware(email.ExpectedEmailSendDuration, RequestPasswordResetSubmit)) + hmnOnly.GET(hmnurl.RegexPasswordResetSent, PasswordResetSent) + hmnOnly.GET(hmnurl.RegexOldDoPasswordReset, DoPasswordReset) + hmnOnly.GET(hmnurl.RegexDoPasswordReset, DoPasswordReset) + hmnOnly.POST(hmnurl.RegexDoPasswordReset, DoPasswordResetSubmit) - mainRoutes.GET(hmnurl.RegexFeed, Feed) - mainRoutes.GET(hmnurl.RegexAtomFeed, AtomFeed) - mainRoutes.GET(hmnurl.RegexShowcase, Showcase) - mainRoutes.GET(hmnurl.RegexSnippet, Snippet) - mainRoutes.GET(hmnurl.RegexProjectIndex, ProjectIndex) - mainRoutes.GET(hmnurl.RegexProjectNotApproved, ProjectHomepage) + hmnOnly.GET(hmnurl.RegexAdminAtomFeed, AdminAtomFeed) + hmnOnly.GET(hmnurl.RegexAdminApprovalQueue, adminMiddleware(AdminApprovalQueue)) + hmnOnly.POST(hmnurl.RegexAdminApprovalQueue, adminMiddleware(csrfMiddleware(AdminApprovalQueueSubmit))) - mainRoutes.GET(hmnurl.RegexDiscordOAuthCallback, authMiddleware(DiscordOAuthCallback)) - mainRoutes.POST(hmnurl.RegexDiscordUnlink, authMiddleware(csrfMiddleware(DiscordUnlink))) - mainRoutes.POST(hmnurl.RegexDiscordShowcaseBacklog, authMiddleware(csrfMiddleware(DiscordShowcaseBacklog))) + hmnOnly.GET(hmnurl.RegexFeed, Feed) + hmnOnly.GET(hmnurl.RegexAtomFeed, AtomFeed) + hmnOnly.GET(hmnurl.RegexShowcase, Showcase) + hmnOnly.GET(hmnurl.RegexSnippet, Snippet) + hmnOnly.GET(hmnurl.RegexProjectIndex, ProjectIndex) + hmnOnly.GET(hmnurl.RegexProjectNotApproved, ProjectHomepage) - mainRoutes.GET(hmnurl.RegexUserProfile, UserProfile) - mainRoutes.GET(hmnurl.RegexUserSettings, authMiddleware(UserSettings)) - mainRoutes.POST(hmnurl.RegexUserSettings, authMiddleware(csrfMiddleware(UserSettingsSave))) + hmnOnly.GET(hmnurl.RegexDiscordOAuthCallback, authMiddleware(DiscordOAuthCallback)) + hmnOnly.POST(hmnurl.RegexDiscordUnlink, authMiddleware(csrfMiddleware(DiscordUnlink))) + hmnOnly.POST(hmnurl.RegexDiscordShowcaseBacklog, authMiddleware(csrfMiddleware(DiscordShowcaseBacklog))) + + hmnOnly.GET(hmnurl.RegexUserProfile, UserProfile) + hmnOnly.GET(hmnurl.RegexUserSettings, authMiddleware(UserSettings)) + hmnOnly.POST(hmnurl.RegexUserSettings, authMiddleware(csrfMiddleware(UserSettingsSave))) + + hmnOnly.GET(hmnurl.RegexPodcast, PodcastIndex) + hmnOnly.GET(hmnurl.RegexPodcastEdit, PodcastEdit) + hmnOnly.POST(hmnurl.RegexPodcastEdit, PodcastEditSubmit) + hmnOnly.GET(hmnurl.RegexPodcastEpisodeNew, PodcastEpisodeNew) + hmnOnly.POST(hmnurl.RegexPodcastEpisodeNew, PodcastEpisodeSubmit) + hmnOnly.GET(hmnurl.RegexPodcastEpisodeEdit, PodcastEpisodeEdit) + hmnOnly.POST(hmnurl.RegexPodcastEpisodeEdit, PodcastEpisodeSubmit) + hmnOnly.GET(hmnurl.RegexPodcastEpisode, PodcastEpisode) + hmnOnly.GET(hmnurl.RegexPodcastRSS, PodcastRSS) + + hmnOnly.GET(hmnurl.RegexLibraryAny, LibraryNotPortedYet) // NOTE(asaf): Any-project routes: - mainRoutes.GET(hmnurl.RegexForumNewThread, authMiddleware(ForumNewThread)) - mainRoutes.POST(hmnurl.RegexForumNewThreadSubmit, authMiddleware(csrfMiddleware(ForumNewThreadSubmit))) - mainRoutes.GET(hmnurl.RegexForumThread, ForumThread) - mainRoutes.GET(hmnurl.RegexForum, Forum) - mainRoutes.POST(hmnurl.RegexForumMarkRead, authMiddleware(csrfMiddleware(ForumMarkRead))) - mainRoutes.GET(hmnurl.RegexForumPost, ForumPostRedirect) - mainRoutes.GET(hmnurl.RegexForumPostReply, authMiddleware(ForumPostReply)) - mainRoutes.POST(hmnurl.RegexForumPostReply, authMiddleware(csrfMiddleware(ForumPostReplySubmit))) - mainRoutes.GET(hmnurl.RegexForumPostEdit, authMiddleware(ForumPostEdit)) - mainRoutes.POST(hmnurl.RegexForumPostEdit, authMiddleware(csrfMiddleware(ForumPostEditSubmit))) - mainRoutes.GET(hmnurl.RegexForumPostDelete, authMiddleware(ForumPostDelete)) - mainRoutes.POST(hmnurl.RegexForumPostDelete, authMiddleware(csrfMiddleware(ForumPostDeleteSubmit))) - mainRoutes.GET(hmnurl.RegexWikiArticle, WikiArticleRedirect) + anyProject.GET(hmnurl.RegexForumNewThread, authMiddleware(ForumNewThread)) + anyProject.POST(hmnurl.RegexForumNewThreadSubmit, authMiddleware(csrfMiddleware(ForumNewThreadSubmit))) + anyProject.GET(hmnurl.RegexForumThread, ForumThread) + anyProject.GET(hmnurl.RegexForum, Forum) + anyProject.POST(hmnurl.RegexForumMarkRead, authMiddleware(csrfMiddleware(ForumMarkRead))) + anyProject.GET(hmnurl.RegexForumPost, ForumPostRedirect) + anyProject.GET(hmnurl.RegexForumPostReply, authMiddleware(ForumPostReply)) + anyProject.POST(hmnurl.RegexForumPostReply, authMiddleware(csrfMiddleware(ForumPostReplySubmit))) + anyProject.GET(hmnurl.RegexForumPostEdit, authMiddleware(ForumPostEdit)) + anyProject.POST(hmnurl.RegexForumPostEdit, authMiddleware(csrfMiddleware(ForumPostEditSubmit))) + anyProject.GET(hmnurl.RegexForumPostDelete, authMiddleware(ForumPostDelete)) + anyProject.POST(hmnurl.RegexForumPostDelete, authMiddleware(csrfMiddleware(ForumPostDeleteSubmit))) + anyProject.GET(hmnurl.RegexWikiArticle, WikiArticleRedirect) - mainRoutes.GET(hmnurl.RegexBlog, BlogIndex) - mainRoutes.GET(hmnurl.RegexBlogNewThread, authMiddleware(BlogNewThread)) - mainRoutes.POST(hmnurl.RegexBlogNewThread, authMiddleware(csrfMiddleware(BlogNewThreadSubmit))) - mainRoutes.GET(hmnurl.RegexBlogThread, BlogThread) - mainRoutes.GET(hmnurl.RegexBlogPost, BlogPostRedirectToThread) - mainRoutes.GET(hmnurl.RegexBlogPostReply, authMiddleware(BlogPostReply)) - mainRoutes.POST(hmnurl.RegexBlogPostReply, authMiddleware(csrfMiddleware(BlogPostReplySubmit))) - mainRoutes.GET(hmnurl.RegexBlogPostEdit, authMiddleware(BlogPostEdit)) - mainRoutes.POST(hmnurl.RegexBlogPostEdit, authMiddleware(csrfMiddleware(BlogPostEditSubmit))) - mainRoutes.GET(hmnurl.RegexBlogPostDelete, authMiddleware(BlogPostDelete)) - mainRoutes.POST(hmnurl.RegexBlogPostDelete, authMiddleware(csrfMiddleware(BlogPostDeleteSubmit))) - mainRoutes.GET(hmnurl.RegexBlogsRedirect, func(c *RequestContext) ResponseData { + anyProject.GET(hmnurl.RegexBlog, BlogIndex) + anyProject.GET(hmnurl.RegexBlogNewThread, authMiddleware(BlogNewThread)) + anyProject.POST(hmnurl.RegexBlogNewThread, authMiddleware(csrfMiddleware(BlogNewThreadSubmit))) + anyProject.GET(hmnurl.RegexBlogThread, BlogThread) + anyProject.GET(hmnurl.RegexBlogPost, BlogPostRedirectToThread) + anyProject.GET(hmnurl.RegexBlogPostReply, authMiddleware(BlogPostReply)) + anyProject.POST(hmnurl.RegexBlogPostReply, authMiddleware(csrfMiddleware(BlogPostReplySubmit))) + anyProject.GET(hmnurl.RegexBlogPostEdit, authMiddleware(BlogPostEdit)) + anyProject.POST(hmnurl.RegexBlogPostEdit, authMiddleware(csrfMiddleware(BlogPostEditSubmit))) + anyProject.GET(hmnurl.RegexBlogPostDelete, authMiddleware(BlogPostDelete)) + anyProject.POST(hmnurl.RegexBlogPostDelete, authMiddleware(csrfMiddleware(BlogPostDeleteSubmit))) + anyProject.GET(hmnurl.RegexBlogsRedirect, func(c *RequestContext) ResponseData { return c.Redirect(hmnurl.ProjectUrl( fmt.Sprintf("blog%s", c.PathParams["remainder"]), nil, c.CurrentProject.Slug, ), http.StatusMovedPermanently) }) - mainRoutes.POST(hmnurl.RegexAssetUpload, AssetUpload) + anyProject.POST(hmnurl.RegexAssetUpload, AssetUpload) - mainRoutes.GET(hmnurl.RegexPodcast, PodcastIndex) - mainRoutes.GET(hmnurl.RegexPodcastEdit, PodcastEdit) - mainRoutes.POST(hmnurl.RegexPodcastEdit, PodcastEditSubmit) - mainRoutes.GET(hmnurl.RegexPodcastEpisodeNew, PodcastEpisodeNew) - mainRoutes.POST(hmnurl.RegexPodcastEpisodeNew, PodcastEpisodeSubmit) - mainRoutes.GET(hmnurl.RegexPodcastEpisodeEdit, PodcastEpisodeEdit) - mainRoutes.POST(hmnurl.RegexPodcastEpisodeEdit, PodcastEpisodeSubmit) - mainRoutes.GET(hmnurl.RegexPodcastEpisode, PodcastEpisode) - mainRoutes.GET(hmnurl.RegexPodcastRSS, PodcastRSS) + anyProject.GET(hmnurl.RegexEpisodeList, EpisodeList) + anyProject.GET(hmnurl.RegexEpisode, Episode) + anyProject.GET(hmnurl.RegexCineraIndex, CineraIndex) - mainRoutes.GET(hmnurl.RegexEpisodeList, EpisodeList) - mainRoutes.GET(hmnurl.RegexEpisode, Episode) - mainRoutes.GET(hmnurl.RegexCineraIndex, CineraIndex) - - mainRoutes.GET(hmnurl.RegexProjectCSS, ProjectCSS) - mainRoutes.GET(hmnurl.RegexEditorPreviewsJS, func(c *RequestContext) ResponseData { + anyProject.GET(hmnurl.RegexProjectCSS, ProjectCSS) + anyProject.GET(hmnurl.RegexEditorPreviewsJS, func(c *RequestContext) ResponseData { var res ResponseData res.MustWriteTemplate("editorpreviews.js", nil, c.Perf) res.Header().Add("Content-Type", "application/javascript") return res }) - mainRoutes.GET(hmnurl.RegexLibraryAny, LibraryNotPortedYet) - // Other - mainRoutes.AnyMethod(hmnurl.RegexCatchAll, FourOhFour) + anyProject.AnyMethod(hmnurl.RegexCatchAll, FourOhFour) return router } @@ -342,9 +342,9 @@ func getBaseData(c *RequestContext, title string, breadcrumbs []templates.Breadc HMNHomepageUrl: hmnurl.BuildHomepage(), ProjectIndexUrl: hmnurl.BuildProjectIndex(1), - PodcastUrl: hmnurl.BuildPodcast(c.CurrentProject.Slug), + PodcastUrl: hmnurl.BuildPodcast(), ForumsUrl: hmnurl.BuildForum(c.CurrentProject.Slug, nil, 1), - LibraryUrl: hmnurl.BuildLibrary(c.CurrentProject.Slug), + LibraryUrl: hmnurl.BuildLibrary(), }, Footer: templates.Footer{ HomepageUrl: hmnurl.BuildHomepage(),