Open education up to all

This commit is contained in:
Ben Visness 2022-11-05 16:18:39 -05:00
parent bd1edb2077
commit f0597f3eb8
2 changed files with 36 additions and 29 deletions

View File

@ -40,7 +40,10 @@ func EducationIndex(c *RequestContext) ResponseData {
// }
article := func(slug string) templates.EduArticle {
if article, err := fetchEduArticle(c, c.Conn, slug, models.EduArticleTypeArticle, c.CurrentUser); err == nil {
if article, err := fetchEduArticle(c, c.Conn, slug, c.CurrentUser, EduArticleQuery{
Types: []models.EduArticleType{models.EduArticleTypeArticle},
IncludeUnpublished: true,
}); err == nil {
return templates.EducationArticleToTemplate(article)
} else if errors.Is(err, db.NotFound) {
return templates.EduArticle{
@ -119,7 +122,9 @@ func EducationArticle(c *RequestContext) ResponseData {
DeleteUrl string
}
article, err := fetchEduArticle(c, c.Conn, c.PathParams["slug"], models.EduArticleTypeArticle, c.CurrentUser)
article, err := fetchEduArticle(c, c.Conn, c.PathParams["slug"], c.CurrentUser, EduArticleQuery{
Types: []models.EduArticleType{models.EduArticleTypeArticle},
})
if errors.Is(err, db.NotFound) {
return FourOhFour(c)
} else if err != nil {
@ -215,7 +220,7 @@ func EducationArticleEdit(c *RequestContext) ResponseData {
Article templates.EduArticle
}
article, err := fetchEduArticle(c, c.Conn, c.PathParams["slug"], 0, c.CurrentUser)
article, err := fetchEduArticle(c, c.Conn, c.PathParams["slug"], c.CurrentUser, EduArticleQuery{})
if errors.Is(err, db.NotFound) {
return FourOhFour(c)
} else if err != nil {
@ -239,7 +244,7 @@ func EducationArticleEditSubmit(c *RequestContext) ResponseData {
return c.ErrorResponse(http.StatusBadRequest, err)
}
_, err = fetchEduArticle(c, c.Conn, c.PathParams["slug"], 0, c.CurrentUser)
_, err = fetchEduArticle(c, c.Conn, c.PathParams["slug"], c.CurrentUser, EduArticleQuery{})
if errors.Is(err, db.NotFound) {
return FourOhFour(c)
} else if err != nil {
@ -255,7 +260,7 @@ func EducationArticleEditSubmit(c *RequestContext) ResponseData {
}
func EducationArticleDelete(c *RequestContext) ResponseData {
article, err := fetchEduArticle(c, c.Conn, c.PathParams["slug"], 0, c.CurrentUser)
article, err := fetchEduArticle(c, c.Conn, c.PathParams["slug"], c.CurrentUser, EduArticleQuery{})
if errors.Is(err, db.NotFound) {
return FourOhFour(c)
} else if err != nil {
@ -291,7 +296,7 @@ func EducationArticleDeleteSubmit(c *RequestContext) ResponseData {
}
func EducationRerender(c *RequestContext) ResponseData {
everything := utils.Must1(fetchEduArticles(c, c.Conn, 0, c.CurrentUser))
everything := utils.Must1(fetchEduArticles(c, c.Conn, c.CurrentUser, EduArticleQuery{}))
for _, thing := range everything {
newHTML := parsing.ParseMarkdown(thing.CurrentVersion.ContentRaw, parsing.EducationRealMarkdown)
utils.Must1(c.Conn.Exec(c,
@ -310,11 +315,16 @@ func EducationRerender(c *RequestContext) ResponseData {
return res
}
type EduArticleQuery struct {
Types []models.EduArticleType
IncludeUnpublished bool // If true, unpublished articles will be fetched even if they would not otherwise be visible
}
func fetchEduArticles(
ctx context.Context,
dbConn db.ConnOrTx,
t models.EduArticleType,
currentUser *models.User,
q EduArticleQuery,
) ([]models.EduArticle, error) {
type eduArticleResult struct {
Article models.EduArticle `db:"a"`
@ -330,11 +340,11 @@ func fetchEduArticles(
WHERE
TRUE
`)
if t != 0 {
qb.Add(`AND a.type = $?`, t)
if len(q.Types) > 0 {
qb.Add(`AND a.type = ANY($?)`, q.Types)
}
if currentUser == nil || !currentUser.CanSeeUnpublishedEducationContent() {
qb.Add(`AND NOT a.published`)
if (currentUser == nil || !currentUser.CanSeeUnpublishedEducationContent()) && !q.IncludeUnpublished {
qb.Add(`AND a.published`)
}
articles, err := db.Query[eduArticleResult](ctx, dbConn, qb.String(), qb.Args()...)
@ -356,8 +366,8 @@ func fetchEduArticle(
ctx context.Context,
dbConn db.ConnOrTx,
slug string,
t models.EduArticleType,
currentUser *models.User,
q EduArticleQuery,
) (*models.EduArticle, error) {
type eduArticleResult struct {
Article models.EduArticle `db:"a"`
@ -376,11 +386,11 @@ func fetchEduArticle(
`,
slug,
)
if t != 0 {
qb.Add(`AND a.type = $?`, t)
if len(q.Types) > 0 {
qb.Add(`AND a.type = ANY($?)`, q.Types)
}
if currentUser == nil || !currentUser.CanSeeUnpublishedEducationContent() {
qb.Add(`AND NOT a.published`)
if (currentUser == nil || !currentUser.CanSeeUnpublishedEducationContent()) && !q.IncludeUnpublished {
qb.Add(`AND a.published`)
}
res, err := db.QueryOne[eduArticleResult](ctx, dbConn, qb.String(), qb.Args()...)

View File

@ -117,19 +117,16 @@ func NewWebsiteRoutes(conn *pgxpool.Pool) http.Handler {
hmnOnly.GET(hmnurl.RegexFishbowlIndex, FishbowlIndex)
hmnOnly.GET(hmnurl.RegexFishbowl, Fishbowl)
educationPrerelease := hmnOnly.WithMiddleware(educationBetaTestersOnly)
{
educationPrerelease.GET(hmnurl.RegexEducationIndex, EducationIndex)
educationPrerelease.GET(hmnurl.RegexEducationGlossary, EducationGlossary)
educationPrerelease.GET(hmnurl.RegexEducationArticleNew, educationAuthorsOnly(EducationArticleNew))
educationPrerelease.POST(hmnurl.RegexEducationArticleNew, educationAuthorsOnly(EducationArticleNewSubmit))
educationPrerelease.GET(hmnurl.RegexEducationRerender, educationAuthorsOnly(EducationRerender))
educationPrerelease.GET(hmnurl.RegexEducationArticle, EducationArticle) // Article stuff must be last so `/glossary` and others do not match as an article slug
educationPrerelease.GET(hmnurl.RegexEducationArticleEdit, educationAuthorsOnly(EducationArticleEdit))
educationPrerelease.POST(hmnurl.RegexEducationArticleEdit, educationAuthorsOnly(EducationArticleEditSubmit))
educationPrerelease.GET(hmnurl.RegexEducationArticleDelete, educationAuthorsOnly(EducationArticleDelete))
educationPrerelease.POST(hmnurl.RegexEducationArticleDelete, educationAuthorsOnly(csrfMiddleware(EducationArticleDeleteSubmit)))
}
hmnOnly.GET(hmnurl.RegexEducationIndex, EducationIndex)
hmnOnly.GET(hmnurl.RegexEducationGlossary, EducationGlossary)
hmnOnly.GET(hmnurl.RegexEducationArticleNew, educationAuthorsOnly(EducationArticleNew))
hmnOnly.POST(hmnurl.RegexEducationArticleNew, educationAuthorsOnly(EducationArticleNewSubmit))
hmnOnly.GET(hmnurl.RegexEducationRerender, educationAuthorsOnly(EducationRerender))
hmnOnly.GET(hmnurl.RegexEducationArticle, EducationArticle) // Article stuff must be last so `/glossary` and others do not match as an article slug
hmnOnly.GET(hmnurl.RegexEducationArticleEdit, educationAuthorsOnly(EducationArticleEdit))
hmnOnly.POST(hmnurl.RegexEducationArticleEdit, educationAuthorsOnly(EducationArticleEditSubmit))
hmnOnly.GET(hmnurl.RegexEducationArticleDelete, educationAuthorsOnly(EducationArticleDelete))
hmnOnly.POST(hmnurl.RegexEducationArticleDelete, educationAuthorsOnly(csrfMiddleware(EducationArticleDeleteSubmit)))
hmnOnly.POST(hmnurl.RegexAPICheckUsername, csrfMiddleware(APICheckUsername))