lil commit

This commit is contained in:
Skeris 2022-02-27 18:27:44 +03:00
parent 268bfa9b53
commit eab8e4960d
15 changed files with 437 additions and 44 deletions

@ -1,6 +1,9 @@
FROM alpine FROM alpine
ADD heruvym / ADD heruvym /
COPY prod.crt /
COPY prod.key /
ENV APP_ADDR=:1488 ENV APP_ADDR=:1488
ENV BB_IS_PROD=true
ENV BB_MONGO_URI=mongodb://mongodb ENV BB_MONGO_URI=mongodb://mongodb
ENV MINIO_ENDPOINT=minio:9001 ENV MINIO_ENDPOINT=minio:9001
RUN apk add --no-cache ca-certificates RUN apk add --no-cache ca-certificates

@ -38,10 +38,10 @@ type Options struct {
MongoURI string `env:"BB_MONGO_URI" default:"mongodb://localhost:27017"` MongoURI string `env:"BB_MONGO_URI" default:"mongodb://localhost:27017"`
NumberPortLocal string `env:"BB_PORT" default:"1488"` NumberPortLocal string `env:"BB_PORT" default:"1488"`
LoggerDevMode bool `env:"BB_IS_PROD" default:"false"` LoggerDevMode bool `env:"BB_IS_PROD" default:"false"`
MinioEndpoint string `env:"BB_MINIO_EP" default:"minio:9001"` MinioEndpoint string `env:"BB_MINIO_EP" default:"minio:9001"`
MinioAccessKey string `env:"BB_MINIO_AK" default:"minioadmin"` MinioAccessKey string `env:"BB_MINIO_AK" default:"minio"`
MinioSecretKey string `env:"BB_MINIO_SK" default:"minioadmin"` MinioSecretKey string `env:"BB_MINIO_SK" default:"miniostorage"`
MinioToken string `env:"BB_MINIO_TOKEN" default:""` MinioToken string `env:"BB_MINIO_TOKEN" default:""`
MongoDbTable string `env:"DATABASE_TABLE" default:"profile"` MongoDbTable string `env:"DATABASE_TABLE" default:"profile"`
MongoCollections string `env:"COLLECTION_NAME" default:"profile,role"` 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 { if options.LoggerDevMode {
zapLogger, err = zap.NewDevelopment(zapOptions...) zapLogger, err = zap.NewProduction(zapOptions...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
} else { } else {
zapLogger, err = zap.NewProduction(zapOptions...) zapLogger, err = zap.NewDevelopment(zapOptions...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -146,8 +146,9 @@ func New(ctx context.Context, opts interface{}) (appInit.CommonApp, error) {
options.MinioAccessKey, options.MinioAccessKey,
options.MinioSecretKey, options.MinioSecretKey,
options.MinioToken, options.MinioToken,
true) false)
if err != nil { if err != nil {
fmt.Println("MINIO store", err)
return nil, 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) signal.Notify(interrupt, os.Interrupt, syscall.SIGTERM)
mux := router.NewRouter(map[string]http.HandlerFunc{ mux := router.NewRouter(map[string]http.HandlerFunc{
"/support/create": heruvym.CreateTicket, "/support/create": heruvym.CreateTicket,
"/support/subscribe": tools.SseWrapper(heruvym.GetList), "/support/subscribe": tools.SseWrapper(heruvym.GetList),
"/support/ticket": tools.SseWrapper(heruvym.Subscribe), "/support/ticket": tools.SseWrapper(heruvym.Subscribe),
"/support/send": tools.HandlerWrapper(heruvym.PutMessage), "/support/send": tools.HandlerWrapper(heruvym.PutMessage),
"/support/sendFiles": heruvym.PutFile, "/support/requestScreenshot": tools.HandlerWrapper(heruvym.RequestScreenshot),
"/support/getTickets": tools.HandlerWrapper(heruvym.GetTickets), "/support/sendFiles": heruvym.PutFile,
"/support/getMessages": tools.HandlerWrapper(heruvym.GetMessages), "/support/sendSC": heruvym.PutSC,
"/support/pick": tools.HandlerWrapper(heruvym.Pick), "/support/getTickets": tools.HandlerWrapper(heruvym.GetTickets),
"/support/delegate": tools.HandlerWrapper(heruvym.Delegate), "/support/getMessages": tools.HandlerWrapper(heruvym.GetMessages),
"/support/vote": tools.HandlerWrapper(heruvym.Vote), "/support/pick": tools.HandlerWrapper(heruvym.Pick),
"/support/close": tools.HandlerWrapper(heruvym.CloseTicket), "/support/delegate": tools.HandlerWrapper(heruvym.Delegate),
"/support/vote": tools.HandlerWrapper(heruvym.Vote),
"/support/close": tools.HandlerWrapper(heruvym.CloseTicket),
}) })
mw := middleware.NewMiddleware( mw := middleware.NewMiddleware(
@ -223,7 +226,16 @@ func New(ctx context.Context, opts interface{}) (appInit.CommonApp, error) {
}() }()
logger.Emit(InfoSvcStarted{}) 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{ logger.Emit(ErrorCanNotServe{
Err: err, Err: err,
}) })

@ -14,7 +14,7 @@ type BlobStore struct {
store *minio.Client store *minio.Client
} }
const bucket = "chat" const bucket = "pair"
func New(ctx context.Context, logger hlog.Logger, func New(ctx context.Context, logger hlog.Logger,
endpoint, keyID, accessKey, token string, endpoint, keyID, accessKey, token string,

@ -94,8 +94,67 @@ func (d *DAL) PutMessage(
SessionID: sessionID, SessionID: sessionID,
TicketID: ticketID, TicketID: ticketID,
Message: message, 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{}, Files: []string{},
Shown: map[string]int{}, Shown: map[string]int{},
RequestScreenshot: "acquisition",
CreatedAt: time.Now(), CreatedAt: time.Now(),
} }
@ -251,7 +310,7 @@ func (d *DAL) YieldActiveTickets(
yield func(ticket model.Ticket) error) error { yield func(ticket model.Ticket) error) error {
cursor, err := d.colTck.Find(ctx, bson.M{ cursor, err := d.colTck.Find(ctx, bson.M{
"State": model.StateOpen, "State": model.StateOpen,
}) }, options.Find().SetLimit(20))
if err != nil { if err != nil {
return err return err
} }
@ -296,8 +355,10 @@ func (d *DAL) YieldUserTickets(
} }
func (d *DAL) WatchActiveTickets(ctx context.Context, yield func(ticket model.Ticket) error) error { func (d *DAL) WatchActiveTickets(ctx context.Context, yield func(ticket model.Ticket) error) error {
operationTypes := []bson.D{{{"operationType", "insert"}}, operationTypes := []bson.D{
{{"operationType", "update"}}} {{"operationType", "insert"}},
{{"operationType", "update"}},
}
matchStage := bson.D{{"$and", []bson.D{ matchStage := bson.D{{"$and", []bson.D{
{ {
@ -491,7 +552,7 @@ func (d *DAL) GetTicketPage(
ctx context.Context, ctx context.Context,
state, srch string, state, srch string,
limit, skip int64, limit, skip int64,
) (*[]model.Ticket, error) { ) (*[]model.Ticket, int64, error) {
query := bson.M{} query := bson.M{}
if state != "" { if state != "" {
@ -506,16 +567,21 @@ func (d *DAL) GetTicketPage(
cur, err := d.colTck.Find(ctx, query, options.Find().SetLimit(limit).SetSkip(skip*limit)) cur, err := d.colTck.Find(ctx, query, options.Find().SetLimit(limit).SetSkip(skip*limit))
if err != nil { if err != nil {
return nil, err return nil,0, err
} }
var result []model.Ticket var result []model.Ticket
if err := cur.All(ctx, &result); err != nil { 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, 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, func (d *DAL) SetTicketStatus(ctx context.Context,
ticket, status string) error { ticket, status string) error {
if _, err := d.colTck.UpdateByID(ctx, ticket, bson.M{ if _, err := d.colTck.UpdateByID(ctx, ticket, bson.M{
"State": status, "$set": bson.M{
"UpdatedAt": time.Now(), "State": status,
"UpdatedAt": time.Now(),
},
}); err != nil { }); err != nil {
return err return err
} }

1
go.mod

@ -7,6 +7,7 @@ require (
github.com/BlackBroker/trashlog v0.0.4 github.com/BlackBroker/trashlog v0.0.4
github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/gorilla/mux v1.8.0 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/pkg/errors v0.9.1
github.com/rs/xid v1.3.0 github.com/rs/xid v1.3.0
github.com/skeris/appInit v0.1.12 github.com/skeris/appInit v0.1.12

@ -17,7 +17,7 @@ spec:
- name: regcred - name: regcred
containers: containers:
- name: heruvym - name: heruvym
image: 192.168.193.205:31320/heruvym image: 192.168.193.230:31320/heruvym
imagePullPolicy: Always imagePullPolicy: Always
ports: ports:
- containerPort: 1488 - containerPort: 1488

@ -19,13 +19,14 @@ func setJwtHeader(adapter *jwt_adapter.JwtAdapter, w http.ResponseWriter, logger
w.Header().Set(jwt_adapter.DefaultHeaderKey, token) w.Header().Set(jwt_adapter.DefaultHeaderKey, token)
outToken, err := adapter.Encode() outToken, err := adapter.Encode()
const Domain = ".blacbrok.com" const domain = ".fynrods.com"
http.SetCookie(w, &http.Cookie{ http.SetCookie(w, &http.Cookie{
Name: jwt_adapter.DefaultHeaderKey, Name: jwt_adapter.DefaultHeaderKey,
Value: outToken, Value: outToken,
Expires: time.Now().Add(time.Hour * 24 * 3), Expires: time.Now().Add(time.Hour * 24 * 3),
Secure: true, Secure: true,
Domain: domain,
HttpOnly: true, HttpOnly: true,
Path: "/", Path: "/",
}) })

@ -11,6 +11,7 @@ type Message struct {
Message string `bson:"Message" json:"message"` Message string `bson:"Message" json:"message"`
Files []string `bson:"Files" json:"files"` Files []string `bson:"Files" json:"files"`
Shown map[string]int `bson:"Shown" json:"shown"` Shown map[string]int `bson:"Shown" json:"shown"`
RequestScreenshot string `bson:"RequestScreenshot" json:"request_screenshot"`
CreatedAt time.Time `bson:"CreatedAt" json:"created_at"` CreatedAt time.Time `bson:"CreatedAt" json:"created_at"`
} }

@ -20,7 +20,7 @@ echo "################################################################"
echo "" 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 ""
echo "" echo ""
@ -30,7 +30,7 @@ echo "################################################################"
echo "" echo ""
echo "" echo ""
sudo docker push 192.168.193.205:31320/heruvym sudo docker push 192.168.193.230:31320/heruvym
echo "" echo ""
echo "" echo ""

29
prod.crt Normal file

@ -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-----

28
prod.key Normal file

@ -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-----

21
server.crt Normal file

@ -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-----

28
server.key Normal file

@ -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-----

@ -174,8 +174,10 @@ func (h *Heruvym) GetList(ctx context.Context) chan interface{} {
role, err := h.ral.GetProfileRole(ctx, sess.User) role, err := h.ral.GetProfileRole(ctx, sess.User)
if err != nil { if err != nil {
fmt.Println("HER ERR", err)
go h.hasNoRole(output) go h.hasNoRole(output)
} }
fmt.Println("ALL TICKETS Sess ", sess.User, role)
if role == "admin" || role == "manager" { if role == "admin" || role == "manager" {
go h.allTickets(ctx, output) go h.allTickets(ctx, output)
} else { } 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{}) { 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 { if err := h.dal.YieldUserTickets(ctx, userID, func(ticket model.Ticket) error {
output <- ticket output <- ticket
return nil return nil
}); err != nil { }); err != nil {
output <- errors.New("cannot get tickets:" + err.Error()) output <- errors.New("cannot get tickets:" + err.Error())
return return
} }
@ -229,8 +238,6 @@ func (h *Heruvym) userTickets(ctx context.Context, userID string, output chan in
} }
func (h *Heruvym) hasNoRole(output chan interface{}) { func (h *Heruvym) hasNoRole(output chan interface{}) {
output <- errors.New("no role in profile") output <- errors.New("no role in profile")
} }
@ -272,7 +279,7 @@ func (h *Heruvym) PutMessage(
sess.User, sess.User,
sess.Session, sess.Session,
request.TicketID, request.TicketID,
request.Files, []string{},
) )
if err != nil { if err != nil {
return errors.New("can not put message"), http.StatusInternalServerError return errors.New("can not put message"), http.StatusInternalServerError
@ -285,10 +292,35 @@ func (h *Heruvym) PutMessage(
return nil, http.StatusOK 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 var _ tools.DataEmitter = (&Heruvym{}).Subscribe
func (h *Heruvym) Subscribe(ctx context.Context) chan interface{} { func (h *Heruvym) Subscribe(ctx context.Context) chan interface{} {
sess := jwt_adapter.Get(ctx) sess := jwt_adapter.Get(ctx)
fmt.Println("SESS Subsc", sess)
ticketID := ctx.Value(tools.ContextURLKey).(string) ticketID := ctx.Value(tools.ContextURLKey).(string)
@ -428,21 +460,28 @@ type GetTicketsReq struct {
Search string `json:"srch"` Search string `json:"srch"`
Status string `json:"status"` Status string `json:"status"`
} }
type GetTicketsResp struct {
Data []model.Ticket `json:"data"`
Count int64 `json:"count"`
}
func (h *Heruvym) GetTickets( func (h *Heruvym) GetTickets(
ctx context.Context, ctx context.Context,
request GetTicketsReq) ([]model.Ticket, int) { request GetTicketsReq) (GetTicketsResp, int) {
result, err := h.dal.GetTicketPage(ctx, result, count, err := h.dal.GetTicketPage(ctx,
request.Status, request.Status,
request.Search, request.Search,
request.Amount, request.Amount,
request.Page, request.Page,
) )
if err != nil { 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 { type GetMessagesReq struct {
@ -471,13 +510,18 @@ func (h *Heruvym) GetMessages(
type CloseTicketReq struct { type CloseTicketReq struct {
TicketID string `json:"ticket"` 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 { 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 { type VoteReq struct {
@ -670,6 +714,159 @@ func (h *Heruvym) PutFile(w http.ResponseWriter, r *http.Request) {
return 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 { if _, err := w.Write(resp); err != nil {
fmt.Println("CAN NOT WRITE", err) fmt.Println("CAN NOT WRITE", err)
} }

@ -15,6 +15,11 @@ const ContextURLKey = "url"
func SseWrapper(emitter DataEmitter) http.HandlerFunc { func SseWrapper(emitter DataEmitter) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
defer func() {
if v := recover(); v != nil {
fmt.Println("sse her err", v)
}
} ()
// Отправляем header event-stream // Отправляем header event-stream
w.Header().Set("Content-Type", "text/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): case <-time.After(time.Second * 10):
SSEPing(w) SSEPing(w)
case m := <-dE: case m := <-dE:
fmt.Println("SEEEND", m)
if m == nil { if m == nil {
continue continue
} }