package handler
import (
"fmt"
"html/template"
"io"
"git.phc.dm.unipi.it/phc/website/appunti"
"git.phc.dm.unipi.it/phc/website/articles"
"git.phc.dm.unipi.it/phc/website/auth"
"git.phc.dm.unipi.it/phc/website/lista_utenti"
"git.phc.dm.unipi.it/phc/website/model"
"git.phc.dm.unipi.it/phc/website/rss"
"git.phc.dm.unipi.it/phc/website/storia"
"git.phc.dm.unipi.it/phc/website/templates"
"git.phc.dm.unipi.it/phc/website/util"
)
type Service interface {
//
// Pages
//
HandleStaticPage ( w io . Writer , view string , ctx Context ) error
// Storia
HandleStoriaPage ( w io . Writer , ctx Context ) error
// Appunti
HandleAppuntiPage ( w io . Writer , query string , ctx Context ) error
HandleAppuntiCondivisiPage ( w io . Writer , ctx Context ) error
HandleDispensaPage ( w io . Writer , id string , ctx Context ) error
// News
HandleNewsPage ( w io . Writer , ctx Context ) error
// Guide
HandleGuidePage ( w io . Writer , ctx Context ) error
// User
HandleProfilePage ( w io . Writer , ctx Context ) error
// Article Pages
HandleNewsArticlePage ( w io . Writer , articleID string , ctx Context ) error
HandleGuideArticlePage ( w io . Writer , articleID string , ctx Context ) error
// RSS
HandleNewsFeedPage ( w io . Writer ) error
HandleGuideFeedPage ( w io . Writer ) error
//
// API
//
// User
HandleLogin ( username , password string ) ( * model . Session , error )
HandleUser ( token string ) * model . User
HandleRequiredUser ( ctx Context ) ( * model . User , error )
// User Listing
HandleUtenti ( ) ( [ ] * model . User , error )
HandleListaUtenti ( ) ( [ ] * model . ListUser , error )
// Appunti
HandleCreateDispensa ( template model . Dispensa , ctx Context ) ( * model . Dispensa , 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
AppuntiService appunti . Service
Renderer * templates . TemplateRenderer
NewsArticlesRegistry * articles . Registry
GuideArticlesRegistry * articles . Registry
ListaUtenti lista_utenti . Service
Storia storia . StoriaService
}
var _ Service = & DefaultHandler { }
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 ( ) ( [ ] * model . ListUser , 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 ) HandleAppuntiPage ( 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 ) HandleAppuntiCondivisiPage ( w io . Writer , ctx Context ) error {
return h . Renderer . Render ( w , "appunti-condivisi.html" , util . Map {
"User" : ctx . getUser ( ) ,
} )
}
func ( h * DefaultHandler ) HandleDispensaPage ( w io . Writer , id string , ctx Context ) error {
dispensa , err := h . AppuntiService . GetDispensa ( id )
if err != nil {
return err
}
return h . Renderer . Render ( w , "dispensa.html" , util . Map {
"User" : ctx . getUser ( ) ,
"Dispensa" : dispensa ,
} )
}
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 , "news" , "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 , "guide" , "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 )
}
//
// API
//
func ( h * DefaultHandler ) HandleCreateDispensa ( template model . Dispensa , ctx Context ) ( * model . Dispensa , error ) {
user := ctx . getUser ( )
if user == nil {
return nil , ErrNoUser
}
template . OwnerId = user . Username
id , err := h . AppuntiService . CreateDispensa ( template )
if err != nil {
return nil , err
}
template . Id = id
if len ( template . Tags ) > 0 {
h . AppuntiService . SetDispensaTags ( id , template . Tags )
}
return & template , nil
}