diff --git a/environment/environment.go b/environment/environment.go new file mode 100644 index 0000000000000000000000000000000000000000..114924aa50eefea902fee010aa3e5722887acbea --- /dev/null +++ b/environment/environment.go @@ -0,0 +1,62 @@ +package environment + +import ( + "encoding/json" + "github.com/hibiken/asynq" + "github.com/jmoiron/sqlx" + "github.com/justjanne/imgconv" + "os" +) + +type Environment struct { + Queue *asynq.Client + Database *sqlx.DB + RolePrefix string + Sizes []imgconv.Size + Quality imgconv.Quality +} + +func NewEnvironment( + redisAddress string, + dbType string, + dbUrl string, + rolePrefix string, + sizes []imgconv.Size, + quality imgconv.Quality, +) (env Environment, err error) { + env.Queue = asynq.NewClient(asynq.RedisClientOpt{ + Addr: redisAddress, + }) + env.Database, err = sqlx.Open(dbType, dbUrl) + env.RolePrefix = rolePrefix + env.Sizes = sizes + env.Quality = quality + return +} + +func InitializeEnvironment() (env Environment, err error) { + var sizes []imgconv.Size + if err = json.Unmarshal([]byte(os.Getenv("CONFIG_SIZES")), &sizes); err != nil { + return + } + var quality imgconv.Quality + if err = json.Unmarshal([]byte(os.Getenv("CONFIG_QUALITY")), &quality); err != nil { + return + } + rolePrefix := os.Getenv("CONFIG_ROLE_PREFIX") + + redisAddress := os.Getenv("REDIS_ADDRESS") + dbType := os.Getenv("DB_TYPE") + dbUrl := os.Getenv("DB_URL") + return NewEnvironment(redisAddress, dbType, dbUrl, rolePrefix, sizes, quality) +} + +func (env Environment) Destroy() error { + if err := env.Queue.Close(); err != nil { + return err + } + if err := env.Database.Close(); err != nil { + return err + } + return nil +} diff --git a/go.mod b/go.mod index e3712525ade50b986a838c2ac3e5977d33d94a5f..96db1b4367823f02aad20f4964a48c1f05b8eb34 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,13 @@ module git.kuschku.de/justjanne/imghost-frontend go 1.13 require ( - github.com/hibiken/asynq v0.18.2 // indirect - github.com/jackc/pgx v3.6.2+incompatible // indirect - github.com/jmoiron/sqlx v1.3.4 // indirect - github.com/justjanne/imgconv v1.0.3 - github.com/minio/minio-go/v7 v7.0.12 // indirect - github.com/pkg/errors v0.9.1 // indirect - golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect + github.com/hibiken/asynq v0.18.2 + github.com/jmoiron/sqlx v1.3.4 + github.com/justjanne/imgconv v1.0.3 // indirect + github.com/lib/pq v1.10.2 + github.com/stretchr/testify v1.4.0 // indirect + golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect + golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect golang.org/x/text v0.3.6 // indirect + gopkg.in/yaml.v2 v2.2.8 // indirect ) diff --git a/go.sum b/go.sum index 07641f48c5ed326a6a430db967e19868ccd56f48..190c08b6451b72e1f0b75aaf35d5a69b58cec899 100644 --- a/go.sum +++ b/go.sum @@ -3,14 +3,15 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/go-redis/redis/v7 v7.4.0 h1:7obg6wUoj05T0EpY0o8B59S9w5yeMWql7sw2kwNW1x4= github.com/go-redis/redis/v7 v7.4.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg= +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/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -27,73 +28,47 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/hibiken/asynq v0.18.2 h1:hbLVygnmQMc2evTmNildtUWaUPHIBtggA59MoaHp/bY= github.com/hibiken/asynq v0.18.2/go.mod h1:Sn3Ql1clxIO5kXoFOAE3W73tX81Hkau+2Kam9LfgymM= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/jackc/pgx v3.6.2+incompatible h1:2zP5OD7kiyR3xzRYMhOcXVvkDZsImVXfj+yIyTQf3/o= -github.com/jackc/pgx v3.6.2+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= github.com/jmoiron/sqlx v1.3.4 h1:wv+0IJZfL5z0uZoUjlpKgHkgaFSYD+r9CfrXjEXsO7w= github.com/jmoiron/sqlx v1.3.4/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= -github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/justjanne/imgconv v1.0.3 h1:XXgqeLJ1ibV0XCdosMqVV65CdpmDADTnC3yBR2w52vE= github.com/justjanne/imgconv v1.0.3/go.mod h1:8VxkQjMdEOziT9LJ8Mrqtz7SbmqlpExl69K8/CZWeAc= -github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s= -github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= +github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/minio/md5-simd v1.1.0 h1:QPfiOqlZH+Cj9teu0t9b1nTBfPbyTl16Of5MeuShdK4= -github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw= -github.com/minio/minio-go/v7 v7.0.12 h1:/4pxUdwn9w0QEryNkrrWaodIESPRX+NxpO0Q6hVdaAA= -github.com/minio/minio-go/v7 v7.0.12/go.mod h1:S23iSP5/gbMwtxeY5FM71R+TkAYyzEdoNEDDwpt8yWs= -github.com/minio/sha256-simd v0.1.1 h1:5QHSlgo3nt5yKOJrC7W8w7X+NFl8cMPZm96iu8kKUJU= -github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= -github.com/rs/xid v1.2.1 h1:mhH9Nq+C1fY2l1XIpgxIiUOfNpRBYH1kKcr+qfKgjRc= -github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +go.uber.org/goleak v0.10.0 h1:G3eWbSNIskeRqtsN/1uI5B+eP73y3JUuBsv9AZjehb4= go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -103,9 +78,7 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -115,16 +88,11 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -137,8 +105,8 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -158,17 +126,19 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gographics/imagick.v2 v2.6.0 h1:ewRsUQk3QkjGumERlndbFn/kTYRjyMaPY5gxwpuAhik= gopkg.in/gographics/imagick.v2 v2.6.0/go.mod h1:/QVPLV/iKdNttRKthmDkeeGg+vdHurVEPc8zkU0XgBk= -gopkg.in/ini.v1 v1.57.0 h1:9unxIsFcTt4I55uWluz+UmL95q4kdJ0buvQ1ZIqVQww= -gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/main.go b/main.go index 50d110baf9b85a705092c309c3e866ee0591bd25..e5a5af7d474fcb5ec5cd8d632efc946cc369ce03 100644 --- a/main.go +++ b/main.go @@ -1,27 +1,58 @@ package main import ( - "net/http" + "fmt" + "git.kuschku.de/justjanne/imghost-frontend/environment" + "git.kuschku.de/justjanne/imghost-frontend/model" + "git.kuschku.de/justjanne/imghost-frontend/repo" + _ "github.com/lib/pq" ) -func MethodOverride(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if r.Method == http.MethodPost { - method := r.PostFormValue("_method") - if method == "" { - method = r.Header.Get("X-HTTP-Method-Override") - } - - if method == http.MethodPut || - method == http.MethodPatch || - method == http.MethodDelete { - r.Method = method - } - } - next.ServeHTTP(w, r) - }) -} - func main() { - println("Hello World!") + user := model.User{ + Id: "ad45284c-be4d-4546-8171-41cf126ac091", + Name: "justJanne", + Email: "janne@kuschku.de", + Roles: []string{"imghost:user", "imghost:admin"}, + } + + var env environment.Environment + env, err := environment.InitializeEnvironment() + if err != nil { + panic(err) + } + defer env.Destroy() + + imageRepo, err := repo.NewImageRepo(env.Database) + if err != nil { + panic(err) + } + + albumRepo, err := repo.NewAlbumRepo(env.Database) + if err != nil { + panic(err) + } + + albumImageRepo, err := repo.NewAlbumImageRepo(env.Database) + if err != nil { + panic(err) + } + + images, err := imageRepo.List(user) + if err != nil { + panic(err) + } + fmt.Printf("images: %v\n", len(images)) + + albums, err := albumRepo.List(user) + if err != nil { + panic(err) + } + fmt.Printf("albums: %v\n", len(albums)) + + albumImages, err := albumImageRepo.List(model.Album{}) + if err != nil { + panic(err) + } + fmt.Printf("albumImages: %v\n", len(albumImages)) } diff --git a/model/album.go b/model/album.go index 59f060dec70ba7bf12a42c9d16ec690e14f25c05..75da1e6da418997525fd60c6f01e249cc90fac8d 100644 --- a/model/album.go +++ b/model/album.go @@ -6,12 +6,12 @@ import ( ) type Album struct { - Id string `json:"id"` - Owner string `json:"owner"` - Title string `json:"title"` - Description string `json:"description"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` + Id string `json:"id" db:"id"` + Owner string `json:"owner" db:"owner"` + Title string `json:"title" db:"title"` + Description string `json:"description" db:"description"` + CreatedAt time.Time `json:"created_at" db:"created_at"` + UpdatedAt time.Time `json:"updated_at" db:"updated_at"` } func (album Album) VerifyOwner(user User) error { diff --git a/model/album_image.go b/model/album_image.go index 3bb099c54d02400ca53eeb8c41283d91cb478af6..b757f7fb6102e69fb73118247318900c3c0ae5f3 100644 --- a/model/album_image.go +++ b/model/album_image.go @@ -1,7 +1,8 @@ package model type AlbumImage struct { - Id string `json:"id"` - Title string `json:"title"` - Description string `json:"description"` + Album string `json:"album" db:"album"` + Image string `json:"image" db:"image"` + Title string `json:"title" db:"title"` + Description string `json:"description" db:"description"` } diff --git a/model/image.go b/model/image.go index 695ad83f134e93e92492f63b20163ffe0db507bd..f3ba2ed39665f0ace26daf2c07c11e898861a842 100644 --- a/model/image.go +++ b/model/image.go @@ -6,14 +6,14 @@ import ( ) type Image struct { - Id string `json:"id"` - Owner string `json:"owner"` - Title string `json:"title"` - Description string `json:"description"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` - OriginalName string `json:"original_name"` - MimeType string `json:"mime_type"` + Id string `json:"id" db:"id"` + Owner string `json:"owner" db:"owner"` + Title string `json:"title" db:"title"` + Description string `json:"description" db:"description"` + CreatedAt time.Time `json:"created_at" db:"created_at"` + UpdatedAt time.Time `json:"updated_at" db:"updated_at"` + OriginalName string `json:"original_name" db:"original_name"` + MimeType string `json:"mime_type" db:"mime_type"` } func (image Image) VerifyOwner(user User) error { diff --git a/repo/album_images.go b/repo/album_images.go new file mode 100644 index 0000000000000000000000000000000000000000..9cfdbc590d692dfc189615c018495a2cb7375e56 --- /dev/null +++ b/repo/album_images.go @@ -0,0 +1,142 @@ +package repo + +import ( + "git.kuschku.de/justjanne/imghost-frontend/model" + "github.com/jmoiron/sqlx" +) + +type AlbumImages struct { + db *sqlx.DB + queryList *sqlx.NamedStmt + queryGet *sqlx.NamedStmt + stmtCreate *sqlx.NamedStmt + stmtUpdate *sqlx.NamedStmt + stmtDelete *sqlx.NamedStmt + stmtDeleteAll *sqlx.NamedStmt + stmtReorder *sqlx.NamedStmt +} + +func NewAlbumImageRepo(db *sqlx.DB) (repo AlbumImages, err error) { + repo.db = db + repo.queryList, err = db.PrepareNamed(` + SELECT album_images.album, + album_images.image, + album_images.title, + album_images.description + FROM album_images + WHERE album_images.album = :albumId + ORDER BY album_images.position + `) + repo.queryGet, err = db.PrepareNamed(` + SELECT album_images.album, + album_images.image, + album_images.title, + album_images.description + FROM album_images + WHERE album_images.album = :albumId + AND album_images.image = :imageId + ORDER BY album_images.position + `) + repo.stmtCreate, err = db.PrepareNamed(` + INSERT INTO album_images (album, image, title, description, position) + VALUES (:albumId, :imageId, :title, :description, ( + SELECT COUNT(album_images.image) + FROM album_images + WHERE album_images.album = :albumId + )) + `) + repo.stmtUpdate, err = db.PrepareNamed(` + UPDATE album_images + SET album_images.title = :title, + album_images.description = :description + WHERE album_images.album = :albumId + AND album_images.image = :imageId + `) + repo.stmtDelete, err = db.PrepareNamed(` + DELETE FROM album_images + WHERE album_images.album = :albumId + AND album_images.image = :imageID + `) + repo.stmtDeleteAll, err = db.PrepareNamed(` + DELETE FROM album_images + WHERE album_images.album = :albumId + `) + repo.stmtReorder, err = db.PrepareNamed(` + UPDATE album_images + SET album_images.position = :position + WHERE album_images.album = :albumId + AND album_images.image = :imageId + `) + + return repo, nil +} + +func (repo AlbumImages) List(album model.Album) (images []model.AlbumImage, err error) { + rows, err := repo.queryList.Queryx(map[string]interface{}{ + "albumId": album.Id, + }) + if err != nil { + return + } + for rows.Next() { + var image model.AlbumImage + err = rows.StructScan(&image) + if err != nil { + return + } + images = append(images, image) + } + return +} + +func (repo AlbumImages) Get(album model.Album, imageId string) (image model.AlbumImage, err error) { + err = repo.queryGet.Get(&image, map[string]interface{}{ + "albumId": album.Id, + "imageId": imageId, + }) + return +} + +func (repo AlbumImages) Create(new model.AlbumImage) (err error) { + _, err = repo.stmtCreate.Exec(map[string]interface{}{ + "albumId": new.Album, + "imageId": new.Image, + "title": new.Title, + "description": new.Description, + }) + return +} + +func (repo AlbumImages) Update(changed model.AlbumImage) (err error) { + _, err = repo.stmtUpdate.Exec(map[string]interface{}{ + "albumId": changed.Album, + "imageId": changed.Image, + "title": changed.Title, + "description": changed.Description, + }) + return +} + +func (repo AlbumImages) Delete(changed model.AlbumImage) (err error) { + _, err = repo.stmtDelete.Exec(map[string]interface{}{ + "albumId": changed.Album, + "imageId": changed.Image, + }) + return +} + +func (repo AlbumImages) DeleteAll(changed model.AlbumImage) (err error) { + _, err = repo.stmtDeleteAll.Exec(map[string]interface{}{ + "albumId": changed.Album, + }) + return +} + +func (repo AlbumImages) Reorder(changed model.AlbumImage, position int) (err error) { + _, err = repo.stmtDeleteAll.Exec(map[string]interface{}{ + "albumId": changed.Album, + "imageId": changed.Image, + "position": position, + }) + return +} diff --git a/repo/albums.go b/repo/albums.go new file mode 100644 index 0000000000000000000000000000000000000000..6be98f1c4f65fbd0f64ac4d726e0f0f25ae33923 --- /dev/null +++ b/repo/albums.go @@ -0,0 +1,108 @@ +package repo + +import ( + "git.kuschku.de/justjanne/imghost-frontend/model" + "github.com/jmoiron/sqlx" +) + +type Albums struct { + db *sqlx.DB + queryList *sqlx.NamedStmt + queryGet *sqlx.NamedStmt + stmtUpdate *sqlx.NamedStmt + stmtCreate *sqlx.NamedStmt + stmtDelete *sqlx.NamedStmt +} + +func NewAlbumRepo(db *sqlx.DB) (repo Albums, err error) { + repo.db = db + repo.queryList, err = db.PrepareNamed(` + SELECT albums.id, + albums.owner, + albums.title, + albums.description, + albums.created_at, + albums.updated_at + FROM albums + WHERE albums.owner = :userId + ORDER BY albums.created_at DESC + `) + repo.queryGet, err = db.PrepareNamed(` + SELECT albums.id, + albums.owner, + albums.title, + albums.description, + albums.created_at, + albums.updated_at + FROM albums + WHERE albums.id = :albumId + `) + repo.stmtCreate, err = db.PrepareNamed(` + INSERT INTO albums (id, owner, title, description, created_at, updated_at) + VALUES (:albumId, :userId, :title, :description, NOW(), NOW()) + `) + repo.stmtUpdate, err = db.PrepareNamed(` + UPDATE albums + SET albums.title = :title, + albums.description = :description, + albums.updated_at = NOW() + WHERE albums.id = :albumId + `) + repo.stmtDelete, err = db.PrepareNamed(` + DELETE FROM albums + WHERE albums.id = :albums + `) + + return repo, nil +} + +func (repo Albums) List(user model.User) (albums []model.Album, err error) { + rows, err := repo.queryList.Queryx(map[string]interface{}{ + "userId": user.Id, + }) + if err != nil { + return + } + for rows.Next() { + var album model.Album + err = rows.StructScan(&album) + if err != nil { + return + } + albums = append(albums, album) + } + return +} + +func (repo Albums) Get(albumId string) (album model.Album, err error) { + err = repo.queryGet.Get(&album, map[string]interface{}{ + "albumId": albumId, + }) + return +} + +func (repo Albums) Create(changed model.Album) (err error) { + _, err = repo.stmtCreate.Exec(map[string]interface{}{ + "albumId": changed.Id, + "userId": changed.Owner, + "title": changed.Title, + "description": changed.Description, + }) + return +} + +func (repo Albums) Update(changed model.Album) (err error) { + _, err = repo.stmtUpdate.Exec(map[string]interface{}{ + "albumId": changed.Id, + "title": changed.Title, + "description": changed.Description, + }) + return +} + +func (repo Albums) Delete(changed model.Album) (err error) { + _, err = repo.stmtDelete.Exec(map[string]interface{}{ + "albumId": changed.Id, + }) + return +} diff --git a/repo/images.go b/repo/images.go new file mode 100644 index 0000000000000000000000000000000000000000..a29c01bf08b4b45d1b35aa709b4349097c1cca55 --- /dev/null +++ b/repo/images.go @@ -0,0 +1,112 @@ +package repo + +import ( + "git.kuschku.de/justjanne/imghost-frontend/model" + "github.com/jmoiron/sqlx" +) + +type Images struct { + db *sqlx.DB + queryList *sqlx.NamedStmt + queryGet *sqlx.NamedStmt + stmtCreate *sqlx.NamedStmt + stmtUpdate *sqlx.NamedStmt + stmtDelete *sqlx.NamedStmt +} + +func NewImageRepo(db *sqlx.DB) (repo Images, err error) { + repo.db = db + repo.queryList, err = db.PrepareNamed(` + SELECT images.id, + images.owner, + images.title, + images.description, + images.original_name, + images.created_at, + images.updated_at + FROM images + WHERE images.owner = :userId + ORDER BY images.created_at DESC + `) + repo.queryGet, err = db.PrepareNamed(` + SELECT images.id, + images.owner, + images.title, + images.description, + images.original_name, + images.created_at, + images.updated_at + FROM images + WHERE images.id = :imageId + `) + repo.stmtCreate, err = db.PrepareNamed(` + INSERT INTO images (id, owner, title, description, original_name, type, created_at, updated_at) + VALUES (:imageId, :userId, :title, :description, :originalName, :mimeType, NOW(), NOW()) + `) + repo.stmtUpdate, err = db.PrepareNamed(` + UPDATE images + SET images.title = :title, + images.description = :description, + images.updated_at = NOW() + WHERE images.id = :imageId + `) + repo.stmtDelete, err = db.PrepareNamed(` + DELETE FROM images + WHERE images.id = :imageId + `) + + return repo, nil +} + +func (repo Images) List(user model.User) (images []model.Image, err error) { + rows, err := repo.queryList.Queryx(map[string]interface{}{ + "userId": user.Id, + }) + if err != nil { + return + } + for rows.Next() { + var image model.Image + err = rows.StructScan(&image) + if err != nil { + return + } + images = append(images, image) + } + return +} + +func (repo Images) Get(imageId string) (image model.Image, err error) { + err = repo.queryGet.Get(&image, map[string]interface{}{ + "imageId": imageId, + }) + return +} + +func (repo Images) Create(new model.Image) (err error) { + _, err = repo.stmtUpdate.Exec(map[string]interface{}{ + "imageId": new.Id, + "userId": new.Owner, + "title": new.Title, + "description": new.Description, + "originalName": new.OriginalName, + "mimeType": new.MimeType, + }) + return +} + +func (repo Images) Update(changed model.Image) (err error) { + _, err = repo.stmtUpdate.Exec(map[string]interface{}{ + "imageId": changed.Id, + "title": changed.Title, + "description": changed.Description, + }) + return +} + +func (repo Images) Delete(changed model.Image) (err error) { + _, err = repo.stmtDelete.Exec(map[string]interface{}{ + "imageId": changed.Id, + }) + return +} diff --git a/task/image_resize.go b/task/image_resize.go new file mode 100644 index 0000000000000000000000000000000000000000..1e140b2e4adb49d78fb2a655774fb70651f3f2b2 --- /dev/null +++ b/task/image_resize.go @@ -0,0 +1,68 @@ +package task + +import ( + "context" + "encoding/json" + "git.kuschku.de/justjanne/imghost-frontend/util" + "github.com/hibiken/asynq" + "github.com/justjanne/imgconv" + "gopkg.in/gographics/imagick.v2/imagick" +) + +const TypeImageResize = "image:Resize" + +type ImageResizePayload struct { + ImageId string + Sizes []imgconv.Size + Quality imgconv.Quality +} + +func NewResizeTask(imageId string, sizes []imgconv.Size, quality imgconv.Quality) (task *asynq.Task, err error) { + payload, err := json.Marshal(ImageResizePayload{ + ImageId: imageId, + Sizes: sizes, + Quality: quality, + }) + if err != nil { + return + } + task = asynq.NewTask(TypeImageResize, payload) + return +} + +func HandleImageResizeTask(ctx context.Context, task *asynq.Task) (err error) { + var payload ImageResizePayload + if err = json.Unmarshal(task.Payload(), &payload); err != nil { + return + } + + wand := imagick.NewMagickWand() + defer wand.Destroy() + + tmpFile := "" + if err = wand.ReadImage(tmpFile); err != nil { + return + } + var originalImage imgconv.ImageHandle + if originalImage, err = imgconv.NewImage(wand); err != nil { + return err + } + + err = util.LaunchGoroutines(len(payload.Sizes), func(index int) error { + size := payload.Sizes[index] + tmpTargetFile := "" + image := originalImage.CloneImage() + if err := image.Crop(size); err != nil { + return err + } + if err := image.Resize(size); err != nil { + return err + } + if err := image.Write(payload.Quality, tmpTargetFile); err != nil { + return err + } + return nil + }) + + return +} diff --git a/util/goroutine_launch.go b/util/goroutine_launch.go new file mode 100644 index 0000000000000000000000000000000000000000..d8ea8f5365dab110bd7a89bb0b00aa12fe690f1a --- /dev/null +++ b/util/goroutine_launch.go @@ -0,0 +1,29 @@ +package util + +func readAllErrors(amount int, errorChannel chan error) []error { + errors := make([]error, 0) + for i := 0; i < amount; i++ { + err := <-errorChannel + if err != nil { + errors = append(errors, err) + } + } + + return errors +} + +func LaunchGoroutines(amount int, function func(index int) error) error { + errorChannel := make(chan error) + for i := 0; i < amount; i++ { + index := i + go func() { errorChannel <- function(index) }() + } + errs := readAllErrors(amount, errorChannel) + for _, err := range errs { + if err != nil { + return err + } + } + + return nil +} diff --git a/util/method_override.go b/util/method_override.go new file mode 100644 index 0000000000000000000000000000000000000000..35a3d9274274f069bb76b95810008aae4bd3c4bb --- /dev/null +++ b/util/method_override.go @@ -0,0 +1,21 @@ +package util + +import "net/http" + +func MethodOverride(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method == http.MethodPost { + method := r.PostFormValue("_method") + if method == "" { + method = r.Header.Get("X-HTTP-Method-Override") + } + + if method == http.MethodPut || + method == http.MethodPatch || + method == http.MethodDelete { + r.Method = method + } + } + next.ServeHTTP(w, r) + }) +}