Merge branch 'master' of ssh://git.andreafazzi.eu:10022/andrea/youtube-dl-service
This commit is contained in:
commit
9691ca6c5c
6 changed files with 127 additions and 1 deletions
26
backend/config.go
Normal file
26
backend/config.go
Normal file
|
@ -0,0 +1,26 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Password string `yaml:"password"`
|
||||
CookieStoreKey string `yaml:"cookie_store_key"`
|
||||
JWTSigningKey string `yaml:"jwt_signing_key"`
|
||||
JWTExpireTime uint `yaml:"jwt_expire_time"`
|
||||
}
|
||||
|
||||
// ReadFile reads the config file placed at the given path.
|
||||
func ReadConfig(path string, config *Config) error {
|
||||
cf, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := yaml.Unmarshal(cf, config); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
4
backend/config.yaml
Normal file
4
backend/config.yaml
Normal file
|
@ -0,0 +1,4 @@
|
|||
password: "secret"
|
||||
jwt_signing_key: "abracadabra"
|
||||
jwt_expire_time: 60
|
||||
cookie_store_key: "abracadabra"
|
|
@ -3,8 +3,10 @@ module git.andreafazzi.eu/andrea/youtube-dl-service
|
|||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||
github.com/gin-contrib/cors v1.3.1
|
||||
github.com/gin-gonic/gin v1.7.4
|
||||
github.com/kkdai/youtube/v2 v2.7.4
|
||||
github.com/remogatto/prettytest v0.0.0-20200211072524-6d385e11dcb8 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
|
|
@ -75,6 +75,7 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc
|
|||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
|
|
|
@ -6,14 +6,21 @@ import (
|
|||
"net/http"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"git.andreafazzi.eu/andrea/youtube-dl-service/downloader"
|
||||
youtube_dl "git.andreafazzi.eu/andrea/youtube-dl-service/downloader/youtube-dl"
|
||||
"git.andreafazzi.eu/andrea/youtube-dl-service/task"
|
||||
jwt "github.com/dgrijalva/jwt-go"
|
||||
"github.com/gin-contrib/cors"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultJWTExpireTime = 60
|
||||
DefaultSigningKey = "secret"
|
||||
)
|
||||
|
||||
var tasks task.Tasks
|
||||
|
||||
func init() {
|
||||
|
@ -58,12 +65,51 @@ func data(c *gin.Context, id string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func postLogin(c *gin.Context, config *Config) error {
|
||||
err := c.Request.ParseForm()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
token, err := getToken(config, c.PostForm("password"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, token)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getToken(config *Config, password string) ([]byte, error) {
|
||||
if password != config.Password {
|
||||
return nil, fmt.Errorf("Wrong password!")
|
||||
}
|
||||
|
||||
/* Set token claims */
|
||||
claims := make(map[string]interface{})
|
||||
|
||||
// Token expire time
|
||||
claims["exp"] = time.Now().Add(time.Minute * time.Duration(config.JWTExpireTime)).Unix()
|
||||
|
||||
/* Create the token */
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims(claims))
|
||||
|
||||
/* Sign the token with our secret */
|
||||
tokenString, err := token.SignedString(config.JWTSigningKey)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return []byte(tokenString), nil
|
||||
}
|
||||
|
||||
// API outline
|
||||
//
|
||||
// POST /task content: url=https://foo.org start a new download task
|
||||
// GET /task/:id get the status for the task
|
||||
// GET /task/:id/download download the file resulted from the task execution
|
||||
//
|
||||
func main() {
|
||||
r := gin.Default()
|
||||
r.Use(cors.New(cors.Config{
|
||||
|
@ -76,6 +122,12 @@ func main() {
|
|||
AllowHeaders: []string{"*"},
|
||||
}))
|
||||
|
||||
config := new(Config)
|
||||
err := ReadConfig("config.yaml", config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
r.Use(gin.CustomRecovery(func(c *gin.Context, recovered interface{}) {
|
||||
if err, ok := recovered.(string); ok {
|
||||
c.String(http.StatusInternalServerError, fmt.Sprintf("error: %s", err))
|
||||
|
@ -97,5 +149,11 @@ func main() {
|
|||
}
|
||||
})
|
||||
|
||||
r.POST("/login", func(c *gin.Context) {
|
||||
if err := postLogin(c, config); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
})
|
||||
|
||||
r.Run()
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.andreafazzi.eu/andrea/youtube-dl-service/downloader"
|
||||
"git.andreafazzi.eu/andrea/youtube-dl-service/logger"
|
||||
|
@ -15,6 +16,8 @@ import (
|
|||
"github.com/remogatto/prettytest"
|
||||
)
|
||||
|
||||
var config *Config
|
||||
|
||||
// Start of setup
|
||||
type testSuite struct {
|
||||
prettytest.Suite
|
||||
|
@ -30,6 +33,12 @@ func TestRunner(t *testing.T) {
|
|||
func (t *testSuite) BeforeAll() {
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
logger.SetLevel(logger.Disabled)
|
||||
|
||||
config = new(Config)
|
||||
err := ReadConfig("config.yaml", config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Test the creation of a new task. A new task is created with a POST
|
||||
|
@ -49,6 +58,9 @@ func (t *testSuite) TestGetTask() {
|
|||
panic(err)
|
||||
}
|
||||
|
||||
timer := time.NewTimer(time.Second * 10)
|
||||
<-timer.C
|
||||
|
||||
// Create a new request
|
||||
req, err := http.NewRequest("GET", "/task/"+video.ID, nil)
|
||||
if err != nil {
|
||||
|
@ -75,6 +87,29 @@ func (t *testSuite) TestGetTask() {
|
|||
t.Equal(task.StatusCompleted, ts.Status)
|
||||
}
|
||||
|
||||
func (t *testSuite) TestPostLogin() {
|
||||
// Set form values
|
||||
form := url.Values{}
|
||||
form.Add("password", "secret")
|
||||
|
||||
req, err := http.NewRequest("POST", "/login", strings.NewReader((form.Encode())))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
// Create an http recorder
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
// Set the context and call the handler
|
||||
c, _ := gin.CreateTestContext(rr)
|
||||
c.Request = req
|
||||
|
||||
err = postLogin(c, config)
|
||||
t.Nil(err)
|
||||
}
|
||||
|
||||
func postTask(ytUrl string) (*downloader.Video, error) {
|
||||
// Set form values
|
||||
form := url.Values{}
|
||||
|
|
Loading…
Reference in a new issue