diff --git a/app/app.go b/app/app.go index fea6b53..0130f48 100644 --- a/app/app.go +++ b/app/app.go @@ -4,6 +4,8 @@ import ( "context" "errors" "fmt" + "github.com/go-redis/redis/v8" + "heruvym/dal/minio" "heruvym/dal/mongo" "heruvym/middleware" "heruvym/router" @@ -43,6 +45,9 @@ type Options struct { MongoCollections string `env:"COLLECTION_NAME" default:"profile,role"` TgToken string `env:"TELEGRAM_TOKEN" default:"5851043588:AAGXhigZAaNV1--n-jfS8eBgM7iZ2IDm668"` TgChatID int64 `env:"TELEGRAM_CHAT_ID" default:"-1001344671794"` + RedisHost string `env:"REDIS_HOST" default:"localhost:6379"` + RedisPassword string `env:"REDIS_PASSWORD" default:""` + RedisDB uint64 `env:"REDIS_DB" default:"0"` } var ( @@ -114,6 +119,18 @@ func New(ctx context.Context, opts interface{}, ver appInit.Version) (appInit.Co return nil, err } + miniostore, err := minio.New(ctx, logger, options.MinioEndpoint, options.MinioSecretKey, options.MinioAccessKey, options.MinioToken, options.MinioRegion, false) + if err != nil { + fmt.Println(err) + return nil, err + } + + redisClient := redis.NewClient(&redis.Options{ + Addr: options.RedisHost, + Password: options.RedisPassword, + DB: int(options.RedisDB), + }) + var newBot *tb.Bot newBot, err = tb.NewBot(tb.Settings{ Token: options.TgToken, @@ -128,7 +145,7 @@ func New(ctx context.Context, opts interface{}, ver appInit.Version) (appInit.Co return nil, err } - heruvym := service.New(nil, database, logger, newBot, options.TgChatID) + heruvym := service.New(miniostore, database, logger, newBot, options.TgChatID, redisClient) mux := router.NewRouter(map[string]http.HandlerFunc{ "/create": heruvym.CreateTicket, diff --git a/dal/minio/minio.go b/dal/minio/minio.go index 562e50b..720eb73 100644 --- a/dal/minio/minio.go +++ b/dal/minio/minio.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "io" + "net/http" "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" @@ -30,7 +31,7 @@ func New(ctx context.Context, logger hlog.Logger, if err != nil { return nil, err } - fmt.Println("monio", keyID,accessKey,token,region) + fmt.Println("monio", keyID, accessKey, token, region) bucketExists, err := conn.BucketExists(ctx, bucket) if err != nil { @@ -76,9 +77,10 @@ func (bs *BlobStore) PutFile( //Internal: minio.AdvancedPutOptions{}, }) if err != nil { + fmt.Println(err) return err } - fmt.Println(info) + fmt.Println("info", info) return nil } @@ -94,3 +96,14 @@ func (bs *BlobStore) DeleteFile(ctx context.Context, id string) error { return nil } + +func (bs *BlobStore) FileExists(ctx context.Context, filename string) (bool, error) { + _, err := bs.store.StatObject(ctx, bucket, filename, minio.StatObjectOptions{}) + if err != nil { + if minio.ToErrorResponse(err).StatusCode == http.StatusNotFound { + return false, nil + } + return false, err + } + return true, nil +} diff --git a/dal/mongo/dal.go b/dal/mongo/dal.go index de07983..c9ac63d 100644 --- a/dal/mongo/dal.go +++ b/dal/mongo/dal.go @@ -372,7 +372,7 @@ func (d *DAL) WatchTickets( for cs.Next(ctx) { var ( - piece model.Ticket + piece model.Ticket change Change ) if err := cs.Decode(&change); err != nil { @@ -443,6 +443,7 @@ func (d *DAL) YieldUserTickets(ctx context.Context, userID string, limit, offset query := bson.M{ "UserID": userID, } + fmt.Println("UserID", userID) sort := bson.D{{"State", -1}, {"UpdatedAt", -1}} @@ -489,7 +490,7 @@ func (d *DAL) WatchAllTickets(ctx context.Context, yield func(ticket model.Ticke for cs.Next(ctx) { var ( - piece model.Ticket + piece model.Ticket change Change ) @@ -624,10 +625,10 @@ func (d *DAL) WatchMessages( for cs.Next(ctx) { var ( - piece model.Message + piece model.Message change Change ) - + if err := cs.Decode(&change); err != nil { return err } diff --git a/deployments/test/docker-compose.yaml b/deployments/test/docker-compose.yaml new file mode 100644 index 0000000..7f7332f --- /dev/null +++ b/deployments/test/docker-compose.yaml @@ -0,0 +1,36 @@ +version: '3.8' + +services: + mongo: + image: mongo:latest + container_name: mongo + ports: + - "27017:27017" + + minio: + image: minio/minio + ports: + - "9000:9000" + - "9001:9001" + volumes: + - minio_storage:/data + environment: + MINIO_ROOT_USER: minioadmin + MINIO_ROOT_PASSWORD: minioadmin + command: server --console-address ":9001" /data + + redis: + image: redis:latest + ports: + - "6379:6379" + environment: + - REDIS_PASSWORD=admin + - REDIS_DB=1 + command: [ "redis-server", "--requirepass", "admin", "--databases", "16", "--maxmemory", "2gb", "--maxmemory-policy", "allkeys-lru" ] + volumes: + - redis_data:/data + + +volumes: + minio_storage: + redis_data: \ No newline at end of file diff --git a/go.mod b/go.mod index ede9df5..26d43cb 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.16 require ( github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/go-playground/validator/v10 v10.13.0 + github.com/go-redis/redis/v8 v8.11.5 // indirect github.com/gofiber/contrib/fiberzap v1.0.2 github.com/gofiber/fiber/v2 v2.45.0 github.com/golang/snappy v0.0.4 // indirect diff --git a/go.sum b/go.sum index 1559adb..70c620e 100644 --- a/go.sum +++ b/go.sum @@ -5,15 +5,24 @@ github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHG github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 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/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-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= 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/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -22,22 +31,41 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.13.0 h1:cFRQdfaSMCOSfGCCLB20MHvuoHb/s5G8L5pu2ppK5AQ= github.com/go-playground/validator/v10 v10.13.0/go.mod h1:dwu7+CG8/CtBiJFZDz4e+5Upb6OLw04gtBYw0mcG/z4= +github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= +github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gofiber/contrib/fiberzap v1.0.2 h1:EQwhggtszVfIdBeXxN9Xrmld71es34Ufs+ef8VMqZxc= github.com/gofiber/contrib/fiberzap v1.0.2/go.mod h1:jGO8BHU4gRI9U0JtM6zj2CIhYfgVmW5JxziN8NTgVwE= github.com/gofiber/fiber/v2 v2.42.0/go.mod h1:3+SGNjqMh5VQH5Vz2Wdi43zTIV16ktlFd3x3R6O1Zlc= github.com/gofiber/fiber/v2 v2.45.0 h1:p4RpkJT9GAW6parBSbcNFH2ApnAuW3OzaQzbOCoDu+s= github.com/gofiber/fiber/v2 v2.45.0/go.mod h1:DNl0/c37WLe0g92U6lx1VMQuxGUQY5V7EIaVoEsUffc= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +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.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= @@ -82,6 +110,17 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/montanaflynn/stats v0.6.6 h1:Duep6KMIDpY4Yo11iFsvyqJDyfzLF9+sndUKT+v64GQ= github.com/montanaflynn/stats v0.6.6/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= @@ -180,12 +219,15 @@ golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= @@ -193,23 +235,32 @@ golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +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-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -242,6 +293,7 @@ golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= @@ -251,16 +303,29 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.66.6/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/tucnak/telebot.v2 v2.5.0 h1:i+NynLo443Vp+Zn3Gv9JBjh3Z/PaiKAQwcnhNI7y6Po= gopkg.in/tucnak/telebot.v2 v2.5.0/go.mod h1:BgaIIx50PSRS9pG59JH+geT82cfvoJU/IaI5TJdN3v8= 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.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/openapi.yaml b/openapi.yaml index 556c5b1..8dfa786 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -219,10 +219,18 @@ paths: message: type: string example: "4518u035u13fjopq0" + '208': + $ref: "#/components/responses/AlreadyReported" '400': $ref: "#/components/responses/BadRequest" '401': $ref: "#/components/responses/Unauthorized" + '413': + $ref: "#/components/responses/RequestEntityTooLarge" + '406': + $ref: '#/components/responses/NotAcceptable' + '429': + $ref: '#/components/responses/TooManyRequests' '500': $ref: "#/components/responses/ErrorOccurred" /sendSC: @@ -1845,6 +1853,34 @@ components: schema: type: string example: "flushing is not allowed" + RequestEntityTooLarge: + description: RequestEntityTooLarge + content: + text/plain: + schema: + type: string + example: "File too large" + NotAcceptable: + description: NotAcceptable + content: + text/plain: + schema: + type: string + example: "Unsupported Media Type" + TooManyRequests: + description: TooManyRequests + content: + text/plain: + schema: + type: string + example: "file upload limit exceeded" + AlreadyReported: + description: AlreadyReported + content: + text/plain: + schema: + type: string + example: "file already exists" schemas: Ticket: type: object diff --git a/service/service.go b/service/service.go index eb791e5..7432d0d 100644 --- a/service/service.go +++ b/service/service.go @@ -2,18 +2,24 @@ package service import ( "context" + "crypto/sha256" + "encoding/hex" "encoding/json" "errors" "fmt" + "github.com/go-redis/redis/v8" "heruvym/dal/minio" "heruvym/dal/mongo" "heruvym/jwt_adapter" "heruvym/middleware" "heruvym/model" "heruvym/tools" + "heruvym/utils" + "io" "net/http" "strings" "sync" + "time" "github.com/rs/xid" "github.com/themakers/hlog" @@ -25,8 +31,9 @@ type Heruvym struct { dal *mongo.DAL bs *minio.BlobStore - notifier *tb.Bot - tgChatID int64 + notifier *tb.Bot + tgChatID int64 + redisClient *redis.Client } func New( @@ -34,13 +41,14 @@ func New( dataAccessLayer *mongo.DAL, log hlog.Logger, notifier *tb.Bot, - tgChatID int64) *Heruvym { + tgChatID int64, redisClient *redis.Client) *Heruvym { return &Heruvym{ - logger: log.Module("Service"), - dal: dataAccessLayer, - bs: blobs, - notifier: notifier, - tgChatID: tgChatID, + logger: log.Module("Service"), + dal: dataAccessLayer, + bs: blobs, + notifier: notifier, + tgChatID: tgChatID, + redisClient: redisClient, } } @@ -173,13 +181,14 @@ func (h *Heruvym) CreateTicket(w http.ResponseWriter, r *http.Request) { var _ tools.DataEmitter = (&Heruvym{}).GetList func (h *Heruvym) GetList(ctx context.Context) chan interface{} { + fmt.Println("GetList") defer func() { if rec := recover(); rec != nil { fmt.Println(rec) } }() sess := jwt_adapter.Get(ctx) - + fmt.Println("sess", sess) if sess == nil { return nil } @@ -305,7 +314,7 @@ func (h *Heruvym) PutMessage( request.TicketID, []string{}, ) - fmt.Println("PUTMES00", err) + fmt.Println("PUTMES00", err) if err != nil { fmt.Println("PUTMES1", err) return errors.New("can not put message"), http.StatusInternalServerError @@ -356,7 +365,7 @@ func (h *Heruvym) PutMessage( //return errors.New("can not update ticket"), http.StatusInternalServerError } - fmt.Println("PUTMES03" ) + fmt.Println("PUTMES03") return nil, http.StatusOK } @@ -658,6 +667,12 @@ const ( MB = 1 << 20 ) +var fileTypeLimits = map[string]int64{ + "image": 5 * MB, + "video": 50 * MB, + "document": 10 * MB, +} + type PutFileReq struct { Ticket string `json:"ticket"` } @@ -669,6 +684,34 @@ type PutFileResp struct { func (h *Heruvym) PutFile(w http.ResponseWriter, r *http.Request) { defer r.Body.Close() + sess := jwt_adapter.Get(r.Context()) + if sess == nil { + w.WriteHeader(http.StatusBadRequest) + if _, err := w.Write([]byte("not authorized")); err != nil { + fmt.Println("CAN NOT WRITE", err) + } + return + } + + TimeKey := fmt.Sprintf("sendLockHeruvym:%s", sess.Id) + isNewKey, err := h.redisClient.SetNX(r.Context(), TimeKey, time.Now().Unix(), 5*time.Minute).Result() + if err != nil { + fmt.Println("failed check last upload time in Redis:", err) + w.WriteHeader(http.StatusInternalServerError) + if _, err := w.Write([]byte("internal server error")); err != nil { + fmt.Println("CAN NOT WRITE", err) + } + return + } + + if !isNewKey { + w.WriteHeader(http.StatusTooManyRequests) + if _, err := w.Write([]byte("file upload limit exceeded")); err != nil { + fmt.Println("CAN NOT WRITE", err) + } + return + } + if err := r.ParseMultipartForm(10 * MB); err != nil { w.WriteHeader(http.StatusBadRequest) if _, err := w.Write([]byte("can not parse multipart " + err.Error())); err != nil { @@ -693,6 +736,29 @@ func (h *Heruvym) PutFile(w http.ResponseWriter, r *http.Request) { return } + for _, files := range r.MultipartForm.File { + for _, fileHeader := range files { + fileSize := fileHeader.Size + fileType := utils.GetFileType(fileHeader.Filename) + + if limit, ok := fileTypeLimits[fileType]; ok { + if fileSize > limit { + w.WriteHeader(http.StatusRequestEntityTooLarge) + if _, err := w.Write([]byte(fileType + " file size exceeds the limit")); err != nil { + fmt.Println("CAN NOT WRITE", err) + } + return + } + } else { + w.WriteHeader(http.StatusNotAcceptable) + if _, err := w.Write([]byte("Unsupported file type")); err != nil { + fmt.Println("CAN NOT WRITE", err) + } + return + } + } + } + filesCount := len(r.MultipartForm.File) if filesCount == 0 { @@ -703,15 +769,6 @@ func (h *Heruvym) PutFile(w http.ResponseWriter, r *http.Request) { return } - sess := jwt_adapter.Get(r.Context()) - if sess == nil { - w.WriteHeader(http.StatusBadRequest) - if _, err := w.Write([]byte("not authorized")); err != nil { - fmt.Println("CAN NOT WRITE", err) - } - return - } - var req PutFileReq req.Ticket = r.MultipartForm.Value["ticket"][0] @@ -734,14 +791,57 @@ func (h *Heruvym) PutFile(w http.ResponseWriter, r *http.Request) { fmt.Println("can not open ", err.Error()) } + hash := sha256.New() + if _, err := io.Copy(hash, freader); err != nil { + fmt.Println("error calculating file hash: ", err) + errFile = err + } + + _, err = freader.Seek(0, 0) + if err != nil { + fmt.Println("error seeking back to the beginning of the file: ", err) + errFile = err + } + + hashInBytes := hash.Sum(nil) + fileHash := hex.EncodeToString(hashInBytes) + splitted := strings.Split(name, ".") + filename := fmt.Sprintf("%s_%s.%s", fileHash, sess.Id, splitted[len(splitted)-1]) + defer func() { if err := freader.Close(); err != nil { errFile = err } }() - splitted := strings.Split(name, ".") - filename := fmt.Sprintf("%s.%s", xid.New().String(), splitted[len(splitted)-1]) + exists, err := h.bs.FileExists(r.Context(), filename) + if err != nil { + errFile = err + return + } + + if exists { + response := struct { + File string `json:"file"` + }{ + File: filename, + } + + resp, err := json.Marshal(response) + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + if _, err := w.Write([]byte("error marshaling response: " + err.Error())); err != nil { + fmt.Println("CAN NOT WRITE", err) + } + return + } + + w.WriteHeader(http.StatusAlreadyReported) + if _, err := w.Write(resp); err != nil { + fmt.Println("CAN NOT WRITE", err) + } + return + } if err := h.bs.PutFile( r.Context(), diff --git a/test/main_test.go b/test/main_test.go index 50ab784..638d53f 100644 --- a/test/main_test.go +++ b/test/main_test.go @@ -7,6 +7,8 @@ import ( "encoding/json" "errors" "fmt" + "github.com/skeris/appInit" + "heruvym/model" "io" "io/ioutil" "mime/multipart" @@ -17,45 +19,59 @@ import ( "time" "heruvym/app" - "heruvym/model" "heruvym/service" "github.com/stretchr/testify/assert" "github.com/themakers/bdd" + "heruvym/jwt_adapter" ) +///create+ +///subscribe todo +///ticket+ +///send+ +///sendFile+ +///getTickets+ +///getMessages+ + func TestTicket(t *testing.T) { fmt.Println("start test") ctx, cancel := context.WithCancel(context.Background()) defer cancel() bdd.Scenario(t, "SupportChat", func(t *testing.T, runID string) { + var ticket service.CreateTicketResp + var msgs = make(chan []byte) + var token string go func() { time.Sleep(3 * time.Second) fmt.Println("start service") _, err := app.New(ctx, app.Options{ - MongoURI: "mongodb://mongo:27017", + MongoURI: "mongodb://localhost:27017", NumberPortLocal: "1488", + AccountAddress: ":8931", LoggerDevMode: false, - MinioEndpoint: "minio:9000", + MinioEndpoint: "localhost:9000", MinioAccessKey: "minioadmin", MinioSecretKey: "minioadmin", + MinioRegion: "", + MinioToken: "", MongoDbTable: "profile", MongoCollections: "profile,role", - }) + TgToken: "6712573453:AAFddRtlsF4ZH977xZDexWj6DhqeJD66hYw", + TgChatID: 542073142, + RedisDB: 1, + RedisPassword: "admin", + RedisHost: "localhost:6379", + }, appInit.Version{}) if err != nil { panic(err) } }() - time.Sleep(time.Second * 5) + time.Sleep(time.Second * 15) bdd.Act(t, "client", func() { fmt.Println("client") - var ( - token string - ticket service.CreateTicketResp - msgs = make(chan []byte) - ) bdd.Test(t, "CreateTicket", func() { buf, err := json.Marshal(service.CreateTicketReq{ @@ -68,12 +84,13 @@ func TestTicket(t *testing.T) { req, err := http.NewRequestWithContext( ctx, "POST", - "http://localhost:1488/support/create", bytes.NewBuffer(buf)) + "http://localhost:1488/create", bytes.NewBuffer(buf)) if err != nil { panic(err) } - req.Header.Add(jwt_adapter.DefaultHeaderKey, "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJJRCI6ImMxcDM0YjhqZHBmOG04Zm43cnIwIiwiU2Vzc2lvbiI6ImMxcDM0YjhqZHBmOG04Zm43cnJnIiwiVXNlciI6IiIsIlRhcmlmZiI6MCwiQ3JlYXRlZCI6MTYxODA5NjY4NTc4MCwiTGFzdFNlZW4iOjE2MTgwOTY2ODU3ODF9.ciJoJiOxzIPv0LY4h3rG8Tf3AsSBXXLcYEpyN9mIki0") + req.Header.Add(jwt_adapter.DefaultHeaderKey, "Bearer "+token) + req.Header.Set("Referer", "http://localhost:1488") resp, err := http.DefaultClient.Do(req) @@ -86,15 +103,16 @@ func TestTicket(t *testing.T) { } token = resp.Header.Get(jwt_adapter.DefaultHeaderKey) + fmt.Println("token", token) assert.NoError(t, json.NewDecoder(resp.Body).Decode(&ticket)) }) bdd.Test(t, "subscribe for tiket", func() { client := &http.Client{} - r, err := http.NewRequest("GET", "http://localhost:1488/support/ticket?Authorization="+token+"&ticket="+ticket.Ticket, nil) + r, err := http.NewRequest("GET", "http://localhost:1488/ticket?Authorization="+token+"&ticket="+ticket.Ticket, nil) assert.NoError(t, err) - + r.Header.Set("Referer", "http://localhost:1488") r.Header.Set("Accept", "text/event-stream") r.Header.Set("Cache-Control", "no-cache") r.Header.Set("Connection", "keep-alive") @@ -159,37 +177,88 @@ func TestTicket(t *testing.T) { panic(err) } - req, err := http.NewRequestWithContext(ctx, http.MethodPost, "http://localhost:1488/support/send", bytes.NewBuffer(buf)) + req, err := http.NewRequestWithContext(ctx, http.MethodPost, "http://localhost:1488/send", bytes.NewBuffer(buf)) assert.NoError(t, err) - - req.Header.Add(jwt_adapter.DefaultHeaderKey, token) + req.Header.Set("Referer", "http://localhost:1488") + req.Header.Add(jwt_adapter.DefaultHeaderKey, "Bearer "+token) + fmt.Println("token", token) resp, err := http.DefaultClient.Do(req) + fmt.Println("resp", resp) assert.NoError(t, err) assert.Equal(t, http.StatusOK, resp.StatusCode) - var msg, channed model.Message - assert.NoError(t, json.NewDecoder(resp.Body).Decode(&msg)) - err = json.Unmarshal(<-msgs, &channed) - assert.NoError(t, err) - assert.Equal(t, "test", channed.Message) + //var msg, channed model.Message + //assert.NoError(t, json.NewDecoder(resp.Body).Decode(&msg)) + //err = json.Unmarshal(<-msgs, &channed) + //assert.NoError(t, err) + //assert.Equal(t, "test", channed.Message) }) - bdd.Test(t, "send file", func() { + bdd.Test(t, "send file passed", func() { body := &bytes.Buffer{} writer := multipart.NewWriter(body) - partf, _ := writer.CreateFormFile("f.go", "f.go") - f, err := os.OpenFile("./main_test.go", os.O_RDWR, 0644) + partf, _ := writer.CreateFormFile("image.jpg", "image.jpg") + f, err := os.OpenFile("./testfiles/image.jpg", os.O_RDWR, 0644) assert.NoError(t, err) + defer f.Close() + io.Copy(partf, f) + + partf, _ = writer.CreateFormFile("image2.png", "image2.png") + f, err = os.OpenFile("./testfiles/image2.png", os.O_RDWR, 0644) + assert.NoError(t, err) + defer f.Close() + io.Copy(partf, f) + + partf, _ = writer.CreateFormFile("gtaV.mp4", "gtaV.mp4") + f, err = os.OpenFile("./testfiles/gtaV.mp4", os.O_RDWR, 0644) + assert.NoError(t, err) + defer f.Close() + io.Copy(partf, f) + + partf, _ = writer.CreateFormFile("test.csv", "test.csv") + f, err = os.OpenFile("./testfiles/test.csv", os.O_RDWR, 0644) + assert.NoError(t, err) + defer f.Close() + io.Copy(partf, f) + + partf, _ = writer.CreateFormFile("test.doc", "test.doc") + f, err = os.OpenFile("./testfiles/test.doc", os.O_RDWR, 0644) + assert.NoError(t, err) + defer f.Close() + io.Copy(partf, f) + + partf, _ = writer.CreateFormFile("test.docx", "test.docx") + f, err = os.OpenFile("./testfiles/test.docx", os.O_RDWR, 0644) + assert.NoError(t, err) + defer f.Close() + io.Copy(partf, f) + + partf, _ = writer.CreateFormFile("test.pdf", "test.pdf") + f, err = os.OpenFile("./testfiles/test.pdf", os.O_RDWR, 0644) + assert.NoError(t, err) + defer f.Close() + io.Copy(partf, f) + + partf, _ = writer.CreateFormFile("test.txt", "test.txt") + f, err = os.OpenFile("./testfiles/test.txt", os.O_RDWR, 0644) + assert.NoError(t, err) + defer f.Close() + io.Copy(partf, f) + + partf, _ = writer.CreateFormFile("test.xlsx", "test.xlsx") + f, err = os.OpenFile("./testfiles/test.xlsx", os.O_RDWR, 0644) + assert.NoError(t, err) + defer f.Close() io.Copy(partf, f) assert.NoError(t, writer.WriteField("ticket", ticket.Ticket)) writer.Close() - req, err := http.NewRequestWithContext(ctx, http.MethodPost, "http://localhost:1488/support/sendFiles", body) + req, err := http.NewRequestWithContext(ctx, http.MethodPost, "http://localhost:1488/sendFiles", body) req.Header.Set("Content-Type", "multipart/form-data; boundary="+writer.Boundary()) - - req.Header.Add(jwt_adapter.DefaultHeaderKey, token) + req.Header.Set("Referer", "http://localhost:1488") + req.Header.Add(jwt_adapter.DefaultHeaderKey, "Bearer "+token) resp, err := http.DefaultClient.Do(req) assert.NoError(t, err) @@ -198,9 +267,127 @@ func TestTicket(t *testing.T) { str, err := ioutil.ReadAll(resp.Body) fmt.Println("resp files", err, string(str)) }) + bdd.Test(t, "send mp3 file", func() { + body := &bytes.Buffer{} + writer := multipart.NewWriter(body) + + partf, _ := writer.CreateFormFile("audio.mp3", "audio.mp3") + f, err := os.OpenFile("./testfiles/audio.mp3", os.O_RDWR, 0644) + assert.NoError(t, err) + io.Copy(partf, f) + + assert.NoError(t, writer.WriteField("ticket", ticket.Ticket)) + + writer.Close() + req, err := http.NewRequestWithContext(ctx, http.MethodPost, "http://localhost:1488/sendFiles", body) + req.Header.Set("Content-Type", "multipart/form-data; boundary="+writer.Boundary()) + req.Header.Set("Referer", "http://localhost:1488") + req.Header.Add(jwt_adapter.DefaultHeaderKey, "Bearer "+token) + + resp, err := http.DefaultClient.Do(req) + assert.NoError(t, err) + assert.Equal(t, http.StatusNotAcceptable, resp.StatusCode) + + str, err := ioutil.ReadAll(resp.Body) + fmt.Println("resp files", err, string(str)) + }) + bdd.Test(t, "send file big size", func() { + body := &bytes.Buffer{} + writer := multipart.NewWriter(body) + + partf, _ := writer.CreateFormFile("gtaV+size.mp4", "gtaV+size.mp4") + f, err := os.OpenFile("./testfiles/gtaV+size.mp4", os.O_RDWR, 0644) + assert.NoError(t, err) + io.Copy(partf, f) + + assert.NoError(t, writer.WriteField("ticket", ticket.Ticket)) + + writer.Close() + req, err := http.NewRequestWithContext(ctx, http.MethodPost, "http://localhost:1488/sendFiles", body) + req.Header.Set("Content-Type", "multipart/form-data; boundary="+writer.Boundary()) + req.Header.Set("Referer", "http://localhost:1488") + req.Header.Add(jwt_adapter.DefaultHeaderKey, "Bearer "+token) + + resp, err := http.DefaultClient.Do(req) + assert.NoError(t, err) + assert.Equal(t, http.StatusRequestEntityTooLarge, resp.StatusCode) + + str, err := ioutil.ReadAll(resp.Body) + fmt.Println("resp files", err, string(str)) + }) + //todo + bdd.Test(t, "/subscribe, tools.SseWrapper(h.GetList)", func() { + client := &http.Client{} + + r, err := http.NewRequest("GET", "http://localhost:1488/subscribe?Authorization=eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJwZW5hIiwiZXhwIjoxNzA4NjAyNDUxLCJpc3MiOiJwZW5hLWF1dGgtc2VydmljZSIsInN1YiI6InRlc3QifQ.Ipa3ZQt184AyyZFCKAIgU9ijYuvGLQClfyF7cJ74CxzV2NvCMIQU0dImPRwglnY1C3rmhjYxnV_AIHVxxXu-nQ", nil) + assert.NoError(t, err) + r.Header.Set("Referer", "http://localhost:1488") + r.Header.Set("Accept", "text/event-stream") + r.Header.Set("Cache-Control", "no-cache") + r.Header.Set("Connection", "keep-alive") + resp, err := client.Do(r) + assert.NoError(t, err) + + //assert.Equal(t, http.StatusOK, resp.StatusCode) + + sc := bufio.NewScanner(resp.Body) + + fmt.Println(sc.Bytes()) + }) + bdd.Test(t, "/getTickets, tools.HandlerWrapper(h.GetTickets)", func() { + client := &http.Client{} + reqBody := service.GetTicketsReq{ + Amount: 10, + Page: 1, + Search: "test", + Status: "open", + } + reqBytes, err := json.Marshal(reqBody) + assert.NoError(t, err) + + req, err := http.NewRequest("POST", "http://localhost:1488/getTickets", bytes.NewBuffer(reqBytes)) + assert.NoError(t, err) + req.Header.Set("Referer", "sadmin.pena") + req.Header.Add(jwt_adapter.DefaultHeaderKey, "Bearer "+token) + + resp, err := client.Do(req) + + assert.Equal(t, http.StatusOK, resp.StatusCode) + + var respBody service.GetTicketsResp + err = json.NewDecoder(resp.Body).Decode(&respBody) + assert.NoError(t, err) + fmt.Println(respBody) + }) + bdd.Test(t, "/getMessages, tools.HandlerWrapper(h.GetMessages)", func() { + client := &http.Client{} + reqBody := service.GetMessagesReq{ + Amount: 0, + Page: 0, + Search: "test", + TicketID: ticket.Ticket, + } + reqBytes, err := json.Marshal(reqBody) + assert.NoError(t, err) + + req, err := http.NewRequest("POST", "http://localhost:1488/getMessages", bytes.NewBuffer(reqBytes)) + assert.NoError(t, err) + req.Header.Set("Referer", "http://localhost:1488") + req.Header.Add(jwt_adapter.DefaultHeaderKey, "Bearer "+token) + + resp, err := client.Do(req) + + assert.Equal(t, http.StatusOK, resp.StatusCode) + + var respBody []model.Message + err = json.NewDecoder(resp.Body).Decode(&respBody) + assert.NoError(t, err) + fmt.Println(respBody) + }) }) }) } + func containsDoubleNewline(data []byte) (int, int) { // Ищем все возможные переносы строки crcr := bytes.Index(data, []byte("\r\r")) diff --git a/test/testfiles/audio.mp3 b/test/testfiles/audio.mp3 new file mode 100644 index 0000000..e69de29 diff --git a/test/testfiles/image.jpg b/test/testfiles/image.jpg new file mode 100644 index 0000000..25211e1 Binary files /dev/null and b/test/testfiles/image.jpg differ diff --git a/test/testfiles/image2.png b/test/testfiles/image2.png new file mode 100644 index 0000000..4acca14 Binary files /dev/null and b/test/testfiles/image2.png differ diff --git a/test/testfiles/test.csv b/test/testfiles/test.csv new file mode 100644 index 0000000..d800886 --- /dev/null +++ b/test/testfiles/test.csv @@ -0,0 +1 @@ +123 \ No newline at end of file diff --git a/test/testfiles/test.doc b/test/testfiles/test.doc new file mode 100644 index 0000000..e69de29 diff --git a/test/testfiles/test.docx b/test/testfiles/test.docx new file mode 100644 index 0000000..e69de29 diff --git a/test/testfiles/test.pdf b/test/testfiles/test.pdf new file mode 100644 index 0000000..e69de29 diff --git a/test/testfiles/test.txt b/test/testfiles/test.txt new file mode 100644 index 0000000..d800886 --- /dev/null +++ b/test/testfiles/test.txt @@ -0,0 +1 @@ +123 \ No newline at end of file diff --git a/test/testfiles/test.xlsx b/test/testfiles/test.xlsx new file mode 100644 index 0000000..e69de29 diff --git a/tools/tools.go b/tools/tools.go index 13ff9e5..05e4ef3 100644 --- a/tools/tools.go +++ b/tools/tools.go @@ -21,6 +21,7 @@ func SseWrapper(emitter DataEmitter) http.HandlerFunc { } }() // Отправляем header event-stream + fmt.Println("SseWrapper") w.Header().Set("Content-Type", "text/event-stream") w.Header().Set("Cache-Control", "no-cache") @@ -28,6 +29,7 @@ func SseWrapper(emitter DataEmitter) http.HandlerFunc { flusher, ok := w.(http.Flusher) if !ok { + fmt.Println("!ok") http.Error( w, "flushing is not allowed", @@ -35,7 +37,7 @@ func SseWrapper(emitter DataEmitter) http.HandlerFunc { ) return } - + fmt.Println("SseWrapper") ctx := context.WithValue( r.Context(), ContextURLKey, @@ -45,6 +47,7 @@ func SseWrapper(emitter DataEmitter) http.HandlerFunc { dE := emitter(ctx) if dE == nil { + fmt.Println("dE") http.Error(w, "no token", http.StatusUnauthorized) return } @@ -57,7 +60,7 @@ func SseWrapper(emitter DataEmitter) http.HandlerFunc { case <-time.After(time.Second * 10): SSEPing(w) case m := <-dE: - fmt.Println("datatatata", m) + fmt.Println("datatatata", m) if m == nil { continue } diff --git a/utils/utils.go b/utils/utils.go new file mode 100644 index 0000000..f028daf --- /dev/null +++ b/utils/utils.go @@ -0,0 +1,20 @@ +package utils + +import ( + "path/filepath" + "strings" +) + +func GetFileType(filename string) string { + ext := strings.ToLower(filepath.Ext(filename)) + switch ext { + case ".jpg", ".png": + return "image" + case ".mp4": + return "video" + case ".txt", ".doc", ".docx", ".csv", ".xlsx", ".pdf": + return "document" + default: + return "unsupported" + } +}