From de11a2f2c10ef8d664daf9c8971e4b775e5d8906 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Delattre?= Date: Fri, 5 May 2017 13:28:52 +0200 Subject: [PATCH 1/2] Add the image URL prefix in the configuration This allows us to use a custom URL for images and use a CDN for caching --- config.yml.exemple | 2 ++ src/internal/config/canape.go | 9 ++--- .../external_medias/external_medias.go | 4 +-- src/internal/external_medias/handlers.go | 4 +-- src/internal/movies/handlers.go | 4 ++- src/internal/movies/movies.go | 29 +++++++++------- src/internal/shows/handlers.go | 8 ++--- src/internal/shows/shows.go | 34 ++++++++++--------- 8 files changed, 52 insertions(+), 42 deletions(-) diff --git a/config.yml.exemple b/config.yml.exemple index 5d00b47..a198efb 100644 --- a/config.yml.exemple +++ b/config.yml.exemple @@ -5,6 +5,8 @@ authorizer: pgdsn: postgres://test:test@127.0.0.1:5432/dev?sslmode=disable listen_port: 3000 public_dir: build/public +# default prefix, will be served by the go http server +img_url_prefix: img/ movie: detailers: diff --git a/src/internal/config/canape.go b/src/internal/config/canape.go index 1687997..1f3f212 100644 --- a/src/internal/config/canape.go +++ b/src/internal/config/canape.go @@ -13,10 +13,11 @@ import ( // Config represents the Config of the canape app type Config struct { - Authorizer AuthorizerConfig `yaml:"authorizer"` - PGDSN string `yaml:"pgdsn"` - Port string `yaml:"listen_port"` - PublicDir string `yaml:"public_dir"` + Authorizer AuthorizerConfig `yaml:"authorizer"` + PGDSN string `yaml:"pgdsn"` + Port string `yaml:"listen_port"` + PublicDir string `yaml:"public_dir"` + ImgURLPrefix string `yaml:"img_url_prefix"` MovieExplorers []polochon.Explorer MovieDetailers []polochon.Detailer diff --git a/src/internal/external_medias/external_medias.go b/src/internal/external_medias/external_medias.go index 7bfa1a3..da915e6 100644 --- a/src/internal/external_medias/external_medias.go +++ b/src/internal/external_medias/external_medias.go @@ -116,7 +116,7 @@ func RefreshShows(env *web.Env) { } // Iterate over the map of shows to refresh them for id := range showMap { - show := shows.New(id, env.Config.PublicDir) + show := shows.New(id, env.Config.PublicDir, env.Config.ImgURLPrefix) // Refresh the shows err := show.Refresh(env, env.Config.ShowDetailers) if err != nil { @@ -161,7 +161,7 @@ func RefreshMovies(env *web.Env) { } // Iterate over the map of movies to refresh them for id := range movieMap { - movie := movies.New(id, nil, nil, false, env.Config.PublicDir) + movie := movies.New(id, nil, nil, false, env.Config.PublicDir, env.Config.ImgURLPrefix) // Refresh the movie err := movie.Refresh(env, env.Config.MovieDetailers) if err != nil { diff --git a/src/internal/external_medias/handlers.go b/src/internal/external_medias/handlers.go index 116b1d2..2cef734 100644 --- a/src/internal/external_medias/handlers.go +++ b/src/internal/external_medias/handlers.go @@ -83,7 +83,7 @@ func GetMovies(env *web.Env, user *users.User, source string, category string) ( // Fill all the movies infos from the list of IDs for _, id := range media.IDs { pMovie, _ := pMovies.Has(id) - movie := movies.New(id, client, pMovie, moviesWishlist.IsMovieInWishlist(id), env.Config.PublicDir) + movie := movies.New(id, client, pMovie, moviesWishlist.IsMovieInWishlist(id), env.Config.PublicDir, env.Config.ImgURLPrefix) // First check in the DB before := []polochon.Detailer{env.Backend.Detailer} // Then with the default detailers @@ -144,7 +144,7 @@ func GetShows(env *web.Env, user *users.User, source string, category string, fo for _, id := range media.IDs { pShow, _ := pShows.Has(id) wShow, _ := wShows.IsShowInWishlist(id) - show := shows.NewWithClient(id, client, pShow, wShow, env.Config.PublicDir) + show := shows.NewWithClient(id, client, pShow, wShow, env.Config.PublicDir, env.Config.ImgURLPrefix) // First check in the DB before := []polochon.Detailer{env.Backend.Detailer} diff --git a/src/internal/movies/handlers.go b/src/internal/movies/handlers.go index 50c1c05..9b73f2b 100644 --- a/src/internal/movies/handlers.go +++ b/src/internal/movies/handlers.go @@ -87,7 +87,7 @@ func RefreshMovieHandler(env *web.Env, w http.ResponseWriter, r *http.Request) e } // Create a new movie - m := New(id, client, pMovie, isWishlisted, env.Config.PublicDir) + m := New(id, client, pMovie, isWishlisted, env.Config.PublicDir, env.Config.ImgURLPrefix) // Refresh the movie's infos if err := m.Refresh(env, env.Config.MovieDetailers); err != nil { @@ -163,6 +163,7 @@ func SearchMovie(env *web.Env, w http.ResponseWriter, r *http.Request) error { pMovie, moviesWishlist.IsMovieInWishlist(m.ImdbID), env.Config.PublicDir, + env.Config.ImgURLPrefix, ) // First check in the DB @@ -289,6 +290,7 @@ func GetWishlistHandler(env *web.Env, w http.ResponseWriter, r *http.Request) er pMovie, moviesWishlist.IsMovieInWishlist(imdbID), env.Config.PublicDir, + env.Config.ImgURLPrefix, ) // First check in the DB before := []polochon.Detailer{env.Backend.Detailer} diff --git a/src/internal/movies/movies.go b/src/internal/movies/movies.go index 194e6ed..523ccfb 100644 --- a/src/internal/movies/movies.go +++ b/src/internal/movies/movies.go @@ -19,10 +19,11 @@ import ( // Movie represents a movie type Movie struct { *polochon.Movie - client *papi.Client - pMovie *papi.Movie - publicDir string - Wishlisted bool `json:"wishlisted"` + client *papi.Client + pMovie *papi.Movie + publicDir string + imgURLPrefix string + Wishlisted bool `json:"wishlisted"` } // MarshalJSON implements the Marshal interface @@ -50,12 +51,13 @@ func (m *Movie) MarshalJSON() ([]byte, error) { } // New returns a new Movie with all the needed infos -func New(imdbID string, client *papi.Client, pMovie *papi.Movie, isWishlisted bool, publicDir string) *Movie { +func New(imdbID string, client *papi.Client, pMovie *papi.Movie, isWishlisted bool, publicDir, imgURLPrefix string) *Movie { return &Movie{ - client: client, - pMovie: pMovie, - publicDir: publicDir, - Wishlisted: isWishlisted, + client: client, + pMovie: pMovie, + publicDir: publicDir, + imgURLPrefix: imgURLPrefix, + Wishlisted: isWishlisted, Movie: &polochon.Movie{ ImdbID: imdbID, }, @@ -205,12 +207,12 @@ func (m *Movie) RefreshTorrents(env *web.Env, torrenters []polochon.Torrenter) e // imgURL returns the default image url func (m *Movie) imgURL() string { - return fmt.Sprintf("img/movies/%s.jpg", m.ImdbID) + return fmt.Sprintf("movies/%s.jpg", m.ImdbID) } // imgFile returns the image location on disk func (m *Movie) imgFile() string { - return filepath.Join(m.publicDir, m.imgURL()) + return filepath.Join(m.publicDir, "img", m.imgURL()) } // PosterURL returns the image URL or the default image if the poster is not yet downloaded @@ -218,9 +220,9 @@ func (m *Movie) PosterURL() string { // Check if the movie image exists if _, err := os.Stat(m.imgFile()); os.IsNotExist(err) { // TODO image in the config ? - return "img/noimage.png" + return m.imgURLPrefix + "noimage.png" } - return m.imgURL() + return m.imgURLPrefix + m.imgURL() } // getPolochonMovies returns an array of the user's polochon movies @@ -253,6 +255,7 @@ func getPolochonMovies(user *users.User, env *web.Env) ([]*Movie, error) { pmovie, moviesWishlist.IsMovieInWishlist(pmovie.ImdbID), env.Config.PublicDir, + env.Config.ImgURLPrefix, ) movies = append(movies, movie) } diff --git a/src/internal/shows/handlers.go b/src/internal/shows/handlers.go index f92ad20..41bb025 100644 --- a/src/internal/shows/handlers.go +++ b/src/internal/shows/handlers.go @@ -48,7 +48,7 @@ func GetDetailsHandler(env *web.Env, w http.ResponseWriter, r *http.Request) err log.Println("Got error getting wishlisted show ", err) } - s := NewWithClient(id, client, pShow, wShow, env.Config.PublicDir) + s := NewWithClient(id, client, pShow, wShow, env.Config.PublicDir, env.Config.ImgURLPrefix) // First try from the db first := []polochon.Detailer{env.Backend.Detailer} // Then try from the polochon detailers @@ -98,7 +98,7 @@ func RefreshShowHandler(env *web.Env, w http.ResponseWriter, r *http.Request) er log.Println("Got error getting wishlisted show ", err) } - s := NewWithClient(id, client, pShow, wShow, env.Config.PublicDir) + s := NewWithClient(id, client, pShow, wShow, env.Config.PublicDir, env.Config.ImgURLPrefix) // Refresh the polochon detailers detailers := env.Config.ShowDetailers err = s.Refresh(env, detailers) @@ -177,7 +177,7 @@ func SearchShow(env *web.Env, w http.ResponseWriter, r *http.Request) error { for _, s := range shows { pShow, _ := pShows.Has(s.ImdbID) wShow, _ := wShows.IsShowInWishlist(s.ImdbID) - show := NewWithClient(s.ImdbID, client, pShow, wShow, env.Config.PublicDir) + show := NewWithClient(s.ImdbID, client, pShow, wShow, env.Config.PublicDir, env.Config.ImgURLPrefix) // First try from the db first := []polochon.Detailer{env.Backend.Detailer} @@ -268,7 +268,7 @@ func GetWishlistHandler(env *web.Env, w http.ResponseWriter, r *http.Request) er showList := []*Show{} for _, wishedShow := range wShows.List() { pShow, _ := pShows.Has(wishedShow.ImdbID) - show := NewWithClient(wishedShow.ImdbID, client, pShow, wishedShow, env.Config.PublicDir) + show := NewWithClient(wishedShow.ImdbID, client, pShow, wishedShow, env.Config.PublicDir, env.Config.ImgURLPrefix) // First check in the DB before := []polochon.Detailer{env.Backend.Detailer} diff --git a/src/internal/shows/shows.go b/src/internal/shows/shows.go index 6059b2e..dc11b24 100644 --- a/src/internal/shows/shows.go +++ b/src/internal/shows/shows.go @@ -24,6 +24,7 @@ type Show struct { TrackedSeason *int `json:"tracked_season"` TrackedEpisode *int `json:"tracked_episode"` publicDir string + imgURLPrefix string } // MarshalJSON implements the Marshal interface @@ -56,24 +57,26 @@ func (s *Show) MarshalJSON() ([]byte, error) { } // New returns a new Show with a polochon ShowConfig -func New(imdbID string, publicDir string) *Show { +func New(imdbID string, publicDir, imgURLPrefix string) *Show { return &Show{ Show: &polochon.Show{ ImdbID: imdbID, }, - publicDir: publicDir, + publicDir: publicDir, + imgURLPrefix: imgURLPrefix, } } // NewWithClient returns a new Show with a polochon ShowConfig -func NewWithClient(imdbID string, client *papi.Client, pShow *papi.Show, wShow *backend.WishedShow, publicDir string) *Show { +func NewWithClient(imdbID string, client *papi.Client, pShow *papi.Show, wShow *backend.WishedShow, publicDir, imgURLPrefix string) *Show { s := &Show{ Show: &polochon.Show{ ImdbID: imdbID, }, - client: client, - pShow: pShow, - publicDir: publicDir, + client: client, + pShow: pShow, + publicDir: publicDir, + imgURLPrefix: imgURLPrefix, } if wShow != nil { s.TrackedSeason = &wShow.Season @@ -153,9 +156,9 @@ func (s *Show) GetImageURL(imgType string) string { // Check if the show image exists if _, err := os.Stat(s.imgFile(imgType)); os.IsNotExist(err) { // TODO image in the config ? - return "img/noimage.png" + return s.imgURLPrefix + "noimage.png" } - return s.imgURL(imgType) + return s.imgURLPrefix + s.imgURL(imgType) } // downloadImages will download the show images @@ -175,15 +178,14 @@ func (s *Show) downloadImages(env *web.Env) { } } -// imgFile returns the image location on disk -func (s *Show) imgFile(imgType string) string { - fileURL := fmt.Sprintf("img/shows/%s-%s.jpg", s.ImdbID, imgType) - return filepath.Join(s.publicDir, fileURL) -} - // imgURL returns the default image url func (s *Show) imgURL(imgType string) string { - return fmt.Sprintf("img/shows/%s-%s.jpg", s.ImdbID, imgType) + return fmt.Sprintf("shows/%s-%s.jpg", s.ImdbID, imgType) +} + +// imgFile returns the image location on disk +func (s *Show) imgFile(imgType string) string { + return filepath.Join(s.publicDir, "img", s.imgURL(imgType)) } // getPolochonShows returns all the Shows from the polochon of a user @@ -209,7 +211,7 @@ func getPolochonShows(env *web.Env, user *users.User) ([]*Show, error) { // Create Shows objects from the shows retrieved for _, pShow := range pshows.List() { wShow, _ := wShows.IsShowInWishlist(pShow.ImdbID) - show := NewWithClient(pShow.ImdbID, client, pShow, wShow, env.Config.PublicDir) + show := NewWithClient(pShow.ImdbID, client, pShow, wShow, env.Config.PublicDir, env.Config.ImgURLPrefix) shows = append(shows, show) } return shows, nil From 215bb09c2ef2310bd13294595b8acebdbc158694 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Delattre?= Date: Fri, 5 May 2017 13:40:26 +0200 Subject: [PATCH 2/2] Allow non admin users to delete movies The security is ensured by the token, not by the status of the user --- src/public/js/components/movies/actions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/public/js/components/movies/actions.js b/src/public/js/components/movies/actions.js index bc61e4d..74cea59 100644 --- a/src/public/js/components/movies/actions.js +++ b/src/public/js/components/movies/actions.js @@ -11,7 +11,7 @@ export default function ActionsButton(props) { resourceId={props.movieId} getDetails={props.getDetails} /> - {(props.isUserAdmin && props.hasMovie) && + {props.hasMovie &&