package handler import ( "fmt" "html/template" "io" "git.phc.dm.unipi.it/phc/website" "git.phc.dm.unipi.it/phc/website/articles" "git.phc.dm.unipi.it/phc/website/auth" "git.phc.dm.unipi.it/phc/website/model" "git.phc.dm.unipi.it/phc/website/rss" "git.phc.dm.unipi.it/phc/website/templates" "git.phc.dm.unipi.it/phc/website/util" ) type Service interface { HandleStaticPage(w io.Writer, view string, ctx Context) error HandleUtenti() ([]*model.User, error) HandleListaUtenti() ([]website.UserInfo, error) HandleStoriaPage(w io.Writer, ctx Context) error HandleQueryAppunti(w io.Writer, query string, ctx Context) error HandleNewsPage(w io.Writer, ctx Context) error HandleGuidePage(w io.Writer, ctx Context) error HandleLogin(username, password string) (*model.Session, error) HandleUser(token string) *model.User HandleRequiredUser(ctx Context) (*model.User, error) HandleProfilePage(w io.Writer, ctx Context) error HandleNewsArticlePage(w io.Writer, articleID string, ctx Context) error HandleGuideArticlePage(w io.Writer, articleID string, ctx Context) error HandleNewsFeedPage(w io.Writer) error HandleGuideFeedPage(w io.Writer) error } // // Typed context // // UserKey is a typed type for *model.User used to extract a user form a [handler.Context] const UserKey ContextKey[*model.User] = "user" func (ctx Context) getUser() *model.User { return GetContextValue(ctx, UserKey) } // Handler holds references to abstract services for easy testing provided by every module (TODO: Make every field an interface of -Service) type DefaultHandler struct { AuthService auth.Service Renderer *templates.TemplateRenderer NewsArticlesRegistry *articles.Registry GuideArticlesRegistry *articles.Registry ListaUtenti website.ListaUtentiService Storia website.StoriaService } func (h *DefaultHandler) HandleStaticPage(w io.Writer, view string, ctx Context) error { return h.Renderer.Render(w, view, util.Map{ "User": ctx.getUser(), }) } func (h *DefaultHandler) HandleUtenti() ([]*model.User, error) { utenti, err := h.AuthService.GetUsers() if err != nil { return nil, err } return utenti, nil } func (h *DefaultHandler) HandleListaUtenti() ([]website.UserInfo, error) { utenti, err := h.ListaUtenti.GetUtenti() if err != nil { return nil, err } return utenti, nil } func (h *DefaultHandler) HandleStoriaPage(w io.Writer, ctx Context) error { storia, err := h.Storia.GetStoria() if err != nil { return err } return h.Renderer.Render(w, "storia.html", util.Map{ "User": ctx.getUser(), "Storia": storia, }) } func (h *DefaultHandler) HandleQueryAppunti(w io.Writer, query string, ctx Context) error { return h.Renderer.Render(w, "appunti.html", util.Map{ "User": ctx.getUser(), "Query": query, }) } func (h *DefaultHandler) HandleNewsPage(w io.Writer, ctx Context) error { articles, err := h.NewsArticlesRegistry.GetArticles() if err != nil { return err } return h.Renderer.Render(w, "news.html", util.Map{ "User": ctx.getUser(), "Articles": articles, }) } func (h *DefaultHandler) HandleGuidePage(w io.Writer, ctx Context) error { articles, err := h.GuideArticlesRegistry.GetArticles() if err != nil { return err } return h.Renderer.Render(w, "guide.html", util.Map{ "User": ctx.getUser(), "Articles": articles, }) } func (h *DefaultHandler) HandleLogin(username, password string) (*model.Session, error) { session, err := h.AuthService.Login(username, password) if err != nil { return nil, err } return session, nil } func (h *DefaultHandler) HandleUser(token string) *model.User { user, _ := auth.UserForSession(h.AuthService, token) return user } var ErrNoUser = fmt.Errorf(`user not logged in`) func (h *DefaultHandler) HandleRequiredUser(ctx Context) (*model.User, error) { user := ctx.getUser() if user == nil { return nil, ErrNoUser } return user, nil } func (h *DefaultHandler) HandleProfilePage(w io.Writer, ctx Context) error { user := ctx.getUser() if user == nil { return ErrNoUser } return h.Renderer.Render(w, "profilo.html", util.Map{ "User": user, }) } func (h *DefaultHandler) HandleNewsArticlePage(w io.Writer, articleID string, ctx Context) error { article, err := h.NewsArticlesRegistry.GetArticle(articleID) if err != nil { return err } html, err := article.Render() if err != nil { return err } return h.Renderer.Render(w, "news-base.html", util.Map{ "User": ctx.getUser(), "Article": article, "ContentHTML": template.HTML(html), }) } func (h *DefaultHandler) HandleGuideArticlePage(w io.Writer, articleID string, ctx Context) error { article, err := h.GuideArticlesRegistry.GetArticle(articleID) if err != nil { return err } html, err := article.Render() if err != nil { return err } return h.Renderer.Render(w, "guide-base.html", util.Map{ "User": ctx.getUser(), "Article": article, "ContentHTML": template.HTML(html), }) } func (h *DefaultHandler) HandleNewsFeedPage(w io.Writer) error { registry, err := h.NewsArticlesRegistry.GetArticles() if err != nil { return err } newsFeed := rss.GenerateRssFeed(registry, "Feed Notizie PHC", "https://phc.dm.unipi.it/news", "Le ultime nuove sul PHC.") return newsFeed.WriteRss(w) } func (h *DefaultHandler) HandleGuideFeedPage(w io.Writer) error { registry, err := h.GuideArticlesRegistry.GetArticles() if err != nil { return err } guideFeed := rss.GenerateRssFeed(registry, "Feed Guide PHC", "https://phc.dm.unipi.it/guide", "Le piĆ¹ recenti guide a carattere informatico a cura dei macchinisti del PHC.") return guideFeed.WriteRss(w) }