2021-03-14 20:49:58 +00:00
|
|
|
package templates
|
|
|
|
|
2021-05-04 01:59:45 +00:00
|
|
|
import (
|
|
|
|
"html/template"
|
|
|
|
"time"
|
|
|
|
)
|
2021-04-22 23:02:50 +00:00
|
|
|
|
2021-03-14 20:49:58 +00:00
|
|
|
type BaseData struct {
|
2022-06-02 01:49:19 +00:00
|
|
|
Title string
|
|
|
|
CanonicalLink string
|
|
|
|
OpenGraphItems []OpenGraphItem
|
|
|
|
BackgroundImage BackgroundImage
|
|
|
|
BodyClasses []string
|
|
|
|
Breadcrumbs []Breadcrumb
|
|
|
|
Notices []Notice
|
|
|
|
ReportIssueEmail string
|
2021-03-26 03:33:00 +00:00
|
|
|
|
2024-05-20 22:00:03 +00:00
|
|
|
CurrentUrl string
|
|
|
|
CurrentProjectUrl string
|
|
|
|
LoginPageUrl string
|
|
|
|
DiscordInviteUrl string
|
|
|
|
NewsletterSignupUrl string
|
2021-05-11 22:53:23 +00:00
|
|
|
|
2024-05-30 04:19:31 +00:00
|
|
|
EsBuildSSEUrl string
|
|
|
|
|
2021-03-26 03:33:00 +00:00
|
|
|
Project Project
|
|
|
|
User *User
|
2021-06-12 03:51:07 +00:00
|
|
|
Session *Session
|
2021-05-11 22:53:23 +00:00
|
|
|
|
2021-09-01 06:15:13 +00:00
|
|
|
IsProjectPage bool
|
|
|
|
Header Header
|
|
|
|
Footer Footer
|
2021-05-11 22:53:23 +00:00
|
|
|
}
|
|
|
|
|
2021-08-17 05:18:04 +00:00
|
|
|
func (bd *BaseData) AddImmediateNotice(class, content string) {
|
|
|
|
bd.Notices = append(bd.Notices, Notice{
|
|
|
|
Class: class,
|
|
|
|
Content: template.HTML(content),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-05-11 22:53:23 +00:00
|
|
|
type Header struct {
|
Add Discord login (#106)
This leverages our existing Discord OAuth implementation. Any users with a linked Discord account will be able to log in immediately. When logging in, we request the `email` scope in addition to `identity`, so existing users will be prompted one time to accept the new permissions. On subsequent logins, Discord will skip the prompt.
When linking your Discord account to an existing HMN account, we continue to only request the `identity` scope, so we do not receive the user's Discord email.
Both login and linking go through the same Discord OAuth callback. All flows through the callback try to achieve the same end goal: a logged-in HMN user with a linked Discord account.
Linking works the same as it ever has. Login, however, is different because we do not have a session ID to use as the OAuth state. To account for this, I have added a `pending_login` table that stores a secure unique ID and the eventual destination URL. These pending logins expire after 10 minutes. When we receive the OAuth callback, we look up the pending login by the OAuth `state` and immediately delete it. The destination URL will be used to redirect the user to the right place.
If we have a `discord_user` entry for the OAuth'd Discord user, we immediately log the user into the associated HMN account. This is the typical login case. If we do not have a `discord_user`, but there is exactly one HMN user with the same email address as the Discord user, we will link the two accounts and log into the HMN account.
(It is possible for multiple HMN accounts to have the same email, because we don't have a uniqueness constraint there. We fail the login in this case rather than link to the wrong account.)
Finally, if no associated HMN user exists, a new one will be created. It will use the Discord user's username, email, and avatar. This user will have no password, but they can set or reset a password through the usual flows.
Co-authored-by: Ben Visness <bvisness@gmail.com>
Reviewed-on: https://git.handmade.network/hmn/hmn/pulls/106
2023-05-06 19:38:50 +00:00
|
|
|
AdminUrl string
|
|
|
|
UserProfileUrl string
|
|
|
|
UserSettingsUrl string
|
|
|
|
LoginActionUrl string
|
|
|
|
LogoutActionUrl string
|
|
|
|
ForgotPasswordUrl string
|
|
|
|
RegisterUrl string
|
|
|
|
LoginWithDiscordUrl string
|
2021-10-21 02:21:24 +00:00
|
|
|
|
|
|
|
HMNHomepageUrl string
|
|
|
|
ProjectIndexUrl string
|
|
|
|
PodcastUrl string
|
2022-06-12 12:45:56 +00:00
|
|
|
FishbowlUrl string
|
2021-10-21 02:21:24 +00:00
|
|
|
ForumsUrl string
|
2022-07-26 15:07:57 +00:00
|
|
|
ConferencesUrl string
|
2023-04-22 16:26:07 +00:00
|
|
|
JamsUrl string
|
2022-09-10 16:29:57 +00:00
|
|
|
EducationUrl string
|
2024-01-28 17:12:59 +00:00
|
|
|
CalendarUrl string
|
2024-05-21 02:37:28 +00:00
|
|
|
ManifestoUrl string
|
|
|
|
AboutUrl string
|
2021-10-28 01:35:53 +00:00
|
|
|
|
|
|
|
Project *ProjectHeader
|
|
|
|
}
|
|
|
|
|
|
|
|
type ProjectHeader struct {
|
|
|
|
HasForums bool
|
|
|
|
HasBlog bool
|
|
|
|
HasEpisodeGuide bool
|
2021-12-04 14:55:45 +00:00
|
|
|
CanEdit bool
|
2021-10-28 01:35:53 +00:00
|
|
|
ForumsUrl string
|
|
|
|
BlogUrl string
|
|
|
|
EpisodeGuideUrl string
|
2021-12-04 14:55:45 +00:00
|
|
|
EditUrl string
|
2021-05-11 22:53:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type Footer struct {
|
|
|
|
HomepageUrl string
|
|
|
|
AboutUrl string
|
|
|
|
ManifestoUrl string
|
|
|
|
CodeOfConductUrl string
|
|
|
|
CommunicationGuidelinesUrl string
|
|
|
|
ProjectIndexUrl string
|
|
|
|
ContactUrl string
|
2022-02-10 20:27:28 +00:00
|
|
|
SearchActionUrl string
|
2021-03-14 20:49:58 +00:00
|
|
|
}
|
|
|
|
|
2021-04-22 23:02:50 +00:00
|
|
|
type Thread struct {
|
|
|
|
Title string
|
|
|
|
|
2021-04-29 04:52:27 +00:00
|
|
|
Locked bool
|
|
|
|
Sticky bool
|
2021-04-22 23:02:50 +00:00
|
|
|
}
|
|
|
|
|
2021-04-11 21:46:06 +00:00
|
|
|
type Post struct {
|
2021-05-06 05:57:14 +00:00
|
|
|
ID int
|
|
|
|
|
|
|
|
Url string
|
|
|
|
DeleteUrl string
|
|
|
|
EditUrl string
|
|
|
|
ReplyUrl string
|
2021-05-04 01:59:45 +00:00
|
|
|
|
2021-04-11 21:46:06 +00:00
|
|
|
Preview string
|
|
|
|
ReadOnly bool
|
|
|
|
|
2021-07-22 02:26:28 +00:00
|
|
|
Author User
|
2021-05-04 01:59:45 +00:00
|
|
|
Content template.HTML
|
|
|
|
PostDate time.Time
|
|
|
|
|
2021-08-28 17:07:45 +00:00
|
|
|
AuthorNumPosts int
|
|
|
|
AuthorNumProjects int
|
|
|
|
|
2021-05-04 01:59:45 +00:00
|
|
|
Editor *User
|
|
|
|
EditDate time.Time
|
|
|
|
EditReason string
|
2021-04-23 04:07:44 +00:00
|
|
|
|
2021-04-11 21:46:06 +00:00
|
|
|
IP string
|
2021-07-20 03:07:15 +00:00
|
|
|
|
|
|
|
ReplyPost *Post
|
2021-04-11 21:46:06 +00:00
|
|
|
}
|
|
|
|
|
2021-03-18 01:25:06 +00:00
|
|
|
type Project struct {
|
2022-08-05 04:03:45 +00:00
|
|
|
ID int
|
2021-06-06 23:48:43 +00:00
|
|
|
Name string
|
|
|
|
Subdomain string
|
|
|
|
Color1 string
|
|
|
|
Color2 string
|
|
|
|
Url string
|
|
|
|
Blurb string
|
|
|
|
ParsedDescription template.HTML
|
|
|
|
Owners []User
|
|
|
|
|
2024-05-25 02:09:28 +00:00
|
|
|
Logo string
|
|
|
|
HeaderImage string
|
2021-05-31 23:23:04 +00:00
|
|
|
|
2021-06-06 23:48:43 +00:00
|
|
|
LifecycleBadgeClass string
|
|
|
|
LifecycleString string
|
2021-03-18 01:25:06 +00:00
|
|
|
|
|
|
|
IsHMN bool
|
|
|
|
|
2021-11-10 04:11:39 +00:00
|
|
|
HasBlog bool
|
|
|
|
HasForum bool
|
2021-05-31 23:23:04 +00:00
|
|
|
|
|
|
|
UUID string
|
|
|
|
DateApproved time.Time
|
2021-03-18 01:25:06 +00:00
|
|
|
}
|
|
|
|
|
2021-11-25 03:59:51 +00:00
|
|
|
type ProjectSettings struct {
|
2022-06-19 22:26:33 +00:00
|
|
|
Name string
|
|
|
|
Slug string
|
|
|
|
Hidden bool
|
|
|
|
Featured bool
|
|
|
|
Personal bool
|
|
|
|
Lifecycle string
|
|
|
|
Tag string
|
|
|
|
JamParticipation []ProjectJamParticipation
|
2021-11-25 03:59:51 +00:00
|
|
|
|
|
|
|
Blurb string
|
|
|
|
Description string
|
2024-05-25 02:09:28 +00:00
|
|
|
LinksJSON string
|
2021-11-25 03:59:51 +00:00
|
|
|
Owners []User
|
|
|
|
|
2024-05-25 02:09:28 +00:00
|
|
|
LightLogo *Asset
|
|
|
|
DarkLogo *Asset
|
|
|
|
HeaderImage *Asset
|
|
|
|
}
|
|
|
|
|
|
|
|
type Asset struct {
|
|
|
|
Url string
|
|
|
|
|
|
|
|
ID string
|
|
|
|
Filename string
|
|
|
|
Size int
|
|
|
|
MimeType string
|
|
|
|
Width, Height int
|
2021-11-25 03:59:51 +00:00
|
|
|
}
|
|
|
|
|
2024-06-22 01:13:20 +00:00
|
|
|
type Follow struct {
|
|
|
|
User *User
|
|
|
|
Project *Project
|
|
|
|
}
|
|
|
|
|
2022-06-19 22:26:33 +00:00
|
|
|
type ProjectJamParticipation struct {
|
|
|
|
JamName string
|
|
|
|
JamSlug string
|
|
|
|
Participating bool
|
|
|
|
}
|
|
|
|
|
2022-08-05 04:03:45 +00:00
|
|
|
type SnippetEdit struct {
|
|
|
|
AvailableProjectsJSON string
|
|
|
|
SubmitUrl string
|
|
|
|
AssetMaxSize int
|
|
|
|
}
|
|
|
|
|
2021-03-26 03:33:00 +00:00
|
|
|
type User struct {
|
2021-07-22 02:16:10 +00:00
|
|
|
ID int
|
|
|
|
Username string
|
|
|
|
Email string
|
|
|
|
IsStaff bool
|
2021-12-15 01:17:42 +00:00
|
|
|
Status int
|
2021-04-17 00:01:13 +00:00
|
|
|
|
2021-04-22 23:02:50 +00:00
|
|
|
Name string
|
|
|
|
Blurb string
|
2021-05-04 01:59:45 +00:00
|
|
|
Bio string
|
2021-04-22 23:02:50 +00:00
|
|
|
Signature string
|
2021-06-22 09:50:40 +00:00
|
|
|
DateJoined time.Time
|
2024-06-25 19:49:24 +00:00
|
|
|
Avatar *Asset
|
2021-04-22 23:02:50 +00:00
|
|
|
AvatarUrl string
|
|
|
|
ProfileUrl string
|
2021-04-17 00:01:13 +00:00
|
|
|
|
2021-08-27 17:58:52 +00:00
|
|
|
ShowEmail bool
|
2021-08-08 20:05:52 +00:00
|
|
|
Timezone string
|
2021-04-17 00:01:13 +00:00
|
|
|
|
|
|
|
DiscordSaveShowcase bool
|
|
|
|
DiscordDeleteSnippetOnMessageDelete bool
|
2022-09-10 16:29:57 +00:00
|
|
|
|
|
|
|
IsEduTester bool
|
|
|
|
IsEduAuthor bool
|
2021-03-26 03:33:00 +00:00
|
|
|
}
|
|
|
|
|
2021-06-22 09:50:40 +00:00
|
|
|
type Link struct {
|
2024-05-25 02:09:28 +00:00
|
|
|
Name string `json:"name"`
|
|
|
|
Url string `json:"url"`
|
|
|
|
ServiceName string `json:"serviceName"`
|
|
|
|
Username string `json:"text"`
|
|
|
|
Icon string `json:"icon"`
|
2024-06-30 23:55:21 +00:00
|
|
|
Primary bool `json:"primary"`
|
2021-07-08 07:40:30 +00:00
|
|
|
}
|
|
|
|
|
2024-07-03 02:23:23 +00:00
|
|
|
type Icon struct {
|
|
|
|
Name string `json:"name"`
|
|
|
|
Svg template.HTML `json:"svg"`
|
|
|
|
}
|
|
|
|
|
2021-07-23 03:09:46 +00:00
|
|
|
type Podcast struct {
|
|
|
|
Title string
|
|
|
|
Description string
|
|
|
|
Language string
|
|
|
|
ImageUrl string
|
|
|
|
Url string
|
|
|
|
|
|
|
|
RSSUrl string
|
|
|
|
AppleUrl string
|
|
|
|
GoogleUrl string
|
|
|
|
SpotifyUrl string
|
|
|
|
}
|
|
|
|
|
|
|
|
type PodcastEpisode struct {
|
|
|
|
GUID string
|
|
|
|
Title string
|
|
|
|
Description string
|
|
|
|
DescriptionHtml template.HTML
|
|
|
|
EpisodeNumber int
|
|
|
|
Url string
|
|
|
|
ImageUrl string
|
|
|
|
FileUrl string
|
|
|
|
FileSize int64
|
|
|
|
PublicationDate time.Time
|
|
|
|
Duration int
|
|
|
|
}
|
|
|
|
|
2021-08-08 20:05:52 +00:00
|
|
|
// NOTE(asaf): See /src/rawdata/scss/_notices.scss for a list of classes.
|
2021-07-08 07:40:30 +00:00
|
|
|
type Notice struct {
|
|
|
|
Content template.HTML
|
|
|
|
Class string
|
2021-06-22 09:50:40 +00:00
|
|
|
}
|
|
|
|
|
2021-06-12 03:51:07 +00:00
|
|
|
type Session struct {
|
|
|
|
CSRFToken string
|
|
|
|
}
|
|
|
|
|
2021-03-14 20:49:58 +00:00
|
|
|
type OpenGraphItem struct {
|
|
|
|
Property string
|
|
|
|
Name string
|
|
|
|
Value string
|
|
|
|
}
|
|
|
|
|
|
|
|
type BackgroundImage struct {
|
|
|
|
Url string
|
|
|
|
Size string // A valid CSS background-size value
|
|
|
|
}
|
2021-04-22 23:02:50 +00:00
|
|
|
|
2021-05-30 18:35:01 +00:00
|
|
|
type PostType int
|
|
|
|
|
|
|
|
const (
|
|
|
|
PostTypeUnknown PostType = iota
|
|
|
|
PostTypeBlogPost
|
|
|
|
PostTypeBlogComment
|
|
|
|
PostTypeForumThread
|
|
|
|
PostTypeForumReply
|
|
|
|
)
|
|
|
|
|
2021-04-22 23:02:50 +00:00
|
|
|
// Data from post_list_item.html
|
|
|
|
type PostListItem struct {
|
|
|
|
Title string
|
|
|
|
Url string
|
2021-05-30 18:35:01 +00:00
|
|
|
UUID string
|
2021-04-22 23:02:50 +00:00
|
|
|
Breadcrumbs []Breadcrumb
|
2021-05-03 14:51:07 +00:00
|
|
|
|
2021-05-30 18:35:01 +00:00
|
|
|
PostType PostType
|
|
|
|
PostTypePrefix string
|
|
|
|
|
2021-05-03 14:51:07 +00:00
|
|
|
User User
|
|
|
|
Date time.Time
|
|
|
|
|
2021-05-30 18:35:01 +00:00
|
|
|
Unread bool
|
|
|
|
Classes string
|
|
|
|
Preview string
|
|
|
|
LastEditDate time.Time
|
2021-05-03 14:51:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Data from thread_list_item.html
|
|
|
|
type ThreadListItem struct {
|
2021-06-22 10:27:27 +00:00
|
|
|
Title string
|
|
|
|
Url string
|
2021-05-03 14:51:07 +00:00
|
|
|
|
|
|
|
FirstUser User
|
|
|
|
FirstDate time.Time
|
|
|
|
LastUser User
|
|
|
|
LastDate time.Time
|
|
|
|
|
|
|
|
Unread bool
|
|
|
|
Classes string
|
|
|
|
Content string
|
2021-04-22 23:02:50 +00:00
|
|
|
}
|
|
|
|
|
2021-06-22 09:50:40 +00:00
|
|
|
type TimelineItem struct {
|
2022-08-05 04:03:45 +00:00
|
|
|
ID string
|
2021-10-23 22:28:06 +00:00
|
|
|
Date time.Time
|
|
|
|
Title string
|
|
|
|
TypeTitle string
|
|
|
|
FilterTitle string
|
|
|
|
Breadcrumbs []Breadcrumb
|
|
|
|
Url string
|
|
|
|
DiscordMessageUrl string
|
2021-06-22 09:50:40 +00:00
|
|
|
|
|
|
|
OwnerAvatarUrl string
|
|
|
|
OwnerName string
|
|
|
|
OwnerUrl string
|
|
|
|
|
2022-08-05 04:03:45 +00:00
|
|
|
Projects []Project
|
|
|
|
Description template.HTML
|
|
|
|
RawDescription string
|
2021-06-22 09:50:40 +00:00
|
|
|
|
2024-06-23 18:05:36 +00:00
|
|
|
Media []TimelineItemMedia
|
2021-10-23 22:28:06 +00:00
|
|
|
|
2024-06-23 18:05:36 +00:00
|
|
|
ForumLayout bool
|
2021-10-25 14:07:14 +00:00
|
|
|
AllowTitleWrap bool
|
|
|
|
TruncateDescription bool
|
|
|
|
CanShowcase bool // whether this snippet can be shown in a showcase gallery
|
2022-08-05 04:03:45 +00:00
|
|
|
Editable bool
|
2021-10-23 22:28:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type TimelineItemMediaType int
|
|
|
|
|
|
|
|
const (
|
2022-04-07 05:19:48 +00:00
|
|
|
TimelineItemMediaTypeUnknown TimelineItemMediaType = iota
|
|
|
|
TimelineItemMediaTypeImage
|
2021-10-23 22:28:06 +00:00
|
|
|
TimelineItemMediaTypeVideo
|
|
|
|
TimelineItemMediaTypeAudio
|
|
|
|
TimelineItemMediaTypeEmbed
|
|
|
|
)
|
|
|
|
|
|
|
|
type TimelineItemMedia struct {
|
|
|
|
Type TimelineItemMediaType
|
|
|
|
AssetUrl string
|
|
|
|
EmbedHTML template.HTML
|
|
|
|
ThumbnailUrl string
|
|
|
|
MimeType string
|
|
|
|
Width, Height int
|
2022-04-07 05:19:48 +00:00
|
|
|
Filename string
|
|
|
|
FileSize int
|
2021-10-23 22:28:06 +00:00
|
|
|
ExtraOpenGraphItems []OpenGraphItem
|
2021-06-22 09:50:40 +00:00
|
|
|
}
|
|
|
|
|
2021-06-06 23:48:43 +00:00
|
|
|
type ProjectCardData struct {
|
|
|
|
Project *Project
|
|
|
|
Classes string
|
|
|
|
}
|
|
|
|
|
2021-11-25 03:59:51 +00:00
|
|
|
type ImageSelectorData struct {
|
|
|
|
Name string
|
2024-05-25 02:09:28 +00:00
|
|
|
Asset *Asset
|
2021-11-25 03:59:51 +00:00
|
|
|
Required bool
|
|
|
|
}
|
|
|
|
|
2021-04-22 23:02:50 +00:00
|
|
|
type Breadcrumb struct {
|
|
|
|
Name, Url string
|
|
|
|
}
|
2021-04-25 19:33:22 +00:00
|
|
|
|
|
|
|
type Pagination struct {
|
|
|
|
Current int
|
|
|
|
Total int
|
|
|
|
|
|
|
|
FirstUrl string
|
|
|
|
LastUrl string
|
|
|
|
PreviousUrl string
|
|
|
|
NextUrl string
|
|
|
|
}
|
2021-08-08 20:05:52 +00:00
|
|
|
|
|
|
|
type EmailBaseData struct {
|
|
|
|
To template.HTML
|
|
|
|
From template.HTML
|
|
|
|
Subject template.HTML
|
|
|
|
Separator template.HTML
|
|
|
|
}
|
2021-08-16 04:40:56 +00:00
|
|
|
|
|
|
|
type DiscordUser struct {
|
|
|
|
Username string
|
|
|
|
Discriminator string
|
|
|
|
Avatar string
|
|
|
|
}
|
2021-11-11 19:00:46 +00:00
|
|
|
|
|
|
|
type Tag struct {
|
|
|
|
Text string
|
|
|
|
Url string
|
|
|
|
}
|
2022-09-10 16:29:57 +00:00
|
|
|
|
2022-09-14 21:44:27 +00:00
|
|
|
type TextEditor struct {
|
|
|
|
ParserName string
|
|
|
|
MaxFileSize int
|
|
|
|
UploadUrl string
|
|
|
|
}
|
|
|
|
|
2022-10-27 05:20:59 +00:00
|
|
|
type EduCourse struct {
|
|
|
|
Name string
|
|
|
|
Slug string
|
|
|
|
Articles []EduArticle
|
|
|
|
}
|
|
|
|
|
2022-09-10 16:29:57 +00:00
|
|
|
type EduArticle struct {
|
|
|
|
Title string
|
|
|
|
Slug string
|
|
|
|
Description string
|
|
|
|
Published bool
|
|
|
|
Type string
|
|
|
|
|
|
|
|
Url string
|
|
|
|
EditUrl string
|
|
|
|
DeleteUrl string
|
|
|
|
|
|
|
|
Content template.HTML
|
|
|
|
}
|
2024-01-28 17:12:59 +00:00
|
|
|
|
|
|
|
type CalendarEvent struct {
|
|
|
|
Name string
|
|
|
|
Desc string
|
|
|
|
StartTime time.Time
|
|
|
|
EndTime time.Time
|
|
|
|
CalName string
|
|
|
|
}
|