From eab8e4960dc8ca7d5376a5ce5ebd1d1606d47702 Mon Sep 17 00:00:00 2001 From: Skeris Date: Sun, 27 Feb 2022 18:27:44 +0300 Subject: [PATCH] lil commit --- Dockerfile | 3 + app/app.go | 50 +++++---- dal/minio/minio.go | 2 +- dal/mongo/dal.go | 86 ++++++++++++++-- go.mod | 1 + k8s/deployment.yml | 2 +- middleware/middleware.go | 3 +- model/model.go | 1 + ops/deploy | 4 +- prod.crt | 29 ++++++ prod.key | 28 +++++ server.crt | 21 ++++ server.key | 28 +++++ service/service.go | 217 +++++++++++++++++++++++++++++++++++++-- tools/tools.go | 6 +- 15 files changed, 437 insertions(+), 44 deletions(-) create mode 100644 prod.crt create mode 100644 prod.key create mode 100644 server.crt create mode 100644 server.key diff --git a/Dockerfile b/Dockerfile index 6f20594..5c6741f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,9 @@ FROM alpine ADD heruvym / +COPY prod.crt / +COPY prod.key / ENV APP_ADDR=:1488 +ENV BB_IS_PROD=true ENV BB_MONGO_URI=mongodb://mongodb ENV MINIO_ENDPOINT=minio:9001 RUN apk add --no-cache ca-certificates diff --git a/app/app.go b/app/app.go index 4197acf..4e6e91a 100644 --- a/app/app.go +++ b/app/app.go @@ -38,10 +38,10 @@ type Options struct { MongoURI string `env:"BB_MONGO_URI" default:"mongodb://localhost:27017"` NumberPortLocal string `env:"BB_PORT" default:"1488"` LoggerDevMode bool `env:"BB_IS_PROD" default:"false"` - MinioEndpoint string `env:"BB_MINIO_EP" default:"minio:9001"` - MinioAccessKey string `env:"BB_MINIO_AK" default:"minioadmin"` - MinioSecretKey string `env:"BB_MINIO_SK" default:"minioadmin"` - MinioToken string `env:"BB_MINIO_TOKEN" default:""` + MinioEndpoint string `env:"BB_MINIO_EP" default:"minio:9001"` + MinioAccessKey string `env:"BB_MINIO_AK" default:"minio"` + MinioSecretKey string `env:"BB_MINIO_SK" default:"miniostorage"` + MinioToken string `env:"BB_MINIO_TOKEN" default:""` MongoDbTable string `env:"DATABASE_TABLE" default:"profile"` MongoCollections string `env:"COLLECTION_NAME" default:"profile,role"` } @@ -85,12 +85,12 @@ func New(ctx context.Context, opts interface{}) (appInit.CommonApp, error) { } if options.LoggerDevMode { - zapLogger, err = zap.NewDevelopment(zapOptions...) + zapLogger, err = zap.NewProduction(zapOptions...) if err != nil { return nil, err } } else { - zapLogger, err = zap.NewProduction(zapOptions...) + zapLogger, err = zap.NewDevelopment(zapOptions...) if err != nil { return nil, err } @@ -146,8 +146,9 @@ func New(ctx context.Context, opts interface{}) (appInit.CommonApp, error) { options.MinioAccessKey, options.MinioSecretKey, options.MinioToken, - true) + false) if err != nil { + fmt.Println("MINIO store", err) return nil, err } @@ -157,17 +158,19 @@ func New(ctx context.Context, opts interface{}) (appInit.CommonApp, error) { signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM) mux := router.NewRouter(map[string]http.HandlerFunc{ - "/support/create": heruvym.CreateTicket, - "/support/subscribe": tools.SseWrapper(heruvym.GetList), - "/support/ticket": tools.SseWrapper(heruvym.Subscribe), - "/support/send": tools.HandlerWrapper(heruvym.PutMessage), - "/support/sendFiles": heruvym.PutFile, - "/support/getTickets": tools.HandlerWrapper(heruvym.GetTickets), - "/support/getMessages": tools.HandlerWrapper(heruvym.GetMessages), - "/support/pick": tools.HandlerWrapper(heruvym.Pick), - "/support/delegate": tools.HandlerWrapper(heruvym.Delegate), - "/support/vote": tools.HandlerWrapper(heruvym.Vote), - "/support/close": tools.HandlerWrapper(heruvym.CloseTicket), + "/support/create": heruvym.CreateTicket, + "/support/subscribe": tools.SseWrapper(heruvym.GetList), + "/support/ticket": tools.SseWrapper(heruvym.Subscribe), + "/support/send": tools.HandlerWrapper(heruvym.PutMessage), + "/support/requestScreenshot": tools.HandlerWrapper(heruvym.RequestScreenshot), + "/support/sendFiles": heruvym.PutFile, + "/support/sendSC": heruvym.PutSC, + "/support/getTickets": tools.HandlerWrapper(heruvym.GetTickets), + "/support/getMessages": tools.HandlerWrapper(heruvym.GetMessages), + "/support/pick": tools.HandlerWrapper(heruvym.Pick), + "/support/delegate": tools.HandlerWrapper(heruvym.Delegate), + "/support/vote": tools.HandlerWrapper(heruvym.Vote), + "/support/close": tools.HandlerWrapper(heruvym.CloseTicket), }) mw := middleware.NewMiddleware( @@ -223,7 +226,16 @@ func New(ctx context.Context, opts interface{}) (appInit.CommonApp, error) { }() logger.Emit(InfoSvcStarted{}) - if err := server.ListenAndServe(); err != nil { + tmplKey := "%s.key" + tmplCrt := "%s.crt" + //if !options.LoggerDevMode { + tmplCrt = fmt.Sprintf(tmplCrt, "prod") + tmplKey = fmt.Sprintf(tmplKey, "prod") + //} else { + // tmplCrt = fmt.Sprintf(tmplCrt, "server") + // tmplKey = fmt.Sprintf(tmplKey, "server") + //} + if err := server.ListenAndServeTLS(tmplCrt, tmplKey); err != nil { logger.Emit(ErrorCanNotServe{ Err: err, }) diff --git a/dal/minio/minio.go b/dal/minio/minio.go index 26eabde..9cd0952 100644 --- a/dal/minio/minio.go +++ b/dal/minio/minio.go @@ -14,7 +14,7 @@ type BlobStore struct { store *minio.Client } -const bucket = "chat" +const bucket = "pair" func New(ctx context.Context, logger hlog.Logger, endpoint, keyID, accessKey, token string, diff --git a/dal/mongo/dal.go b/dal/mongo/dal.go index dd54fd2..23ceaba 100644 --- a/dal/mongo/dal.go +++ b/dal/mongo/dal.go @@ -94,8 +94,67 @@ func (d *DAL) PutMessage( SessionID: sessionID, TicketID: ticketID, Message: message, + Files: files, + Shown: map[string]int{}, + CreatedAt: time.Now(), + } + + if _, err := d.colMsg.InsertOne(ctx, &insertable); err != nil { + d.logger.Emit(ErrorInsert{ + Err: err, + UserID: userID, + SessionID: sessionID, + }) + + return nil, err + } + + return &insertable, nil +} + +func (d *DAL) PutSCResponse( + ctx context.Context, + message, userID, sessionID, ticketID string, + files []string, +) (*model.Message, error) { + insertable := model.Message{ + ID: xid.New().String(), + UserID: userID, + SessionID: sessionID, + TicketID: ticketID, + Message: message, + Files: files, + RequestScreenshot: "response", + Shown: map[string]int{}, + CreatedAt: time.Now(), + } + + if _, err := d.colMsg.InsertOne(ctx, &insertable); err != nil { + d.logger.Emit(ErrorInsert{ + Err: err, + UserID: userID, + SessionID: sessionID, + }) + + return nil, err + } + + return &insertable, nil +} + +func (d *DAL) PutSCRequest( + ctx context.Context, + userID, sessionID, ticketID string, +) (*model.Message, error) { + insertable := model.Message{ + ID: xid.New().String(), + UserID: userID, + SessionID: sessionID, + TicketID: ticketID, + Message: "", Files: []string{}, Shown: map[string]int{}, + RequestScreenshot: "acquisition", CreatedAt: time.Now(), } @@ -251,7 +310,7 @@ func (d *DAL) YieldActiveTickets( yield func(ticket model.Ticket) error) error { cursor, err := d.colTck.Find(ctx, bson.M{ "State": model.StateOpen, - }) + }, options.Find().SetLimit(20)) if err != nil { return err } @@ -296,8 +355,10 @@ func (d *DAL) YieldUserTickets( } func (d *DAL) WatchActiveTickets(ctx context.Context, yield func(ticket model.Ticket) error) error { - operationTypes := []bson.D{{{"operationType", "insert"}}, - {{"operationType", "update"}}} + operationTypes := []bson.D{ + {{"operationType", "insert"}}, + {{"operationType", "update"}}, + } matchStage := bson.D{{"$and", []bson.D{ { @@ -491,7 +552,7 @@ func (d *DAL) GetTicketPage( ctx context.Context, state, srch string, limit, skip int64, -) (*[]model.Ticket, error) { +) (*[]model.Ticket, int64, error) { query := bson.M{} if state != "" { @@ -506,16 +567,21 @@ func (d *DAL) GetTicketPage( cur, err := d.colTck.Find(ctx, query, options.Find().SetLimit(limit).SetSkip(skip*limit)) if err != nil { - return nil, err + return nil,0, err } var result []model.Ticket if err := cur.All(ctx, &result); err != nil { - return nil, err + return nil,0, err } - return &result, nil + col, err := d.colTck.CountDocuments(ctx, query) + if err != nil { + return nil, 0, err + } + + return &result, col, nil } func (d *DAL) GetMessagesPage(ctx context.Context, @@ -555,8 +621,10 @@ func (d *DAL) GetMessagesPage(ctx context.Context, func (d *DAL) SetTicketStatus(ctx context.Context, ticket, status string) error { if _, err := d.colTck.UpdateByID(ctx, ticket, bson.M{ - "State": status, - "UpdatedAt": time.Now(), + "$set": bson.M{ + "State": status, + "UpdatedAt": time.Now(), + }, }); err != nil { return err } diff --git a/go.mod b/go.mod index 7def4f4..7fa70a9 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/BlackBroker/trashlog v0.0.4 github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/gorilla/mux v1.8.0 + github.com/minio/minio-go/v7 v7.0.10 github.com/pkg/errors v0.9.1 github.com/rs/xid v1.3.0 github.com/skeris/appInit v0.1.12 diff --git a/k8s/deployment.yml b/k8s/deployment.yml index 5208c66..de77a87 100644 --- a/k8s/deployment.yml +++ b/k8s/deployment.yml @@ -17,7 +17,7 @@ spec: - name: regcred containers: - name: heruvym - image: 192.168.193.205:31320/heruvym + image: 192.168.193.230:31320/heruvym imagePullPolicy: Always ports: - containerPort: 1488 diff --git a/middleware/middleware.go b/middleware/middleware.go index 0e29a43..864d505 100644 --- a/middleware/middleware.go +++ b/middleware/middleware.go @@ -19,13 +19,14 @@ func setJwtHeader(adapter *jwt_adapter.JwtAdapter, w http.ResponseWriter, logger w.Header().Set(jwt_adapter.DefaultHeaderKey, token) outToken, err := adapter.Encode() - const Domain = ".blacbrok.com" + const domain = ".fynrods.com" http.SetCookie(w, &http.Cookie{ Name: jwt_adapter.DefaultHeaderKey, Value: outToken, Expires: time.Now().Add(time.Hour * 24 * 3), Secure: true, + Domain: domain, HttpOnly: true, Path: "/", }) diff --git a/model/model.go b/model/model.go index 76c5ee2..3004178 100644 --- a/model/model.go +++ b/model/model.go @@ -11,6 +11,7 @@ type Message struct { Message string `bson:"Message" json:"message"` Files []string `bson:"Files" json:"files"` Shown map[string]int `bson:"Shown" json:"shown"` + RequestScreenshot string `bson:"RequestScreenshot" json:"request_screenshot"` CreatedAt time.Time `bson:"CreatedAt" json:"created_at"` } diff --git a/ops/deploy b/ops/deploy index b23db0c..052ecee 100755 --- a/ops/deploy +++ b/ops/deploy @@ -20,7 +20,7 @@ echo "################################################################" echo "" echo "" -sudo docker build -t 192.168.193.205:31320/heruvym:latest . +sudo docker build -t 192.168.193.230:31320/heruvym:latest . echo "" echo "" @@ -30,7 +30,7 @@ echo "################################################################" echo "" echo "" -sudo docker push 192.168.193.205:31320/heruvym +sudo docker push 192.168.193.230:31320/heruvym echo "" echo "" diff --git a/prod.crt b/prod.crt new file mode 100644 index 0000000..696b1a2 --- /dev/null +++ b/prod.crt @@ -0,0 +1,29 @@ +-----BEGIN CERTIFICATE----- +MIIE7jCCA9agAwIBAgIUVvQYivgWS6pPgexcAauT87iGCWAwDQYJKoZIhvcNAQEL +BQAwgYsxCzAJBgNVBAYTAlVTMRkwFwYDVQQKExBDbG91ZEZsYXJlLCBJbmMuMTQw +MgYDVQQLEytDbG91ZEZsYXJlIE9yaWdpbiBTU0wgQ2VydGlmaWNhdGUgQXV0aG9y +aXR5MRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRMwEQYDVQQIEwpDYWxpZm9ybmlh +MB4XDTIyMDIwMzEzMTYwMFoXDTM3MDEzMDEzMTYwMFowYjEZMBcGA1UEChMQQ2xv +dWRGbGFyZSwgSW5jLjEdMBsGA1UECxMUQ2xvdWRGbGFyZSBPcmlnaW4gQ0ExJjAk +BgNVBAMTHUNsb3VkRmxhcmUgT3JpZ2luIENlcnRpZmljYXRlMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA24tlivNlweGDSmMwfeo1QyKG8bhuqQ9Ci9E9 +/dni+DUJii8zBP0vmMyiY94XYE9hxa62qdRukqotYDOobCPNCgZoKfR+KciPoVXa +YlGJkuuzHGG5t+c05f9NX3Zc+mmlMnzgq6L0lYrjwzqeggvGVpGxJItXDUz/BGGq ++HN8sZlaylv1xyeeLrblMFDnxLg1PHAKFNa0dpVmlXQMtmUpIPSaWOm2dDzszu4V +IYJuc6GMP0wGj5koqYW96np+HmZyQlwhWH6hrC4qsDBx2occZ+UdXf5y9/QVibXi +9lrK0jZrYz2Wi6+A4YpvffWgc7ziVCmS8vX3vWAgWBg5TnxNuQIDAQABo4IBcDCC +AWwwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcD +ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBQbbVvRVYFwSfCMTvbuBe0/gWeO/zAf +BgNVHSMEGDAWgBQk6FNXXXw0QIep65TbuuEWePwppDBABggrBgEFBQcBAQQ0MDIw +MAYIKwYBBQUHMAGGJGh0dHA6Ly9vY3NwLmNsb3VkZmxhcmUuY29tL29yaWdpbl9j +YTBxBgNVHREEajBoggwqLmZ5bmFmZi5jb22CCyouZnluYWZmLnJ1gg0qLmZ5bnJv +ZHMuY29tggwqLmZ5bnJvZHMucnWCCmZ5bmFmZi5jb22CCWZ5bmFmZi5ydYILZnlu +cm9kcy5jb22CCmZ5bnJvZHMucnUwOAYDVR0fBDEwLzAtoCugKYYnaHR0cDovL2Ny +bC5jbG91ZGZsYXJlLmNvbS9vcmlnaW5fY2EuY3JsMA0GCSqGSIb3DQEBCwUAA4IB +AQCus5r+968+lJul4R8yyK4RUGbdWLTls/wHjtMDCyNo8/LXGdLaYMuMwC44UhxI +OsKnTmGJirvYQcnhwSz3biFYfKE55/dUB/0tyZ9TK5b5AoOn6H34FZEvyosaTXXZ +wv/zVK6sH7mHa8qFd+jdaPTqxxkrK+1XzK6KdcZ0vIUeUkI47OCPAIJHU+z7GNO9 +LML6jHqklOgePDliEEygc2n7Jb493woo3S18VJCwlim4ZkGpESAASqhZ6hKYVN41 +QqcRqy0VEKIDBaqmLDyoupTPpJjU5ELRNCkDH7FC69nPHzItF5avdRzbNRl2Sq1D +VY0DBkrVuqmdgQipEanyaLCi +-----END CERTIFICATE----- diff --git a/prod.key b/prod.key new file mode 100644 index 0000000..4bbe2b1 --- /dev/null +++ b/prod.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDbi2WK82XB4YNK +YzB96jVDIobxuG6pD0KL0T392eL4NQmKLzME/S+YzKJj3hdgT2HFrrap1G6Sqi1g +M6hsI80KBmgp9H4pyI+hVdpiUYmS67McYbm35zTl/01fdlz6aaUyfOCrovSViuPD +Op6CC8ZWkbEki1cNTP8EYar4c3yxmVrKW/XHJ54utuUwUOfEuDU8cAoU1rR2lWaV +dAy2ZSkg9JpY6bZ0POzO7hUhgm5zoYw/TAaPmSiphb3qen4eZnJCXCFYfqGsLiqw +MHHahxxn5R1d/nL39BWJteL2WsrSNmtjPZaLr4Dhim999aBzvOJUKZLy9fe9YCBY +GDlOfE25AgMBAAECggEAC0Xonw5pcrT8M1p4LSGqE3pB40aSSWmzA+U+IXtJ2Bni +aq81bPOn49jaG8urIp22NQWIHpyoWC1B1YyW1jADwW3bymUMrLjo2yLClcV/DXAU +izK0wRiE/axdfOHh21UyZNnHBY6BWu5ooefa0hhTBQidHSBvMLZ76m3YxBeArHPN +iceCSNoG0G0gql+Zs9KwcUK0vc9w4VdATNgVa8+AN3iZh+Fm0h4XLWh7FUR1kMG+ +NCKM9/0hSA5cpEEJet60tmzHXUBJCo+suuMF9eOl4c+ba+/991Zyz0aLmPwtB37O +Ruk6r98mdRhRHAWL9SHelXDPOrmvrlOTwGVZKmhfSQKBgQD6o0fHtf63dp/lbXrk +2EB7dT3BAkGMobkAxNv61tRiA/vvXb2JzlB5g1s3I9imNBokLwXriHZVB3qdHN6v +IgxFur4sCqCj3H1gfVNgGz2AMlUH3bvikjXqBR/TQs+3mUAmrpDlxsmE3IcEZDwE +D58SzOElAA5aDMY11QOjJUWG7QKBgQDgPdI7ZzaYM8ByH/R/me+pJa5cdRi8Tjap +Lu8aY48aIwh9tMwKTKu6OJ6OysrMU7c1gmPeJ0UDi42HRyxUk/CdnaDW9hRjGiZt +kxPHHPN8rg0oDz8pJz4GkTM2pg603Zw6NCxcF3aTPCvPfeOn4JK7W6mzriQGhKYu +7fTB/3WcfQKBgCSPnPDtA3MPwtNc3Qh04zMfLxrwkU9KaApMrSoyHFkP67hHHFb1 +2ZdgKfYpLHlSMF4G3f41sc1FggVZKMKzXMbvLr6N7lD44PEqVvc2AgqpTO4Q0k+C +tIqmpLXUkShfGpSJ8mkSTmMrKCbj2D1fafz8FfunvnA0XNWNdTJfRX0hAoGAblU8 +ucnBDQZ5rC2Y6afeSgWmUwuyjgSV1IypTPyrjpqqNN/efTrYTBpLucqCGiMexA9S +AB6mUGY7ztHwN/VKsOK8HsiZo2FcgxGY66GNFE23X3yRATizxhtvbXYrSka39dNx ++CX7S9qRW9h/STywNcuWJjiKtUJTWkfu4/1D6ykCgYATd/eu7SJZHfSuSjJx+h4e +3OGXI0SS3Y3wDriSsYFZVQmM33mgyAJmLO0BPgzWKfKQEE3TldatGU7ZTXsHSV/a +yJCfbnG7yGM3fPY0ckS+b+3q9skUo5FJ5+rFkSEJB4bgyKmYfZDkfhVapHFvmcP3 +f2O+O75zc3RFC3+YGHdKrg== +-----END PRIVATE KEY----- diff --git a/server.crt b/server.crt new file mode 100644 index 0000000..33910ed --- /dev/null +++ b/server.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDazCCAlOgAwIBAgIUTZYPqWpnMp0w/hf7OjuNm0FwanYwDQYJKoZIhvcNAQEL +BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM +GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMjAxMjUwMjU2MzBaFw0yMzAx +MjUwMjU2MzBaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw +HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCl/UGvlDrkg9Mwqj2rvGkv9jvZ8Z8ZZe6ZHb/KR56Y +jgyIKow+bqxpduLXclezaUdG9XFQaR+FD1nK5lW6oUrX8Vcd59ImKBV+cCfMwjCH +sYrjheTQyoFY/o3+7bt8nyjnmYG0Z0dQqXSquHngKeoiVqkNGzZHSMLuRuRZFHu/ +SUj+7WOJsraIWK/8yt0dxjhGA/TMK4MlI2tdJ2vEaP9QPIBoWSGIpEa1myjV9XoG +qOtUQzjeRuMHG8Wp+4JzIsNdl1Gg+N3dBEQSExyVv0cLAJouKy2zmR2Eio3nXhWW +2kq+x3gjPlf8RDZJz+x/SsDmWvgGOcGTWcSLOdn/fa7VAgMBAAGjUzBRMB0GA1Ud +DgQWBBS315REqIh/ACzxxAK3EiZ1zTNSWDAfBgNVHSMEGDAWgBS315REqIh/ACzx +xAK3EiZ1zTNSWDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBW +pxle1BCaYtVRwT/05XXBFRfB5Mog8ip6JvWpWcixwx7qsCIsZd4VN2tenuvSQFTr +o9c2PCnU4fJihIiNZqX9X3UzH4WFmkqv1FMeDPPplzs4yxLxBjDDFmGBXLotZYpN +kjq/G1OYdbCssv1oz7S6flqQ1YyzW/Cwx/jkz15uUiqZhDPGj+HX4Fcdl2h3TF9Z +mS1s6VDXLlQM3zCcwVJo3Twryc8IjJWkA3VPfACpJF9dBj8RJW42P92+kBI3fhCL +nhdBxrAvrXK+HT4jdjnYxVDVWTVYx8Acwlr36yTDcucRJpnVN9zZgr8DuL+Ag4FX +xkL9kbdEGt6XnlV8K9Z8 +-----END CERTIFICATE----- diff --git a/server.key b/server.key new file mode 100644 index 0000000..c4bffe5 --- /dev/null +++ b/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCl/UGvlDrkg9Mw +qj2rvGkv9jvZ8Z8ZZe6ZHb/KR56YjgyIKow+bqxpduLXclezaUdG9XFQaR+FD1nK +5lW6oUrX8Vcd59ImKBV+cCfMwjCHsYrjheTQyoFY/o3+7bt8nyjnmYG0Z0dQqXSq +uHngKeoiVqkNGzZHSMLuRuRZFHu/SUj+7WOJsraIWK/8yt0dxjhGA/TMK4MlI2td +J2vEaP9QPIBoWSGIpEa1myjV9XoGqOtUQzjeRuMHG8Wp+4JzIsNdl1Gg+N3dBEQS +ExyVv0cLAJouKy2zmR2Eio3nXhWW2kq+x3gjPlf8RDZJz+x/SsDmWvgGOcGTWcSL +Odn/fa7VAgMBAAECggEAK1ALbNJkD67qU7+IeiCe3foFohgvaMQ1X1To79KCatJe +KMXZdI0Shi6UgJ2AjvtAsx5mpBHaPLFFv/Ecm6dszS5XiiEsr/IzsZt4dzCQ00eb +s0UD8Qt2dw9tZAEKtDkfxldDBh0Q+dZN8CJVAw5M3wr378iTAETXQK/U8/2pUL9V +6kR899Qb1hnK2NK0vQxvg7JoFxsc8DzLBc3q4UuzvzN1EnUDMhxnCiSR36HaX3CQ +c18bSvzchv5HNA+C7oKnvHRcMMfFsbJQZsgXR5oW5pTIsBDPJVW4Ob7DKIZ5r7J9 +5Ew38dHlE8bYmtp+rRgarj/W/PLEu55s+N09mncL3QKBgQDdCeHq9IwRJM5g4+0w +0cRbqU1zsr1jEAPDorLviRi9+GBqUPAwMEEJ3GHZqYofMyAlEmpqHzrJ/Its0IX4 +eQ+oZfSuRW+XUnlrhgSxqZv5bXOVIHHaMNpumx5bg86/2O/Cgr44qezsHazr+cWB +O7cH7Jwe1axGpZrFmJ+yfe7MNwKBgQDAPlx8CTJEh9FfLjg7gKOHMSfMsIh8k4Dh +dU9dXFA5g/FmOf01rlIf9qVBwemn14wRx/+o035qRSEDWfMua7PF/yI/KXo9Gmcg +U4XNNE1cbPLH7w7kEp9Xx7XsyiOX76S4Aa6Oh383PYQjWb1cb1oug4kWhkJGuRCO +1XeznRfPUwKBgQClm5fmf57J4Xe25E57+05RFsHu44Y9yGvpkebazS76djNWtJmg +oSa5iqLNf9b6lUWKQQf1xrw3Rb34oysdBScUFn+Caoe3KpXKV7kAm4E/GiA1JP/o +aB3gLNxL2K940cKhS2/V6IqYRYufqZ2uu9zgVQiLma/fpogVb8qG4w+ddQKBgH7w +7srsm6fK80LhVzpbQCAGIlyz+Pwhvkmh180zJrpD2MQC6KNov0vh5s+cBvjQiOo4 +4SWOufvcN+dpnv15GtVUGj4Q2mm8pHohDMoqjibIviutPGz3qwYglo2MEKLEGEV0 +vtnYuPU2Bqn9GOAPm0H5ky0vbFYc38UhShBtXAqHAoGACD57o0rl3nBUoHyk9kuI +6EYFV+r6NJhHu+oDrMUNExG59G+nIZ/GujYQCGB8ncCZa+R+CmUdDpOQ88tWbuGC +WEdmGyGqWesuSp5mj5171jf5GdoqWvH+N5frD7TGCWUuWF4KCGnMvbcTx/KxEbr7 +Jzr59ImXdRbFP1sL9CibBw8= +-----END PRIVATE KEY----- diff --git a/service/service.go b/service/service.go index 36ebb57..b32b76d 100644 --- a/service/service.go +++ b/service/service.go @@ -174,8 +174,10 @@ func (h *Heruvym) GetList(ctx context.Context) chan interface{} { role, err := h.ral.GetProfileRole(ctx, sess.User) if err != nil { + fmt.Println("HER ERR", err) go h.hasNoRole(output) } + fmt.Println("ALL TICKETS Sess ", sess.User, role) if role == "admin" || role == "manager" { go h.allTickets(ctx, output) } else { @@ -211,10 +213,17 @@ func (h *Heruvym) allTickets(ctx context.Context, output chan interface{}) { func (h *Heruvym) userTickets(ctx context.Context, userID string, output chan interface{}) { + defer func() { + if v := recover(); v != nil { + fmt.Println("USERTICKS", v) + } + } () + if err := h.dal.YieldUserTickets(ctx, userID, func(ticket model.Ticket) error { output <- ticket return nil }); err != nil { + output <- errors.New("cannot get tickets:" + err.Error()) return } @@ -229,8 +238,6 @@ func (h *Heruvym) userTickets(ctx context.Context, userID string, output chan in } func (h *Heruvym) hasNoRole(output chan interface{}) { - - output <- errors.New("no role in profile") } @@ -272,7 +279,7 @@ func (h *Heruvym) PutMessage( sess.User, sess.Session, request.TicketID, - request.Files, + []string{}, ) if err != nil { return errors.New("can not put message"), http.StatusInternalServerError @@ -285,10 +292,35 @@ func (h *Heruvym) PutMessage( return nil, http.StatusOK } +type ReqScreenshot struct { + TicketID string `json:"ticket"` + Lang string `json:"lang"` +} + +func (h *Heruvym) RequestScreenshot( + ctx context.Context, + request ReqScreenshot, +) (interface{}, int) { + sess := jwt_adapter.Get(ctx) + + _, err := h.dal.PutSCRequest( + ctx, + sess.User, + sess.Session, + request.TicketID, + ) + if err != nil { + return errors.New("can not put message"), http.StatusInternalServerError + } + + return nil, http.StatusOK +} + var _ tools.DataEmitter = (&Heruvym{}).Subscribe func (h *Heruvym) Subscribe(ctx context.Context) chan interface{} { sess := jwt_adapter.Get(ctx) + fmt.Println("SESS Subsc", sess) ticketID := ctx.Value(tools.ContextURLKey).(string) @@ -428,21 +460,28 @@ type GetTicketsReq struct { Search string `json:"srch"` Status string `json:"status"` } +type GetTicketsResp struct { + Data []model.Ticket `json:"data"` + Count int64 `json:"count"` +} func (h *Heruvym) GetTickets( ctx context.Context, - request GetTicketsReq) ([]model.Ticket, int) { - result, err := h.dal.GetTicketPage(ctx, + request GetTicketsReq) (GetTicketsResp, int) { + result, count, err := h.dal.GetTicketPage(ctx, request.Status, request.Search, request.Amount, request.Page, ) if err != nil { - return nil, http.StatusNoContent + return GetTicketsResp{}, http.StatusNoContent } - return *result, http.StatusOK + return GetTicketsResp{ + Data: *result, + Count: count, + }, http.StatusOK } type GetMessagesReq struct { @@ -471,13 +510,18 @@ func (h *Heruvym) GetMessages( type CloseTicketReq struct { TicketID string `json:"ticket"` } +type CloseTicketResp struct { + TicketID string `json:"ticket"` +} -func (h *Heruvym) CloseTicket(ctx context.Context, req CloseTicketReq) (error, int) { +func (h *Heruvym) CloseTicket(ctx context.Context, req CloseTicketReq) (*CloseTicketResp, int) { if err := h.dal.SetTicketStatus(ctx, req.TicketID, model.StateClose); err != nil { - return err, http.StatusBadRequest + return nil, http.StatusBadRequest } - return nil, http.StatusOK + return &CloseTicketResp{ + TicketID: req.TicketID, + }, http.StatusOK } type VoteReq struct { @@ -670,6 +714,159 @@ func (h *Heruvym) PutFile(w http.ResponseWriter, r *http.Request) { return } + if _, err := w.Write(resp); err != nil { + fmt.Println("CAN NOT WRITE", err) + } + w.WriteHeader(http.StatusOK) +} + +type PutSCReq struct { + Ticket string `json:"ticket"` +} + +type PutSCResp struct { + Message string `json:"message"` +} + +func (h *Heruvym) PutSC(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + + if err := r.ParseMultipartForm(10 * MB); err != nil { + if _, err := w.Write([]byte("can not parse multipart "+err.Error())); err != nil { + fmt.Println("CAN NOT WRITE", err) + } + w.WriteHeader(http.StatusBadRequest) + return + } + + if r.MultipartForm == nil { + if _, err := w.Write([]byte("no multipart")); err != nil { + fmt.Println("CAN NOT WRITE", err) + } + w.WriteHeader(http.StatusBadRequest) + return + } + + if r.MultipartForm.File == nil { + if _, err := w.Write([]byte("no file")); err != nil { + fmt.Println("CAN NOT WRITE", err) + } + w.WriteHeader(http.StatusBadRequest) + return + } + + filesCount:= len(r.MultipartForm.File) + + if filesCount == 0 { + if _, err := w.Write([]byte("no files")); err != nil { + fmt.Println("CAN NOT WRITE", err) + } + w.WriteHeader(http.StatusBadRequest) + return + } + + sess := jwt_adapter.Get(r.Context()) + if sess == nil { + if _, err := w.Write([]byte("not authorized")); err != nil { + fmt.Println("CAN NOT WRITE", err) + } + w.WriteHeader(http.StatusBadRequest) + return + } + + var req PutFileReq + if err := json.NewDecoder(r.Body).Decode(&req); err != nil { + if _, err := w.Write([]byte("can not decode "+err.Error())); err != nil { + fmt.Println("CAN NOT WRITE", err) + } + w.WriteHeader(http.StatusBadRequest) + return + } + + var ( + fileIDs, filenames []string + errFile error + ) + wg := new(sync.WaitGroup) + m:=new(sync.Mutex) + + wg.Add(filesCount) + for name, file := range r.MultipartForm.File { + file := file + name := name + go func() { + defer wg.Done() + + freader, err := file[0].Open() + if err != nil { + fmt.Println("can not open ", err.Error()) + } + + 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]) + + if err := h.bs.PutFile( + r.Context(), + filename, + freader, + file[0].Size); err != nil { + errFile = err + } + + m.Lock() + defer m.Unlock() + fileIDs = append(fileIDs, filename) + filenames = append(filenames, name) + }() + } + wg.Wait() + + if errFile != nil { + if _, err := w.Write([]byte("can not store files "+errFile.Error())); err != nil { + fmt.Println("CAN NOT WRITE", err) + } + w.WriteHeader(http.StatusInternalServerError) + return + } + + message, err := h.dal.PutSCResponse( + r.Context(), + strings.Join(filenames, ", "), + sess.User, + sess.Session, + req.Ticket, + fileIDs, + ) + + if err != nil { + for _, filename := range filenames { + if err := h.bs.DeleteFile(r.Context(), filename); err != nil { + fmt.Println("can not delete", err) + } + } + + if _, err := w.Write([]byte("can not store message "+err.Error())); err != nil { + fmt.Println("CAN NOT WRITE", err) + } + w.WriteHeader(http.StatusInternalServerError) + return + } + + resp, err := json.Marshal(&PutFileResp{Message: message.ID}) + if err != nil { + if _, err := w.Write([]byte("can not marshal resp "+err.Error())); err != nil { + fmt.Println("CAN NOT WRITE", err) + } + w.WriteHeader(http.StatusInternalServerError) + return + } + if _, err := w.Write(resp); err != nil { fmt.Println("CAN NOT WRITE", err) } diff --git a/tools/tools.go b/tools/tools.go index c6cebdd..a2c52c1 100644 --- a/tools/tools.go +++ b/tools/tools.go @@ -15,6 +15,11 @@ const ContextURLKey = "url" func SseWrapper(emitter DataEmitter) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { + defer func() { + if v := recover(); v != nil { + fmt.Println("sse her err", v) + } + } () // Отправляем header event-stream w.Header().Set("Content-Type", "text/event-stream") @@ -52,7 +57,6 @@ func SseWrapper(emitter DataEmitter) http.HandlerFunc { case <-time.After(time.Second * 10): SSEPing(w) case m := <-dE: - fmt.Println("SEEEND", m) if m == nil { continue }