2021-04-11 09:48:15 +00:00
|
|
|
package service
|
|
|
|
|
|
|
|
import (
|
2021-05-02 22:25:12 +00:00
|
|
|
"bitbucket.org/skeris/heruvym/dal"
|
|
|
|
"bitbucket.org/skeris/heruvym/jwt_adapter"
|
|
|
|
"bitbucket.org/skeris/heruvym/model"
|
|
|
|
"bitbucket.org/skeris/heruvym/tools"
|
2021-05-01 17:50:03 +00:00
|
|
|
rAL "bitbucket.org/skeris/profile/dal"
|
2021-05-01 12:36:22 +00:00
|
|
|
"context"
|
2021-04-11 09:48:15 +00:00
|
|
|
"encoding/json"
|
2021-05-01 12:36:22 +00:00
|
|
|
"errors"
|
2021-05-15 20:10:07 +00:00
|
|
|
"fmt"
|
2021-04-11 09:48:15 +00:00
|
|
|
"github.com/themakers/hlog"
|
|
|
|
"net/http"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Heruvym struct {
|
|
|
|
logger hlog.Logger
|
|
|
|
dal *dal.DAL
|
2021-05-01 17:50:03 +00:00
|
|
|
ral rAL.LayerMongoDb
|
2021-04-11 09:48:15 +00:00
|
|
|
}
|
|
|
|
|
2021-05-01 17:50:03 +00:00
|
|
|
func New(dataAccessLayer *dal.DAL, ral rAL.LayerMongoDb, log hlog.Logger) *Heruvym {
|
2021-04-11 09:48:15 +00:00
|
|
|
return &Heruvym{
|
|
|
|
logger: log.Module("Service"),
|
|
|
|
dal: dataAccessLayer,
|
2021-05-01 17:50:03 +00:00
|
|
|
ral: ral,
|
2021-04-11 09:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-01 17:50:03 +00:00
|
|
|
func (h Heruvym) Register(m *http.ServeMux) *http.ServeMux {
|
2021-04-11 09:48:15 +00:00
|
|
|
|
|
|
|
m.HandleFunc("/create", h.CreateTicket)
|
2021-05-02 22:25:12 +00:00
|
|
|
m.HandleFunc("/subscribe", tools.SseWrapper(h.GetList))
|
|
|
|
m.HandleFunc("/ticket", tools.SseWrapper(h.Subscribe))
|
|
|
|
m.HandleFunc("/send", tools.HandlerWrapper(h.PutMessage))
|
2021-05-11 10:57:58 +00:00
|
|
|
m.HandleFunc("/getTickets", tools.HandlerWrapper(h.GetTickets))
|
|
|
|
m.HandleFunc("/getMessages", tools.HandlerWrapper(h.GetMessages))
|
|
|
|
m.HandleFunc("/pick", tools.HandlerWrapper(h.Pick))
|
|
|
|
m.HandleFunc("/delegate", tools.HandlerWrapper(h.Delegate))
|
|
|
|
m.HandleFunc("/vote", tools.HandlerWrapper(h.Vote))
|
|
|
|
m.HandleFunc("/close", tools.HandlerWrapper(h.CloseTicket))
|
2021-04-11 09:48:15 +00:00
|
|
|
|
|
|
|
return m
|
|
|
|
}
|
|
|
|
|
|
|
|
type CreateTicketReq struct {
|
|
|
|
Title string `json:"Title"`
|
|
|
|
Message string `json:"Message"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type CreateTicketResp struct {
|
|
|
|
Ticket string `json:"Ticket"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *Heruvym) CreateTicket(w http.ResponseWriter, r *http.Request) {
|
|
|
|
defer func() {
|
|
|
|
if err := r.Body.Close(); err != nil {
|
|
|
|
h.logger.Emit(ErrorClose{
|
|
|
|
Err: err,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
var request CreateTicketReq
|
|
|
|
|
|
|
|
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
|
|
|
http.Error(w, "Invalid json", http.StatusBadRequest)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if request.Title == "" {
|
|
|
|
http.Error(w, "No Title", http.StatusNoContent)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if request.Message == "" {
|
|
|
|
http.Error(w, "No Message", http.StatusNoContent)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx := r.Context()
|
|
|
|
|
|
|
|
session := jwt_adapter.Get(ctx)
|
|
|
|
|
|
|
|
if session == nil {
|
|
|
|
http.Error(w, "No session", http.StatusMethodNotAllowed)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
ticketID, err := h.dal.CreateTicket(
|
|
|
|
ctx,
|
|
|
|
session.User,
|
|
|
|
session.ID,
|
|
|
|
request.Title,
|
2021-05-02 22:25:12 +00:00
|
|
|
request.Message,
|
|
|
|
[]string{},
|
2021-04-11 09:48:15 +00:00
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
http.Error(w, "CannotCreateTicket", http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-05-02 22:25:12 +00:00
|
|
|
if _, err := h.dal.PutMessage(ctx,
|
2021-04-11 09:48:15 +00:00
|
|
|
request.Message,
|
|
|
|
session.User,
|
|
|
|
session.Session,
|
|
|
|
ticketID,
|
|
|
|
[]string{},
|
|
|
|
); err != nil {
|
|
|
|
http.Error(w, "CannotCreateMessage", http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
response, err := json.Marshal(CreateTicketResp{Ticket: ticketID})
|
|
|
|
if err != nil {
|
|
|
|
h.logger.Emit(ErrorMarshal{
|
|
|
|
Err: err,
|
|
|
|
})
|
|
|
|
http.Error(w, "CannotMarshalMessage", http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if _, err := w.Write(response); err != nil {
|
|
|
|
h.logger.Emit(ErrorMarshal{
|
|
|
|
Err: err,
|
|
|
|
})
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
2021-05-01 10:05:45 +00:00
|
|
|
|
2021-05-02 22:25:12 +00:00
|
|
|
var _ tools.DataEmitter = (&Heruvym{}).GetList
|
2021-05-01 10:05:45 +00:00
|
|
|
|
2021-05-01 12:36:22 +00:00
|
|
|
func (h *Heruvym) GetList(ctx context.Context) chan interface{} {
|
|
|
|
sess := jwt_adapter.Get(ctx)
|
|
|
|
|
|
|
|
output := make(chan interface{})
|
|
|
|
|
|
|
|
if sess.User == "" {
|
|
|
|
go h.unauthorizedTickets(ctx, sess.Session, output)
|
|
|
|
} else {
|
2021-05-02 22:25:12 +00:00
|
|
|
role, err := h.ral.GetProfileRole(ctx, sess.User)
|
|
|
|
if err != nil {
|
|
|
|
go h.hasNoRole(output)
|
|
|
|
}
|
2021-05-01 17:50:03 +00:00
|
|
|
|
2021-05-02 22:25:12 +00:00
|
|
|
if role == "admin" || role == "manager" {
|
|
|
|
go h.allTickets(ctx, output)
|
|
|
|
} else {
|
|
|
|
go h.userTickets(ctx, sess.User, output)
|
|
|
|
}
|
2021-05-01 12:36:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return output
|
2021-05-01 10:05:45 +00:00
|
|
|
}
|
2021-05-01 12:36:22 +00:00
|
|
|
|
2021-05-02 22:25:12 +00:00
|
|
|
func (h *Heruvym) allTickets(ctx context.Context, output chan interface{}) {
|
|
|
|
defer close(output)
|
|
|
|
|
|
|
|
if err := h.dal.WatchActiveTickets(ctx, func(ticket model.Ticket) error {
|
|
|
|
output <- ticket
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
|
|
|
output <- errors.New("cannot watch all tickets")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *Heruvym) userTickets(ctx context.Context, userID string, output chan interface{}) {
|
|
|
|
defer close(output)
|
|
|
|
|
|
|
|
if err := h.dal.YieldUserTickets(ctx, userID, func(ticket model.Ticket) error {
|
|
|
|
output <- ticket
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
|
|
|
output <- errors.New("cannot get tickets")
|
2021-05-15 20:10:07 +00:00
|
|
|
return
|
2021-05-02 22:25:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if err := h.dal.WatchTickets(ctx, userID, func(ticket model.Ticket) error {
|
|
|
|
output <- ticket
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
|
|
|
output <- errors.New("cannot watch tickets")
|
2021-05-15 20:10:07 +00:00
|
|
|
return
|
2021-05-02 22:25:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *Heruvym) hasNoRole(output chan interface{}) {
|
|
|
|
defer close(output)
|
|
|
|
|
|
|
|
output <- errors.New("no role in profile")
|
|
|
|
}
|
|
|
|
|
2021-05-01 12:36:22 +00:00
|
|
|
func (h *Heruvym) unauthorizedTickets(ctx context.Context, sess string, output chan interface{}) {
|
|
|
|
defer close(output)
|
|
|
|
|
|
|
|
tickets, err := h.dal.GetTickets4Sess(ctx, sess)
|
2021-05-01 17:50:03 +00:00
|
|
|
if err != nil {
|
2021-05-01 12:36:22 +00:00
|
|
|
output <- errors.New("no tickets for session")
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, ticket := range tickets {
|
|
|
|
output <- ticket
|
|
|
|
}
|
2021-05-01 17:50:03 +00:00
|
|
|
}
|
2021-05-02 22:25:12 +00:00
|
|
|
|
|
|
|
type ReqPutMessage struct {
|
|
|
|
Message string `json:"message"`
|
|
|
|
TicketID string `json:"ticket"`
|
|
|
|
Files []string `json:"files"`
|
|
|
|
Lang string `json:"lang"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *Heruvym) PutMessage(
|
|
|
|
ctx context.Context,
|
|
|
|
request ReqPutMessage,
|
|
|
|
) (interface{}, int) {
|
|
|
|
sess := jwt_adapter.Get(ctx)
|
|
|
|
|
|
|
|
message, err := h.dal.PutMessage(
|
|
|
|
ctx,
|
|
|
|
request.Message,
|
|
|
|
sess.User,
|
|
|
|
sess.Session,
|
|
|
|
request.TicketID,
|
|
|
|
request.Files,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return errors.New("can not put message"), http.StatusInternalServerError
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := h.dal.UpdateTopMessage(ctx, request.TicketID, message); err != nil {
|
|
|
|
return errors.New("can not update ticket"), 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)
|
|
|
|
|
2021-05-15 20:10:07 +00:00
|
|
|
ticketID := ctx.Value(tools.ContextURLKey).(string)
|
2021-05-02 22:25:12 +00:00
|
|
|
|
|
|
|
output := make(chan interface{})
|
|
|
|
|
|
|
|
if sess.User == "" {
|
|
|
|
go func() {
|
|
|
|
ticket, err := h.dal.GetTicket4Sess(ctx, ticketID, sess.Session)
|
|
|
|
if err != nil || ticket == nil {
|
|
|
|
output <- errors.New("no tickets 4 session")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := h.dal.YieldMessages(ctx, ticketID, func(message model.Message) error {
|
|
|
|
output <- message
|
|
|
|
|
|
|
|
if err := h.dal.SetShown(ctx, message.ID, sess.Session); err != nil {
|
2021-05-15 20:10:07 +00:00
|
|
|
fmt.Println("2", err)
|
|
|
|
output <- errors.New("cannot show message " + err.Error())
|
2021-05-02 22:25:12 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
2021-05-15 20:10:07 +00:00
|
|
|
fmt.Println("1", err)
|
|
|
|
output <- errors.New("cannot read messages " + err.Error())
|
2021-05-02 22:25:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if err := h.dal.WatchMessages(ctx, ticketID,
|
|
|
|
func(message model.Message) error {
|
|
|
|
output <- message
|
|
|
|
|
|
|
|
if err := h.dal.SetShown(ctx, message.ID, sess.Session); err != nil {
|
2021-05-15 20:10:07 +00:00
|
|
|
fmt.Println("3", err)
|
|
|
|
output <- errors.New("cannot show watch message " + err.Error())
|
2021-05-02 22:25:12 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
2021-05-15 20:10:07 +00:00
|
|
|
fmt.Println("4", err)
|
|
|
|
output <- errors.New("cannot watch messages " + err.Error())
|
2021-05-02 22:25:12 +00:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
} else {
|
|
|
|
role, err := h.ral.GetProfileRole(ctx, sess.User)
|
|
|
|
if err != nil {
|
|
|
|
go h.hasNoRole(output)
|
|
|
|
}
|
|
|
|
|
|
|
|
if role == "admin" || role == "manager" {
|
|
|
|
go func() {
|
|
|
|
|
|
|
|
if err := h.dal.YieldMessages(ctx, ticketID, func(message model.Message) error {
|
|
|
|
output <- message
|
|
|
|
|
|
|
|
if err := h.dal.SetShown(ctx, message.ID, sess.User); err != nil {
|
2021-05-15 20:10:07 +00:00
|
|
|
fmt.Println("2", err)
|
|
|
|
output <- errors.New("cannot show message " + err.Error())
|
2021-05-02 22:25:12 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
2021-05-15 20:10:07 +00:00
|
|
|
fmt.Println("1", err)
|
|
|
|
output <- errors.New("cannot read messages " + err.Error())
|
2021-05-02 22:25:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if err := h.dal.WatchMessages(ctx, ticketID,
|
|
|
|
func(message model.Message) error {
|
|
|
|
output <- message
|
|
|
|
|
|
|
|
if err := h.dal.SetShown(ctx, message.ID, sess.Session); err != nil {
|
2021-05-15 20:10:07 +00:00
|
|
|
fmt.Println("3", err)
|
|
|
|
output <- errors.New("cannot show watch message " + err.Error())
|
2021-05-02 22:25:12 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
2021-05-15 20:10:07 +00:00
|
|
|
fmt.Println("4", err)
|
|
|
|
output <- errors.New("cannot watch messages " + err.Error())
|
2021-05-02 22:25:12 +00:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
} else {
|
|
|
|
go func() {
|
|
|
|
ticket, err := h.dal.GetTicket4User(ctx, ticketID, sess.User)
|
|
|
|
if err != nil || ticket == nil {
|
|
|
|
output <- errors.New("no tickets 4 user")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := h.dal.YieldMessages(ctx, ticketID, func(message model.Message) error {
|
|
|
|
output <- message
|
|
|
|
|
|
|
|
if err := h.dal.SetShown(ctx, message.ID, sess.User); err != nil {
|
2021-05-15 20:10:07 +00:00
|
|
|
fmt.Println("2", err)
|
|
|
|
output <- errors.New("cannot show message " + err.Error())
|
2021-05-02 22:25:12 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
2021-05-15 20:10:07 +00:00
|
|
|
fmt.Println("1", err)
|
|
|
|
output <- errors.New("cannot read messages " + err.Error())
|
2021-05-02 22:25:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if err := h.dal.WatchMessages(ctx, ticketID,
|
|
|
|
func(message model.Message) error {
|
|
|
|
output <- message
|
|
|
|
|
|
|
|
if err := h.dal.SetShown(ctx, message.ID, sess.Session); err != nil {
|
2021-05-15 20:10:07 +00:00
|
|
|
fmt.Println("3", err)
|
|
|
|
output <- errors.New("cannot show watch message " + err.Error())
|
2021-05-02 22:25:12 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}); err != nil {
|
2021-05-15 20:10:07 +00:00
|
|
|
fmt.Println("4", err)
|
|
|
|
output <- errors.New("cannot watch messages " + err.Error())
|
2021-05-02 22:25:12 +00:00
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return output
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *Heruvym) handleOwnMessages(output chan interface{}) {
|
|
|
|
defer close(output)
|
2021-05-11 10:57:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type GetTicketsReq struct {
|
|
|
|
Amount int64 `json:"amt"`
|
|
|
|
Page int64 `json:"page"`
|
|
|
|
Search string `json:"srch"`
|
|
|
|
Status string `json:"status"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *Heruvym) GetTickets(
|
|
|
|
ctx context.Context,
|
|
|
|
request GetTicketsReq) ([]model.Ticket, int) {
|
|
|
|
result, err := h.dal.GetTicketPage(ctx,
|
|
|
|
request.Status,
|
|
|
|
request.Search,
|
|
|
|
request.Amount,
|
|
|
|
request.Page,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return nil, http.StatusNoContent
|
|
|
|
}
|
|
|
|
|
|
|
|
return *result, http.StatusOK
|
|
|
|
}
|
|
|
|
|
|
|
|
type GetMessagesReq struct {
|
|
|
|
Amount int64 `json:"amt"`
|
|
|
|
Page int64 `json:"page"`
|
|
|
|
Search string `json:"srch"`
|
|
|
|
TicketID string `json:"ticket"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *Heruvym) GetMessages(
|
|
|
|
ctx context.Context,
|
|
|
|
request GetMessagesReq) ([]model.Message, int) {
|
|
|
|
result, err := h.dal.GetMessagesPage(ctx,
|
|
|
|
request.Search,
|
|
|
|
request.TicketID,
|
|
|
|
request.Amount,
|
|
|
|
request.Page,
|
|
|
|
)
|
|
|
|
if err != nil {
|
|
|
|
return nil, http.StatusNoContent
|
|
|
|
}
|
|
|
|
|
|
|
|
return result, http.StatusOK
|
|
|
|
}
|
|
|
|
|
|
|
|
type CloseTicketReq struct {
|
|
|
|
TicketID string `json:"ticket"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *Heruvym) CloseTicket(ctx context.Context, req CloseTicketReq) (error, int) {
|
|
|
|
if err := h.dal.SetTicketStatus(ctx, req.TicketID, model.StateClose); err != nil {
|
|
|
|
return err, http.StatusBadRequest
|
|
|
|
}
|
2021-05-02 22:25:12 +00:00
|
|
|
|
2021-05-11 10:57:58 +00:00
|
|
|
return nil, http.StatusOK
|
|
|
|
}
|
|
|
|
|
|
|
|
type VoteReq struct {
|
|
|
|
TicketID string `json:"ticket"`
|
|
|
|
Rate int `json:"rate"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *Heruvym) Vote(ctx context.Context, req VoteReq) (error, int) {
|
|
|
|
if err := h.dal.SetRate(ctx, req.TicketID, req.Rate); err != nil {
|
|
|
|
return err, http.StatusBadRequest
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, http.StatusOK
|
|
|
|
}
|
|
|
|
|
|
|
|
type PickReq struct {
|
|
|
|
TicketID string `json:"ticket"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *Heruvym) Pick(ctx context.Context, req PickReq) (error, int) {
|
|
|
|
sess := jwt_adapter.Get(ctx)
|
|
|
|
if err := h.dal.SetAnswerer(ctx, req.TicketID, sess.User); err != nil {
|
|
|
|
return err, http.StatusBadRequest
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, http.StatusOK
|
|
|
|
}
|
|
|
|
|
|
|
|
type DelegateReq struct {
|
|
|
|
TicketID string `json:"ticket"`
|
|
|
|
AnswererID string `json:"answerer"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *Heruvym) Delegate(ctx context.Context, req DelegateReq) (error, int) {
|
|
|
|
if err := h.dal.SetAnswerer(ctx, req.TicketID, req.AnswererID); err != nil {
|
|
|
|
return err, http.StatusBadRequest
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, http.StatusOK
|
2021-05-02 22:25:12 +00:00
|
|
|
}
|