diff --git a/src/internal/auth/auth.go b/src/internal/auth/auth.go index e9457c6..0597981 100644 --- a/src/internal/auth/auth.go +++ b/src/internal/auth/auth.go @@ -21,7 +21,7 @@ var ( // UserBackend interface for user backend type UserBackend interface { - Get(username string) (User, error) + GetUser(username string) (User, error) } // User interface for user @@ -64,7 +64,7 @@ func (a *Authorizer) GenHash(password string) (string, error) { // Login cheks password and creates a jwt token func (a *Authorizer) Login(rw http.ResponseWriter, req *http.Request, username, password string) (User, error) { - u, err := a.Backend.Get(username) + u, err := a.Backend.GetUser(username) if err != nil { return nil, err } @@ -109,7 +109,7 @@ func (a *Authorizer) CurrentUser(rw http.ResponseWriter, req *http.Request) (Use } // Get the user - u, err := a.Backend.Get(tokenClaims.Username) + u, err := a.Backend.GetUser(tokenClaims.Username) if err != nil { return nil, err } diff --git a/src/internal/backend/backend.go b/src/internal/backend/backend.go new file mode 100644 index 0000000..3bb0094 --- /dev/null +++ b/src/internal/backend/backend.go @@ -0,0 +1,146 @@ +package backend + +import ( + "database/sql" + "errors" + + "gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/auth" + "gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/movies" + "gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/shows" + "gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/torrents" + "gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/users" + + "github.com/Sirupsen/logrus" + "github.com/jmoiron/sqlx" + polochon "github.com/odwrtw/polochon/lib" +) + +// Backend represents the data backend +type Backend struct { + Database *sqlx.DB +} + +// GetUser gets the username from the UserBackend +// Implements the UserBackend interface +func (b *Backend) GetUser(username string) (auth.User, error) { + return users.Get(b.Database, username) +} + +// Name implements the Module interface +func (b *Backend) Name() string { + return "canape-backend" +} + +// GetDetails implements the polochon Detailer interface +func (b *Backend) GetDetails(media interface{}, log *logrus.Entry) error { + switch t := media.(type) { + case *polochon.Show: + return b.GetShowDetails(t, log) + case *polochon.ShowEpisode: + return b.GetShowEpisodeDetails(t, log) + case *polochon.Movie: + return b.GetMovieDetails(t, log) + default: + return errors.New("invalid type") + } +} + +// GetMovieDetails gets details for movies +func (b *Backend) GetMovieDetails(pmovie *polochon.Movie, log *logrus.Entry) error { + m := movies.New(pmovie.ImdbID) + if err := m.GetMovie(b.Database); err != nil { + return err + } + log.Debugf("got movie %s from backend", pmovie.ImdbID) + *pmovie = m.Movie + return nil +} + +// GetShowDetails gets details for shows +func (b *Backend) GetShowDetails(pshow *polochon.Show, log *logrus.Entry) error { + s := shows.New(pshow.ImdbID) + if err := s.GetShow(b.Database); err != nil { + return err + } + log.Debugf("got show %s from backend", pshow.ImdbID) + *pshow = s.Show + return nil +} + +// GetShowEpisodeDetails gets details for episodes +func (b *Backend) GetShowEpisodeDetails(pepisode *polochon.ShowEpisode, log *logrus.Entry) error { + e := shows.NewEpisode() + e.ShowImdbID = pepisode.ShowImdbID + e.Season = pepisode.Season + e.Episode = pepisode.Episode + if err := e.GetEpisode(b.Database); err != nil { + return err + } + log.Debugf("got episode S%02dE%02d %s from backend", pepisode.Season, pepisode.Episode, pepisode.ShowImdbID) + *pepisode = e.ShowEpisode + return nil +} + +// GetTorrents implements the polochon Torrenter interface +func (b *Backend) GetTorrents(media interface{}, log *logrus.Entry) error { + switch t := media.(type) { + case *polochon.ShowEpisode: + return b.GetEpisodeTorrents(t, log) + case *polochon.Movie: + return b.GetMovieTorrents(t, log) + default: + return errors.New("invalid type") + } +} + +// GetMovieTorrents fetch Torrents for movies +func (b *Backend) GetMovieTorrents(pmovie *polochon.Movie, log *logrus.Entry) error { + // m := movies.New(pmovie.ImdbID) + movieTorrents, err := torrents.GetMovieTorrents(b.Database, pmovie.ImdbID) + switch err { + case nil: + log.Debug("torrents found in backend") + case sql.ErrNoRows: + log.Debug("torrent not found in backend") + default: + // Unexpected error + return err + } + log.Debugf("got torrents for movie %s from backend", pmovie.ImdbID) + + for _, t := range movieTorrents { + pmovie.Torrents = append(pmovie.Torrents, t.Torrent) + } + + return nil +} + +// GetEpisodeTorrents fetch Torrents for episodes +func (b *Backend) GetEpisodeTorrents(pepisode *polochon.ShowEpisode, log *logrus.Entry) error { + e := shows.NewEpisode() + e.ShowImdbID = pepisode.ShowImdbID + e.Season = pepisode.Season + e.Episode = pepisode.Episode + episodeTorrents, err := torrents.GetEpisodeTorrents( + b.Database, + pepisode.ShowImdbID, + pepisode.Season, + pepisode.Episode, + ) + switch err { + case nil: + log.Debug("torrents found in backend") + case sql.ErrNoRows: + log.Debug("torrent not found in backend") + default: + // Unexpected error + return err + } + log.Debugf("got torrents for episode S%02dE%02d %s from backend", pepisode.Season, pepisode.Episode, pepisode.ShowImdbID) + // Add the torrents to the episode + for _, t := range episodeTorrents { + e.Torrents = append(e.Torrents, t.Torrent) + } + + return nil +} diff --git a/src/internal/movies/movies.go b/src/internal/movies/movies.go index 8d69cb8..34ac7fb 100644 --- a/src/internal/movies/movies.go +++ b/src/internal/movies/movies.go @@ -32,7 +32,7 @@ const ( tagline=:tagline RETURNING id;` - getMovieQueryByImdbID = ` + getUserMovieQueryByImdbID = ` SELECT movies.id, movies.title, @@ -54,7 +54,7 @@ const ( ON movies.imdb_id=movies_tracked.imdb_id AND movies_tracked.user_id=$2 WHERE movies.imdb_id=$1;` - getMovieQueryByID = ` + getUserMovieQueryByID = ` SELECT movies.id, movies.title, @@ -76,6 +76,16 @@ const ( ON movies.imdb_id=movies_tracked.imdb_id AND movies_tracked.user_id=$2 WHERE movies.id=$1;` + getMovieQueryByImdbID = ` + SELECT * + FROM movies + WHERE imdb_id=$1;` + + getMovieQueryByID = ` + SELECT * + FROM movies + WHERE movies.id=$1;` + deleteMovieQuery = `DELETE FROM movies WHERE id=$1;` ) @@ -170,9 +180,9 @@ func (m *Movie) Get(env *web.Env, user *users.User) error { var mDB MovieDB var err error if m.ID != "" { - err = env.Database.QueryRowx(getMovieQueryByID, m.ID, user.ID).StructScan(&mDB) + err = env.Database.QueryRowx(getUserMovieQueryByID, m.ID, user.ID).StructScan(&mDB) } else if m.ImdbID != "" { - err = env.Database.QueryRowx(getMovieQueryByImdbID, m.ImdbID, user.ID).StructScan(&mDB) + err = env.Database.QueryRowx(getUserMovieQueryByImdbID, m.ImdbID, user.ID).StructScan(&mDB) } else { err = fmt.Errorf("Can't get movie details, you have to specify an ID or ImdbID") } @@ -187,7 +197,27 @@ func (m *Movie) Get(env *web.Env, user *users.User) error { return nil } -// GetDetails retrieves details for the movie, first try to get info from db, +// GetMovie returns show details in database from id or imdbid or an error +func (m *Movie) GetMovie(db *sqlx.DB) error { + var mDB MovieDB + var err error + if m.ID != "" { + err = db.QueryRowx(getMovieQueryByID, m.ID).StructScan(&mDB) + } else if m.ImdbID != "" { + err = db.QueryRowx(getMovieQueryByImdbID, m.ImdbID).StructScan(&mDB) + } else { + err = fmt.Errorf("Can't get movie details, you have to specify an ID or ImdbID") + } + if err != nil { + return err + } + + // Set the poster url + // m.PosterURL = m.GetPosterURL(env) + + m.FillFromDB(&mDB) + return nil +} // if not exists, use polochon.Detailer and save informations in the database // for future use // diff --git a/src/internal/shows/episodes.go b/src/internal/shows/episodes.go index 29f79f6..7b751a7 100644 --- a/src/internal/shows/episodes.go +++ b/src/internal/shows/episodes.go @@ -187,8 +187,13 @@ func (e *Episode) GetTorrents(env *web.Env, force bool) error { // Get returns an episode func (e *Episode) Get(env *web.Env) error { + return e.GetEpisode(env.Database) +} + +// GetEpisode returns an episode +func (e *Episode) GetEpisode(db *sqlx.DB) error { var episodeDB EpisodeDB - err := env.Database.QueryRowx(getEpisodeQuery, e.ShowImdbID, e.Season, e.Episode).StructScan(&episodeDB) + err := db.QueryRowx(getEpisodeQuery, e.ShowImdbID, e.Season, e.Episode).StructScan(&episodeDB) if err != nil { return err } diff --git a/src/internal/shows/shows.go b/src/internal/shows/shows.go index 681d77b..e0e4187 100644 --- a/src/internal/shows/shows.go +++ b/src/internal/shows/shows.go @@ -171,6 +171,27 @@ func (s *Show) Get(env *web.Env, user *users.User) error { return nil } +// GetShow returns a show with user info like tracked +func (s *Show) GetShow(db *sqlx.DB) error { + var err error + var sDB ShowDB + if s.ID != "" { + err = db.QueryRowx(getShowQueryByID, s.ID).StructScan(&sDB) + } else if s.ImdbID != "" { + err = db.QueryRowx(getShowQueryByImdbID, s.ImdbID).StructScan(&sDB) + } else { + err = fmt.Errorf("Can't get show details, you have to specify an ID or ImdbID") + } + if err != nil { + return err + } + // Set the poster url + // s.PosterURL = s.GetPosterURL(env) + + s.FillFromDB(&sDB) + return nil +} + // GetDetails retrieves details for the show, first try to // get info from db, if not exists, use polochon.Detailer // and save informations in the database for future use diff --git a/src/main.go b/src/main.go index 313a0f2..78fc2c2 100644 --- a/src/main.go +++ b/src/main.go @@ -5,6 +5,7 @@ import ( "os" "gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/auth" + "gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/backend" "gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/config" "gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/external_medias" "gitlab.quimbo.fr/odwrtw/canape-sql/src/internal/movies" @@ -20,16 +21,6 @@ import ( "github.com/urfave/negroni" ) -// UserBackend represents the data backend to get the user -type UserBackend struct { - Database *sqlx.DB -} - -// Get gets the username from the UserBackend -func (b *UserBackend) Get(username string) (auth.User, error) { - return users.Get(b.Database, username) -} - func main() { var cfgPath string cfgPath = os.Getenv("CONFIG_FILE") @@ -48,20 +39,23 @@ func main() { log.Panic(err) } + // Connect to the database db, err := sqlx.Connect("postgres", cf.PGDSN) if err != nil { log.Panic(err) } - uBackend := &UserBackend{Database: db} + backend := &backend.Backend{Database: db} + // Generate auth params authParams := auth.Params{ - Backend: uBackend, + Backend: backend, Pepper: cf.Authorizer.Pepper, Cost: cf.Authorizer.Cost, Secret: cf.Authorizer.Secret, } authorizer := auth.New(authParams) + // Create web environment needed by the app env := web.NewEnv(web.EnvParams{ Database: db, Auth: authorizer,