From af210c8903e82e1bbc99278ab71c6d453eca2a21 Mon Sep 17 00:00:00 2001 From: Yash Jipkate <34203227+YashJipkate@users.noreply.github.com> Date: Wed, 9 Jun 2021 01:14:30 +0530 Subject: [PATCH] Add Native Sharing REST API (#1150) * Initial draft - UNTESTED * changes to Save() and Update() * apply col filter and limit nanoid * remove columns to not update --- cmd/wire_gen.go | 3 +- core/share.go | 57 +++++++++++++++++++ core/wire_providers.go | 1 + .../20210601231734_update_share_fieldnames.go | 25 ++++++++ go.mod | 8 ++- go.sum | 12 ++++ main.go | 3 + model/share.go | 2 +- server/app/app.go | 7 ++- 9 files changed, 112 insertions(+), 6 deletions(-) create mode 100644 core/share.go create mode 100644 db/migration/20210601231734_update_share_fieldnames.go diff --git a/cmd/wire_gen.go b/cmd/wire_gen.go index cec66563a..c75239e24 100644 --- a/cmd/wire_gen.go +++ b/cmd/wire_gen.go @@ -31,7 +31,8 @@ func CreateServer(musicFolder string) *server.Server { func CreateAppRouter() *app.Router { dataStore := persistence.New() broker := GetBroker() - router := app.New(dataStore, broker) + share := core.NewShare(dataStore) + router := app.New(dataStore, broker, share) return router } diff --git a/core/share.go b/core/share.go new file mode 100644 index 000000000..b16a57d14 --- /dev/null +++ b/core/share.go @@ -0,0 +1,57 @@ +package core + +import ( + "context" + + "github.com/deluan/rest" + gonanoid "github.com/matoous/go-nanoid" + "github.com/navidrome/navidrome/model" +) + +type Share interface { + NewRepository(ctx context.Context) rest.Repository +} + +func NewShare(ds model.DataStore) Share { + return &shareService{ + ds: ds, + } +} + +type shareService struct { + ds model.DataStore +} + +func (s *shareService) NewRepository(ctx context.Context) rest.Repository { + repo := s.ds.Share(ctx) + wrapper := &shareRepositoryWrapper{ + ShareRepository: repo, + Repository: repo.(rest.Repository), + Persistable: repo.(rest.Persistable), + } + return wrapper +} + +type shareRepositoryWrapper struct { + model.ShareRepository + rest.Repository + rest.Persistable +} + +func (r *shareRepositoryWrapper) Save(entity interface{}) (string, error) { + s := entity.(*model.Share) + id, err := gonanoid.Generate("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 9) + s.Name = id + if err != nil { + return "", err + } + id, err = r.Persistable.Save(s) + return id, err +} + +func (r *shareRepositoryWrapper) Update(entity interface{}, _ ...string) error { + s := entity.(*model.Share) + cols := []string{"description"} + err := r.Persistable.Update(s, cols...) + return err +} diff --git a/core/wire_providers.go b/core/wire_providers.go index 2d57a10bc..d308a3c0a 100644 --- a/core/wire_providers.go +++ b/core/wire_providers.go @@ -16,4 +16,5 @@ var Set = wire.NewSet( NewCacheWarmer, NewPlayers, transcoder.New, + NewShare, ) diff --git a/db/migration/20210601231734_update_share_fieldnames.go b/db/migration/20210601231734_update_share_fieldnames.go new file mode 100644 index 000000000..cc6dd2076 --- /dev/null +++ b/db/migration/20210601231734_update_share_fieldnames.go @@ -0,0 +1,25 @@ +package migrations + +import ( + "database/sql" + + "github.com/pressly/goose" +) + +func init() { + goose.AddMigration(upUpdateShareFieldNames, downUpdateShareFieldNames) +} + +func upUpdateShareFieldNames(tx *sql.Tx) error { + _, err := tx.Exec(` +alter table share rename column expires to expires_at; +alter table share rename column created to created_at; +alter table share rename column last_visited to last_visited_at; +`) + + return err +} + +func downUpdateShareFieldNames(tx *sql.Tx) error { + return nil +} diff --git a/go.mod b/go.mod index f3b81889a..424b31928 100644 --- a/go.mod +++ b/go.mod @@ -4,14 +4,14 @@ go 1.16 require ( code.cloudfoundry.org/go-diodes v0.0.0-20190809170250-f77fb823c7ee - github.com/ClickHouse/clickhouse-go v1.4.3 // indirect + github.com/ClickHouse/clickhouse-go v1.4.5 // indirect github.com/Masterminds/squirrel v1.5.0 github.com/ReneKroon/ttlcache/v2 v2.6.0 github.com/astaxie/beego v1.12.3 github.com/bradleyjkemp/cupaloy v2.3.0+incompatible github.com/cespare/reflex v0.3.0 github.com/deluan/rest v0.0.0-20210503015435-e7091d44f0ba - github.com/denisenkom/go-mssqldb v0.9.0 // indirect + github.com/denisenkom/go-mssqldb v0.10.0 // indirect github.com/dhowden/tag v0.0.0-20200412032933-5d76b8eaae27 github.com/disintegration/imaging v1.6.2 github.com/djherbis/fscache v0.10.2-0.20201024185917-a0daa9e52747 @@ -20,12 +20,15 @@ require ( github.com/go-chi/cors v1.2.0 github.com/go-chi/httprate v0.4.0 github.com/go-chi/jwtauth/v5 v5.0.1 + github.com/go-sql-driver/mysql v1.6.0 // indirect github.com/golangci/golangci-lint v1.40.1 github.com/google/uuid v1.2.0 github.com/google/wire v0.5.0 github.com/kennygrant/sanitize v0.0.0-20170120101633-6a0bfdde8629 github.com/kr/pretty v0.2.1 github.com/lestrrat-go/jwx v1.2.0 + github.com/lib/pq v1.10.2 // indirect + github.com/matoous/go-nanoid v1.5.0 // indirect github.com/mattn/go-sqlite3 v2.0.3+incompatible github.com/microcosm-cc/bluemonday v1.0.9 github.com/mitchellh/mapstructure v1.3.2 // indirect @@ -45,6 +48,7 @@ require ( github.com/unrolled/secure v1.0.9 github.com/xrash/smetrics v0.0.0-20200730060457-89a2a8a1fb0b github.com/ziutek/mymysql v1.5.4 // indirect + golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 golang.org/x/tools v0.1.2-0.20210512205948-8287d5da45e4 diff --git a/go.sum b/go.sum index b41ff23c5..d6d401fd5 100644 --- a/go.sum +++ b/go.sum @@ -43,6 +43,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ClickHouse/clickhouse-go v1.4.3 h1:iAFMa2UrQdR5bHJ2/yaSLffZkxpcOYQMCUuKeNXGdqc= github.com/ClickHouse/clickhouse-go v1.4.3/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI= +github.com/ClickHouse/clickhouse-go v1.4.5 h1:FfhyEnv6/BaWldyjgT2k4gDDmeNwJ9C4NbY/MXxJlXk= +github.com/ClickHouse/clickhouse-go v1.4.5/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= @@ -161,6 +163,8 @@ github.com/denis-tingajkin/go-header v0.4.2 h1:jEeSF4sdv8/3cT/WY8AgDHUoItNSoEZ7q github.com/denis-tingajkin/go-header v0.4.2/go.mod h1:eLRHAVXzE5atsKAnNRDB90WHCFFnBUn4RN0nRcs1LJA= github.com/denisenkom/go-mssqldb v0.9.0 h1:RSohk2RsiZqLZ0zCjtfn3S4Gp4exhpBWHyQ7D0yGjAk= github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/denisenkom/go-mssqldb v0.10.0 h1:QykgLZBorFE95+gO3u9esLd0BmbvpWp0/waNNZfHBM8= +github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= 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/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= @@ -220,6 +224,8 @@ github.com/go-redis/redis v6.15.8+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8w github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= @@ -498,12 +504,16 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8= github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/maratori/testpackage v1.0.1 h1:QtJ5ZjqapShm0w5DosRjg0PRlSdAdlx+W6cCKoALdbQ= github.com/maratori/testpackage v1.0.1/go.mod h1:ddKdw+XG0Phzhx8BFDTKgpWP4i7MpApTE5fXSKAqwDU= +github.com/matoous/go-nanoid v1.5.0 h1:VRorl6uCngneC4oUQqOYtO3S0H5QKFtKuKycFG3euek= +github.com/matoous/go-nanoid v1.5.0/go.mod h1:zyD2a71IubI24efhpvkJz+ZwfwagzgSO6UNiFsZKN7U= github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 h1:pWxk9e//NbPwfxat7RXkts09K+dEBJWakUWwICVqYbA= github.com/matoous/godox v0.0.0-20210227103229-6504466cf951/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= @@ -841,6 +851,8 @@ golang.org/x/crypto v0.0.0-20201217014255-9d1352758620/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= diff --git a/main.go b/main.go index 0c2d0fafa..4c328d7fa 100644 --- a/main.go +++ b/main.go @@ -1,12 +1,15 @@ package main import ( + "math/rand" "runtime" + "time" "github.com/navidrome/navidrome/cmd" ) func main() { + rand.Seed(time.Now().UTC().UnixNano()) runtime.MemProfileRate = 0 cmd.Execute() } diff --git a/model/share.go b/model/share.go index ecc7f9537..02aee26f3 100644 --- a/model/share.go +++ b/model/share.go @@ -13,7 +13,7 @@ type Share struct { LastVisitedAt time.Time `json:"lastVisitedAt"` ResourceIDs string `json:"resourceIds" orm:"column(resource_ids)"` ResourceType string `json:"resourceType"` - VisitCount string `json:"visitCount"` + VisitCount int `json:"visitCount"` } type Shares []Share diff --git a/server/app/app.go b/server/app/app.go index 5de780a79..59a4eecaf 100644 --- a/server/app/app.go +++ b/server/app/app.go @@ -10,6 +10,7 @@ import ( "github.com/go-chi/chi/v5" "github.com/go-chi/httprate" "github.com/navidrome/navidrome/conf" + "github.com/navidrome/navidrome/core" "github.com/navidrome/navidrome/log" "github.com/navidrome/navidrome/model" "github.com/navidrome/navidrome/server/events" @@ -20,10 +21,11 @@ type Router struct { ds model.DataStore mux http.Handler broker events.Broker + share core.Share } -func New(ds model.DataStore, broker events.Broker) *Router { - return &Router{ds: ds, broker: broker} +func New(ds model.DataStore, broker events.Broker, share core.Share) *Router { + return &Router{ds: ds, broker: broker, share: share} } func (app *Router) Setup(path string) { @@ -62,6 +64,7 @@ func (app *Router) routes(path string) http.Handler { app.R(r, "/player", model.Player{}, true) app.R(r, "/playlist", model.Playlist{}, true) app.R(r, "/transcoding", model.Transcoding{}, conf.Server.EnableTranscodingConfig) + app.RX(r, "/share", app.share.NewRepository, true) app.RX(r, "/translation", newTranslationRepository, false) app.addPlaylistTrackRoute(r)