func GetChatMessageReadHandler(start_addr string, notifier *ntf.Notifier, db *d.MainDb, config c.ChatConfig) http.Handler { m := GetMartini(config.Name, config.CompanyId, start_addr, db) m.Post(start_addr, web.LoginRequired, web.AutHandler.CheckReadRights(config.CompanyId), func(render render.Render, req *http.Request) { type Readed struct { From string `json:"from"` } data, err := ioutil.ReadAll(req.Body) if err != nil { log.Printf("CS QE E: errror at reading req body %v", err) render.JSON(500, map[string]interface{}{"error": err}) return } readed := Readed{} err = json.Unmarshal(data, &readed) if err != nil { log.Printf("CS QE E: at unmarshal json messages %v\ndata:%s", err, data) render.JSON(500, map[string]interface{}{"error": err}) return } err = db.Messages.SetAllMessagesRead(readed.From, config.CompanyId) if err != nil { log.Printf("CS QE E: at unmarshal json messages %v\ndata:%s", err, data) render.JSON(500, map[string]interface{}{"error": err}) return } render.JSON(200, map[string]interface{}{"ok": true}) }) return m }
func GetChatContactsChangeHandler(start_addr string, notifier *ntf.Notifier, db *d.MainDb, config c.ChatConfig) http.Handler { m := GetMartini(config.Name, config.CompanyId, start_addr, db) m.Post(start_addr, web.LoginRequired, web.AutHandler.CheckWriteRights(config.CompanyId), func(render render.Render, req *http.Request) { type NewContactName struct { Id string `json:"id"` NewName string `json:"new_name"` } ncn := NewContactName{} request_body, err := ioutil.ReadAll(req.Body) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": "can not read request body"}) return } err = json.Unmarshal(request_body, &ncn) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": fmt.Sprintf("can not unmarshal request body %v \n %s", err, request_body)}) return } err = db.Users.SetUserShowedName(ncn.Id, ncn.NewName) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": err}) return } render.JSON(200, map[string]interface{}{"ok": true}) }) return m }
func GetChatUnreadMessagesHandler(start_addr string, notifier *ntf.Notifier, db *d.MainDb, config c.ChatConfig) http.Handler { m := GetMartini(config.Name, config.CompanyId, start_addr, db) m.Post(start_addr, func(render render.Render, req *http.Request) { type NewMessagesReq struct { For string `json:"m_for"` } nmReq := NewMessagesReq{} request_body, err := ioutil.ReadAll(req.Body) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": "can not read request body"}) return } err = json.Unmarshal(request_body, &nmReq) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": fmt.Sprintf("can not unmarshal request body %v \n %s", err, request_body)}) return } result, err := get_messages(nmReq.For, config.CompanyId, db) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": fmt.Sprintf("error in db: %v", err)}) } render.JSON(200, map[string]interface{}{"messages": result}) }) return m }
func GetMessageAdditionalFunctionsHandler(start_addr string, notifier *ntf.Notifier, db *d.MainDb, config c.ChatConfig, chc *CoffeeHouseConfiguration) http.Handler { m := GetMartini(config.Name, config.CompanyId, start_addr, db) m.Post(start_addr, web.LoginRequired, web.AutHandler.CheckReadRights(config.CompanyId), web.AutHandler.CheckWriteRights(config.CompanyId), func(render render.Render, req *http.Request) { cfd := CoffeeFunctionData{} request_body, err := ioutil.ReadAll(req.Body) if err != nil { log.Printf("Coffee serv: error at read data: %v", err) render.JSON(500, map[string]interface{}{"ok": false, "detail": "can not read request body"}) return } err = json.Unmarshal(request_body, &cfd) if err != nil { log.Printf("Coffee serv: error at unmarshal json: %v", err) render.JSON(500, map[string]interface{}{"ok": false, "detail": fmt.Sprintf("can not unmarshal request body %v \n %s", err, request_body)}) return } log.Printf("Coffee serv: message function: %+v", cfd) orderId, err := strconv.ParseInt(cfd.Context.OrderId, 10, 64) if err != nil { log.Printf("Coffee serv: error at parse int ") } var result string switch cfd.Action { case "cancel": commands := getCommands(chc, false, false) notifier.NotifyTextWithCommands(cfd.Context.UserName, "Ваш заказ отменили!", commands) db.Orders.SetActive(orderId, cfd.Context.CompanyName, false) result = "Отменено" case "start": notifier.NotifyText(cfd.Context.UserName, "Ваш заказ в процессе приготовления!") result = "В процессе" case "end": notifier.NotifyText(cfd.Context.UserName, "Ваш заказ готов!") db.Orders.SetActive(orderId, cfd.Context.CompanyName, false) result = "Окончено" case "confirm": notifier.NotifyText(cfd.Context.UserName, "Вы уверены что хотите сделать заказ?") result = "Подтверждение отправлено" } db.Messages.SetMessageFunctionUsed(cfd.MessageId, cfd.Action) db.Messages.UpdateMessageRelatedOrderState(cfd.MessageId, result) found, err := db.Orders.GetByOwner(cfd.Context.UserName, cfd.Context.CompanyName, true) render.JSON(200, map[string]interface{}{"ok": true, "result": result, "user_have_active_orders": found != nil}) }) return m }
func GetChatContactsHandler(start_addr string, notifier *ntf.Notifier, db *d.MainDb, config c.ChatConfig) http.Handler { m := GetMartini(config.Name, config.CompanyId, start_addr, db) m.Post(start_addr, func(render render.Render, req *http.Request) { type NewContactsReq struct { After int64 `json:"after"` Exist []string `json:"exist"` } cr := NewContactsReq{} request_body, err := ioutil.ReadAll(req.Body) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": "can not read request body"}) return } err = json.Unmarshal(request_body, &cr) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": fmt.Sprintf("can not unmarshal request body %v \n %s", err, request_body)}) return } contacts, err := getContacts(db, config.CompanyId) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": fmt.Sprintf("db err body %v", err)}) return } new_contacts := []usrs.Contact{} old_contacts := []usrs.Contact{} for _, contact := range contacts { if u.InS(contact.ID, cr.Exist) { if contact.NewMessagesCount > 0 { old_contacts = append(old_contacts, contact) } } else { new_contacts = append(new_contacts, contact) } } render.JSON(200, map[string]interface{}{ "ok": true, "new": new_contacts, "old": old_contacts, "next_": time.Now().Unix(), }) }) return m }
func GetChatSendHandler(start_addr string, notifier *ntf.Notifier, db *d.MainDb, config c.ChatConfig, cs *ChatStorage) http.Handler { m := GetMartini(config.Name, config.CompanyId, start_addr, db) m.Post(start_addr, web.LoginRequired, web.AutHandler.CheckWriteRights(config.CompanyId), func(render render.Render, req *http.Request) { type MessageFromF struct { From string `json:"from"` To string `json:"to"` Body string `json:"body"` } data, err := ioutil.ReadAll(req.Body) if err != nil { log.Printf("CS QE E: errror at reading req body %v", err) render.JSON(500, map[string]interface{}{"error": err}) return } message := MessageFromF{} err = json.Unmarshal(data, &message) if err != nil { log.Printf("CS QE E: at unmarshal json messages %v\ndata:%s", err, data) render.JSON(500, map[string]interface{}{"error": err}) return } log.Printf("CS message to send: %v", message) var messageSID string if message.From != "" && message.To != "" && message.Body != "" { if message.To == ALL { peoples, _ := cs.GetUsersOfCompany(config.CompanyId) notifier.SendMessageToPeople(peoples, message.Body) } else { user, _ := db.Users.GetUserById(message.To) if user != nil { db.Messages.SetMessagesRead(user.UserId) _, resultMessage, _ := notifier.NotifyText(message.To, message.Body) resultMessage, _ = db.Messages.GetMessageByMessageId(resultMessage.MessageID) messageSID = resultMessage.SID } db.Messages.SetMessagesAnswered(message.To, config.CompanyId, config.CompanyId) } } else { render.Redirect("/chat") } render.JSON(200, map[string]interface{}{"ok": true, "message": d.NewMessageForWeb(messageSID, message.From, message.To, message.Body)}) }) return m }
func main() { // parse command line var configFile string flag.StringVar(&configFile, "config", "/etc/codegrinder/config.json", "Path to the config file") var ta, daycare bool flag.BoolVar(&ta, "ta", true, "Serve the TA role") flag.BoolVar(&daycare, "daycare", true, "Serve the daycare role") flag.Parse() if !ta && !daycare { log.Fatalf("must run at least one role (ta/daycare)") } // set config defaults Config.ToolName = "CodeGrinder" Config.ToolID = "codegrinder" Config.ToolDescription = "Programming exercises with grading" Config.LetsEncryptCache = "/etc/codegrinder/letsencrypt.cache" Config.PostgresHost = "/var/run/postgresql" Config.PostgresPort = "" Config.PostgresUsername = os.Getenv("USER") Config.PostgresPassword = "" Config.PostgresDatabase = os.Getenv("USER") // load config file if raw, err := ioutil.ReadFile(configFile); err != nil { log.Fatalf("failed to load config file %q: %v", configFile, err) } else if err := json.Unmarshal(raw, &Config); err != nil { log.Fatalf("failed to parse config file: %v", err) } Config.SessionSecret = unBase64(Config.SessionSecret) Config.DaycareSecret = unBase64(Config.DaycareSecret) // set up martini r := martini.NewRouter() m := martini.New() m.Logger(log.New(os.Stderr, "", log.LstdFlags)) m.Use(martini.Logger()) m.Use(martini.Recovery()) m.Use(martini.Static(Config.StaticDir, martini.StaticOptions{SkipLogging: true})) m.MapTo(r, (*martini.Routes)(nil)) m.Action(r.Handle) m.Use(render.Renderer(render.Options{IndentJSON: true})) store := sessions.NewCookieStore([]byte(Config.SessionSecret)) m.Use(sessions.Sessions(CookieName, store)) // sessions expire June 30 and December 31 go func() { for { now := time.Now() // expire at the end of the calendar year expires := time.Date(now.Year(), time.December, 31, 23, 59, 59, 0, time.Local) if expires.Sub(now).Hours() < 14*24 { // are we within 2 weeks of the end of the year? probably prepping for spring, // so expire next June 30 instead expires = time.Date(now.Year()+1, time.June, 30, 23, 59, 59, 0, time.Local) } else if expires.Sub(now).Hours() > (365/2+14)*24 { // is it still more than 2 weeks before June 30? probably in spring semester, // so expire this June 30 instead expires = time.Date(now.Year(), time.June, 30, 23, 59, 59, 0, time.Local) } store.Options(sessions.Options{Path: "/", Secure: true, MaxAge: int(expires.Sub(now).Seconds())}) time.Sleep(11 * time.Minute) } }() // set up TA role if ta { // make sure relevant secrets are included in config file if Config.LTISecret == "" { log.Fatalf("cannot run TA role with no LTISecret in the config file") } if Config.SessionSecret == "" { log.Fatalf("cannot run TA role with no SessionSecret in the config file") } if Config.DaycareSecret == "" { log.Fatalf("cannot run with no DaycareSecret in the config file") } // set up the database db := setupDB(Config.PostgresHost, Config.PostgresPort, Config.PostgresUsername, Config.PostgresPassword, Config.PostgresDatabase) // martini service: wrap handler in a transaction withTx := func(c martini.Context, w http.ResponseWriter) { // start a transaction tx, err := db.Begin() if err != nil { loggedHTTPErrorf(w, http.StatusInternalServerError, "db error starting transaction: %v", err) return } // pass it on to the main handler c.Map(tx) c.Next() // was it a successful result? rw := w.(martini.ResponseWriter) if rw.Status() < http.StatusBadRequest { // commit the transaction if err := tx.Commit(); err != nil { loggedHTTPErrorf(w, http.StatusInternalServerError, "db error committing transaction: %v", err) return } } else { // rollback log.Printf("rolling back transaction") if err := tx.Rollback(); err != nil { loggedHTTPErrorf(w, http.StatusInternalServerError, "db error rolling back transaction: %v", err) return } } } // martini service: to require an active logged-in session auth := func(w http.ResponseWriter, session sessions.Session) { if userID := session.Get("id"); userID == nil { loggedHTTPErrorf(w, http.StatusUnauthorized, "authentication: no user ID found in session") return } } // martini service: include the current logged-in user (requires withTx and auth) withCurrentUser := func(c martini.Context, w http.ResponseWriter, tx *sql.Tx, session sessions.Session) { rawID := session.Get("id") if rawID == nil { loggedHTTPErrorf(w, http.StatusInternalServerError, "cannot find user ID in session") return } userID, ok := rawID.(int64) if !ok { session.Clear() loggedHTTPErrorf(w, http.StatusInternalServerError, "error extracting user ID from session") return } // load the user record user := new(User) if err := meddler.Load(tx, "users", user, userID); err != nil { if err == sql.ErrNoRows { loggedHTTPErrorf(w, http.StatusUnauthorized, "user %d not found", userID) return } loggedHTTPErrorf(w, http.StatusInternalServerError, "db error: %v", err) return } // map the current user to the request context c.Map(user) } // martini service: require logged in user to be an administrator (requires withCurrentUser) administratorOnly := func(w http.ResponseWriter, currentUser *User) { if !currentUser.Admin { loggedHTTPErrorf(w, http.StatusUnauthorized, "user %d (%s) is not an administrator", currentUser.ID, currentUser.Email) return } } // martini service: require logged in user to be an author or administrator (requires withCurrentUser) authorOnly := func(w http.ResponseWriter, tx *sql.Tx, currentUser *User) { if currentUser.Admin { return } if !currentUser.Author { loggedHTTPErrorf(w, http.StatusUnauthorized, "user %d (%s) is not an author", currentUser.ID, currentUser.Name) return } } // version r.Get("/v2/version", func(w http.ResponseWriter, render render.Render) { render.JSON(http.StatusOK, &CurrentVersion) }) // LTI r.Get("/v2/lti/config.xml", GetConfigXML) r.Post("/v2/lti/problem_sets", binding.Bind(LTIRequest{}), checkOAuthSignature, withTx, LtiProblemSets) r.Post("/v2/lti/problem_sets/:unique", binding.Bind(LTIRequest{}), checkOAuthSignature, withTx, LtiProblemSet) // problem bundles--for problem creation only r.Post("/v2/problem_bundles/unconfirmed", auth, withTx, withCurrentUser, authorOnly, binding.Json(ProblemBundle{}), PostProblemBundleUnconfirmed) r.Post("/v2/problem_bundles/confirmed", auth, withTx, withCurrentUser, authorOnly, binding.Json(ProblemBundle{}), PostProblemBundleConfirmed) r.Put("/v2/problem_bundles/:problem_id", auth, withTx, withCurrentUser, authorOnly, binding.Json(ProblemBundle{}), PutProblemBundle) // problem set bundles--for problem set creation only r.Post("/v2/problem_set_bundles", auth, withTx, withCurrentUser, authorOnly, binding.Json(ProblemSetBundle{}), PostProblemSetBundle) // problem types r.Get("/v2/problem_types", auth, GetProblemTypes) r.Get("/v2/problem_types/:name", auth, GetProblemType) // problems r.Get("/v2/problems", auth, withTx, withCurrentUser, GetProblems) r.Get("/v2/problems/:problem_id", auth, withTx, withCurrentUser, GetProblem) r.Get("/v2/problems/:problem_id/steps", auth, withTx, withCurrentUser, GetProblemSteps) r.Get("/v2/problems/:problem_id/steps/:step", auth, withTx, withCurrentUser, GetProblemStep) r.Delete("/v2/problems/:problem_id", auth, withTx, withCurrentUser, administratorOnly, DeleteProblem) // problem sets r.Get("/v2/problem_sets", auth, withTx, withCurrentUser, GetProblemSets) r.Get("/v2/problem_sets/:problem_set_id", auth, withTx, withCurrentUser, GetProblemSet) r.Get("/v2/problem_sets/:problem_set_id/problems", auth, withTx, withCurrentUser, GetProblemSetProblems) r.Delete("/v2/problem_sets/:problem_set_id", auth, withTx, withCurrentUser, administratorOnly, DeleteProblemSet) // courses r.Get("/v2/courses", auth, withTx, withCurrentUser, GetCourses) r.Get("/v2/courses/:course_id", auth, withTx, withCurrentUser, GetCourse) r.Delete("/v2/courses/:course_id", auth, withTx, withCurrentUser, administratorOnly, DeleteCourse) // users r.Get("/v2/users", auth, withTx, withCurrentUser, GetUsers) r.Get("/v2/users/me", auth, withTx, withCurrentUser, GetUserMe) r.Get("/v2/users/me/cookie", auth, GetUserMeCookie) r.Get("/v2/users/:user_id", auth, withTx, withCurrentUser, GetUser) r.Get("/v2/courses/:course_id/users", auth, withTx, withCurrentUser, GetCourseUsers) r.Delete("/v2/users/:user_id", auth, withTx, withCurrentUser, administratorOnly, DeleteUser) // assignments r.Get("/v2/users/:user_id/assignments", auth, withTx, withCurrentUser, GetUserAssignments) r.Get("/v2/courses/:course_id/users/:user_id/assignments", auth, withTx, withCurrentUser, GetCourseUserAssignments) r.Get("/v2/assignments/:assignment_id", auth, withTx, withCurrentUser, GetAssignment) r.Delete("/v2/assignments/:assignment_id", auth, withTx, withCurrentUser, administratorOnly, DeleteAssignment) // commits r.Get("/v2/assignments/:assignment_id/problems/:problem_id/commits/last", auth, withTx, withCurrentUser, GetAssignmentProblemCommitLast) r.Get("/v2/assignments/:assignment_id/problems/:problem_id/steps/:step/commits/last", auth, withTx, withCurrentUser, GetAssignmentProblemStepCommitLast) r.Delete("/v2/commits/:commit_id", auth, withTx, withCurrentUser, administratorOnly, DeleteCommit) // commit bundles r.Post("/v2/commit_bundles/unsigned", auth, withTx, withCurrentUser, binding.Json(CommitBundle{}), PostCommitBundlesUnsigned) r.Post("/v2/commit_bundles/signed", auth, withTx, withCurrentUser, binding.Json(CommitBundle{}), PostCommitBundlesSigned) } // set up daycare role if daycare { // make sure relevant secrets are included in config file if Config.DaycareSecret == "" { log.Fatalf("cannot run with no DaycareSecret in the config file") } // attach to docker and try a ping var err error dockerClient, err = docker.NewVersionedClient("unix:///var/run/docker.sock", "1.18") if err != nil { log.Fatalf("NewVersionedClient: %v", err) } if err = dockerClient.Ping(); err != nil { log.Fatalf("Ping: %v", err) } r.Get("/v2/sockets/:problem_type/:action", SocketProblemTypeAction) } // start redirecting http calls to https log.Printf("starting http -> https forwarder") go http.ListenAndServe(":http", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // get the address of the client addr := r.Header.Get("X-Real-IP") if addr == "" { addr = r.Header.Get("X-Forwarded-For") if addr == "" { addr = r.RemoteAddr } } // make sure the request is for the right host name if Config.Hostname != r.Host { loggedHTTPErrorf(w, http.StatusNotFound, "http request to invalid host: %s", r.Host) return } var u url.URL = *r.URL u.Scheme = "https" u.Host = Config.Hostname log.Printf("redirecting http request from %s to %s", addr, u.String()) http.Redirect(w, r, u.String(), http.StatusMovedPermanently) })) // set up letsencrypt lem := letsencrypt.Manager{} if err := lem.CacheFile(Config.LetsEncryptCache); err != nil { log.Fatalf("Setting up LetsEncrypt: %v", err) } lem.SetHosts([]string{Config.Hostname}) if !lem.Registered() { log.Printf("registering with letsencrypt") if err := lem.Register(Config.LetsEncryptEmail, nil); err != nil { log.Fatalf("Registering with LetsEncrypt: %v", err) } } // start the https server log.Printf("accepting https connections") server := &http.Server{ Addr: ":https", Handler: m, TLSConfig: &tls.Config{ MinVersion: tls.VersionTLS10, GetCertificate: lem.GetCertificate, }, } if err := server.ListenAndServeTLS("", ""); err != nil { log.Fatalf("ListenAndServeTLS: %v", err) } }
func Run(config c.QuestConfig, qs *QuestStorage, ntf *ntf.Notifier, additionalNotifier *ntf.Notifier) { m := martini.New() m.Use(w.NonJsonLogger()) m.Use(martini.Recovery()) m.Use(render.Renderer(render.Options{ Directory: "templates/quests", Layout: "layout", Extensions: []string{".tmpl", ".html"}, Charset: "UTF-8", IndentJSON: true, IndentXML: true, Funcs: []template.FuncMap{ template.FuncMap{ "eq_s": func(a, b string) bool { return a == b }, "stamp_date": func(t time.Time) string { return t.Format(time.Stamp) }, }, }, })) m.Use(auth.BasicFunc(func(username, password string) bool { pwd, ok := users[username] return ok && pwd == password })) m.Use(martini.Static("static")) r := martini.NewRouter() r.Get("/", func(user auth.User, render render.Render) { render.HTML(200, "readme", map[string]interface{}{}) }) r.Get("/new_keys", func(render render.Render) { render.HTML(200, "new_keys", GetKeysErrorInfo("", qs)) }) r.Post("/add_key", func(user auth.User, render render.Render, request *http.Request) { start_key := strings.TrimSpace(request.FormValue("start-key")) next_key := strings.TrimSpace(request.FormValue("next-key")) description := request.FormValue("description") log.Printf("QUESTS WEB add key %s -> %s -> %s", start_key, description, next_key) if start_key != "" && description != "" { key, err := qs.AddStep(start_key, description, next_key) if key != nil && err != nil { render.HTML(200, "new_keys", GetKeysErrorInfo("Такой ключ уже существует. Используйте изменение ключа если хотите его изменить.", qs)) return } } else { render.HTML(200, "new_keys", GetKeysErrorInfo("Невалидные значения ключа или ответа", qs)) return } render.Redirect("/new_keys") }) r.Post("/delete_key/:key", func(params martini.Params, render render.Render) { key := params["key"] err := qs.DeleteStep(key) log.Printf("QUESTS WEB will delete %v (%v)", key, err) render.Redirect("/new_keys") }) r.Post("/update_key/:key", func(params martini.Params, render render.Render, request *http.Request) { key_id := params["key"] start_key := strings.TrimSpace(request.FormValue("start-key")) next_key := strings.TrimSpace(request.FormValue("next-key")) description := request.FormValue("description") err := qs.UpdateStep(key_id, start_key, description, next_key) log.Printf("QUESTS WEB was update key %s %s %s %s\n err? %v", key_id, start_key, description, next_key, err) render.Redirect("/new_keys") }) r.Get("/delete_key_all", func(render render.Render) { qs.Steps.RemoveAll(bson.M{}) render.Redirect("/new_keys") }) xlsFileReg := regexp.MustCompile(".+\\.xlsx?") r.Post("/load/up", func(render render.Render, request *http.Request) { file, header, err := request.FormFile("file") log.Printf("QS: Form file information: file: %+v \nheader:%v, %v\nerr:%v", file, header.Filename, header.Header, err) if err != nil { render.HTML(200, "new_keys", GetKeysErrorInfo(fmt.Sprintf("Ошибка загрузки файлика: %v", err), qs)) return } defer file.Close() data, err := ioutil.ReadAll(file) if err != nil { render.HTML(200, "new_keys", GetKeysErrorInfo(fmt.Sprintf("Ошибка загрузки файлика: %v", err), qs)) return } if xlsFileReg.MatchString(header.Filename) { xlFile, err := xlsx.OpenBinary(data) if err != nil || xlFile == nil { render.HTML(200, "new_keys", GetKeysErrorInfo(fmt.Sprintf("Ошибка обработки файлика: %v", err), qs)) return } skip_rows, errsr := strconv.Atoi(request.FormValue("skip-rows")) skip_cols, errsc := strconv.Atoi(request.FormValue("skip-cols")) if errsr != nil || errsc != nil { render.HTML(200, "new_keys", GetKeysErrorInfo("Не могу распознать количества столбцов и строк пропускаемых :(", qs)) return } log.Printf("QS: Will process file: %+v, err: %v \n with skipped rows: %v, cols: %v", xlFile, err, skip_rows, skip_cols) parse_res, errp := w.ParseExportXlsx(xlFile, skip_rows, skip_cols) if errp != nil { render.HTML(200, "new_keys", GetKeysErrorInfo("Ошибка в парсинге файла:(", qs)) return } res, val_err := ValidateKeys(parse_res) if val_err != nil { render.HTML(200, "new_keys", GetKeysErrorInfo(val_err.Error(), qs)) return } for _, prel := range parse_res { qs.AddStep(prel[0], prel[1], prel[2]) } render.HTML(200, "new_keys", GetKeysTeamsInfo(res, qs)) } else { render.HTML(200, "new_keys", GetKeysErrorInfo("Файл имеет не то расширение :(", qs)) } render.Redirect("/new_keys") }) r.Get("/chat", func(render render.Render, params martini.Params, req *http.Request) { var with string result_data := map[string]interface{}{} query := req.URL.Query() for key, value := range query { if key == "with" && len(value) > 0 { with = value[0] log.Printf("QSERV: with found is: %v", with) break } } type Collocutor struct { IsTeam bool IsMan bool IsAll bool IsWinner bool WinTime string Info interface{} Name string } collocutor := Collocutor{} var messages []Message if with != ALL && with != ALL_TEAM_MEMBERS { if team, _ := qs.GetTeamByName(with); team != nil { type TeamInfo struct { FoundedKeys []string Members []TeamMember AllKeys []Step } collocutor.Name = team.Name collocutor.IsTeam = true collocutor.IsWinner = team.Winner if collocutor.IsWinner { tm := time.Unix(team.WinTime, 0) collocutor.WinTime = tm.Format("Mon 15:04:05") } members, _ := qs.GetMembersOfTeam(team.Name) keys, _ := qs.GetSteps(bson.M{"for_team": team.Name}) keys = SortSteps(keys) collocutor.Info = TeamInfo{FoundedKeys: team.FoundKeys, Members: members, AllKeys: keys} messages, _ = qs.GetMessages(bson.M{ "$or": []bson.M{ bson.M{"from": team.Name}, bson.M{"to": team.Name}, }, }) } else { if peoples, _ := qs.GetPeoples(bson.M{"user_id": with}); len(peoples) > 0 { man := peoples[0] collocutor.IsMan = true collocutor.Name = man.Name collocutor.Info = man messages, _ = qs.GetMessages(bson.M{ "$or": []bson.M{ bson.M{"from": man.UserId}, bson.M{"to": man.UserId}, }, }) for i, _ := range messages { if messages[i].From != ME { messages[i].From = man.Name } } } else { with = "all" } } } if strings.HasPrefix(with, "all") { collocutor.IsAll = true collocutor.Name = with messages, _ = qs.GetMessages(bson.M{"to": with}) } //log.Printf("QS i return this messages: %+v", messages) result_data["with"] = with result_data["collocutor"] = collocutor if len(messages) > 100 { messages = messages[0:100] } result_data["messages"] = messages qs.SetMessagesRead(with) all_teams, _ := qs.GetAllTeams() if contacts, err := qs.GetContacts(all_teams); err == nil { result_data["contacts"] = contacts } render.HTML(200, "chat", result_data) }) r.Post("/send", func(render render.Render, req *http.Request) { type MessageFromF struct { From string `json:"from"` To string `json:"to"` Body string `json:"body"` } data, err := ioutil.ReadAll(req.Body) if err != nil { log.Printf("QS QE E: errror at reading req body %v", err) render.JSON(500, map[string]interface{}{"error": err}) return } message := MessageFromF{} err = json.Unmarshal(data, &message) if err != nil { log.Printf("QS QE E: at unmarshal json messages %v\ndata:%s", err, data) render.JSON(500, map[string]interface{}{"error": err}) return } log.Printf("QS I see this data for send message from f:\n %+v", message) var result Message if message.From != "" && message.To != "" && message.Body != "" { if message.To == "all" { peoples, _ := qs.GetPeoples(bson.M{}) log.Printf("QSERV: will send [%v] to all %v peoples", message.Body, len(peoples)) SendMessagesToPeoples(peoples, ntf, message.Body) } else if message.To == "all_team_members" { peoples, _ := qs.GetAllTeamMembers() log.Printf("QSERV: will send [%v] to all team members %v peoples", message.Body, len(peoples)) SendMessagesToPeoples(peoples, ntf, message.Body) } else { team, _ := qs.GetTeamByName(message.To) if team == nil { man, _ := qs.GetManByUserId(message.To) if man != nil { log.Printf("QSERV: will send [%v] to %v", message.Body, man.UserId) go ntf.NotifyText(man.UserId, message.Body) } } else { peoples, _ := qs.GetMembersOfTeam(team.Name) log.Printf("QSERV: will send [%v] to team members of %v team to %v peoples", message.Body, team.Name, len(peoples)) SendMessagesToPeoples(peoples, ntf, message.Body) } } result, err = qs.StoreMessage(message.From, message.To, message.Body, false) if err != nil { log.Printf("QSERV: error at storing message %v", err) render.JSON(200, map[string]interface{}{"ok": false}) return } result.TimeFormatted = result.Time.Format(time.Stamp) } else { render.JSON(200, map[string]interface{}{"ok": false}) } render.JSON(200, map[string]interface{}{"ok": true, "message": result}) }) r.Post("/messages", func(render render.Render, req *http.Request) { type NewMessagesReq struct { For string `json:"m_for"` After int64 `json:"after"` } q := NewMessagesReq{} request_body, err := ioutil.ReadAll(req.Body) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": "can not read request body"}) return } err = json.Unmarshal(request_body, &q) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": fmt.Sprintf("can not unmarshal request body %v \n %s", err, request_body)}) return } messages, err := qs.GetMessages(bson.M{"from": q.For, "time_stamp": bson.M{"$gt": q.After}}) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": fmt.Sprintf("error in db: %v", err)}) return } for i, message := range messages { team, _ := qs.GetTeamByName(message.From) if team != nil { messages[i].From = team.Name } else { man, _ := qs.GetManByUserId(message.From) if man != nil { messages[i].From = man.Name } } messages[i].TimeFormatted = message.Time.Format(time.Stamp) } render.JSON(200, map[string]interface{}{"messages": messages, "next_": time.Now().Unix()}) }) r.Post("/contacts", func(render render.Render, req *http.Request) { type NewContactsReq struct { After int64 `json:"after"` Exist []string `json:"exist"` } cr := NewContactsReq{} request_body, err := ioutil.ReadAll(req.Body) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": "can not read request body"}) return } err = json.Unmarshal(request_body, &cr) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": fmt.Sprintf("can not unmarshal request body %v \n %s", err, request_body)}) return } contacts, err := qs.GetContactsAfter(cr.After) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": err}) return } new_contacts := []Contact{} old_contacts := []Contact{} for _, contact := range contacts { if utils.InS(contact.ID, cr.Exist) { old_contacts = append(old_contacts, contact) } else { new_contacts = append(new_contacts, contact) } } render.JSON(200, map[string]interface{}{ "ok": true, "new": new_contacts, "old": old_contacts, "next_": time.Now().Unix(), }) }) r.Get("/manage", func(render render.Render, req *http.Request) { configResult, err := qs.GetMessageConfiguration(config.Chat.CompanyId) if err != nil { log.Printf("QS E: Can not load quest configuration for %v, because: %v", config.Chat.CompanyId, err) } render.HTML(200, "manage", map[string]interface{}{"config": configResult}) }) r.Post("/manage", binding.Bind(QuestMessageConfiguration{}), func(qmc QuestMessageConfiguration, ren render.Render, req *http.Request) { if req.FormValue("to-winner-on") == "on" { qmc.EndMessageForWinnersActive = true } if req.FormValue("to-not-winner-on") == "on" { qmc.EndMessageForNotWinnersActive = true } if req.FormValue("to-all-on") == "on" { qmc.EndMessageForAllActive = true } log.Printf("QS Manage: %+v", qmc) qmc.CompanyId = config.Chat.CompanyId err := qs.SetMessageConfiguration(qmc, true) if err != nil { log.Printf("QS ERROR at update quest message configuration for [%v], because: %v", qmc.CompanyId, err) } ren.Redirect("/manage", 302) }) r.Post("/start_quest", func(ren render.Render) { qmc, err := qs.GetMessageConfiguration(config.Chat.CompanyId) if err != nil { log.Printf("QS E: Can not load quest configuration for %v, because: %v", config.Chat.CompanyId, err) ren.JSON(500, map[string]interface{}{"ok": false, "detail": err}) return } if qmc.Started == false { qs.SetQuestStarted(config.Chat.CompanyId, true) ren.JSON(200, map[string]interface{}{"ok": true}) } else { ren.JSON(200, map[string]interface{}{"ok": false, "detail": "already started"}) } }) r.Post("/stop_quest", func(ren render.Render) { qmc, err := qs.GetMessageConfiguration(config.Chat.CompanyId) if err != nil { log.Printf("QS E: Can not load quest configuration for %v, because: %v", config.Chat.CompanyId, err) ren.JSON(500, map[string]interface{}{"ok": false, "detail": err}) return } if qmc.Started == true { qs.SetQuestStarted(config.Chat.CompanyId, false) teams, err := qs.GetAllTeams() if err != nil { log.Printf("QS QE E: errror at getting teams %v", err) } if qmc.EndMessageForAllActive == true { for _, team := range teams { log.Printf("QS Will send message to team: %v from Klichat", team.Name) members, _ := qs.GetMembersOfTeam(team.Name) SendMessagesToPeoples(members, additionalNotifier, qmc.EndMessageForAll) } } if qmc.EndMessageForWinnersActive == true { for _, team := range teams { if team.Winner == true { log.Printf("QS Will send WIN message to team: %v from quest", team.Name) members, _ := qs.GetMembersOfTeam(team.Name) SendMessagesToPeoples(members, ntf, qmc.EndMessageForWinners) } } } if qmc.EndMessageForNotWinnersActive == true { for _, team := range teams { if team.Winner == false { log.Printf("QS Will send NOT WIN message to team: %v from quest", team.Name) members, _ := qs.GetMembersOfTeam(team.Name) SendMessagesToPeoples(members, ntf, qmc.EndMessageForNotWinners) } } } ren.JSON(200, map[string]interface{}{"ok": true}) } else { ren.JSON(200, map[string]interface{}{"ok": false, "detail": "already stopped"}) } }) r.Get("/delete_chat/:between", func(params martini.Params, render render.Render, req *http.Request) { between := params["between"] qs.Messages.RemoveAll(bson.M{"$or": []bson.M{bson.M{"from": between}, bson.M{"to": between}}}) render.Redirect(fmt.Sprintf("/chat?with=%v", between)) }) r.Post("/send_messages_at_quest_end", func(render render.Render, req *http.Request) { type Messages struct { Text string `json:"text"` Teams []string `json:"teams"` Exclude bool `json:"exclude"` } messages := Messages{} data, err := ioutil.ReadAll(req.Body) if err != nil { log.Printf("QS QE E: errror at reading req body %v", err) render.JSON(500, map[string]interface{}{"error": err}) return } err = json.Unmarshal(data, &messages) if err != nil { log.Printf("QS QE E: at unmarshal json messages %v", err) render.JSON(500, map[string]interface{}{"error": err}) return } log.Printf("QS I see this data for send messages at quest end:\n %+v", messages) if messages.Exclude { teams, err := qs.GetAllTeams() if err != nil { log.Printf("QS QE E: errror at getting teams %v", err) render.JSON(500, map[string]interface{}{"error": err}) return } for _, team := range teams { if !utils.InS(team.Name, messages.Teams) { log.Printf("QS Will send message to team: %v", team.Name) members, _ := qs.GetMembersOfTeam(team.Name) SendMessagesToPeoples(members, additionalNotifier, messages.Text) } } render.JSON(200, map[string]interface{}{"ok": true}) } else { for _, team_name := range messages.Teams { members, err := qs.GetMembersOfTeam(team_name) if err != nil { log.Printf("QS QE E: errror at getting team members %v", err) continue } log.Printf("QS Will send message to team: %v", team_name) SendMessagesToPeoples(members, additionalNotifier, messages.Text) } render.JSON(200, map[string]interface{}{"ok": true}) } }) r.Post("/delete_all_keys", func(render render.Render, req *http.Request) { //1. Steps or keys: si, _ := qs.Steps.RemoveAll(bson.M{}) //2 Peoples pi, _ := qs.Peoples.UpdateAll(bson.M{ "$and": []bson.M{ bson.M{"$or": []bson.M{ bson.M{"is_passerby": false}, bson.M{"is_passerby": bson.M{"$exists": false}}, }}, bson.M{"$or": []bson.M{ bson.M{"team_name": bson.M{"$exists": true}}, bson.M{"team_sid": bson.M{"$exists": true}}, }}, }, }, bson.M{ "$set": bson.M{"is_passerby": true}, "$unset": bson.M{"team_name": "", "team_sid": ""}, }) //3 teams and messages teams := []Team{} qs.Teams.Find(bson.M{}).All(&teams) tc := 0 mc := 0 for _, team := range teams { mri, _ := qs.Messages.RemoveAll(bson.M{ "$or": []bson.M{ bson.M{"from": team.Name}, bson.M{"to": team.Name}, }}) mc += mri.Removed qs.Teams.RemoveId(team.ID) tc += 1 } render.JSON(200, map[string]interface{}{ "ok": true, "steps_removed": si.Removed, "peoples_updated": pi.Updated, "teams_removed": tc, "messages_removed": mc, }) }) r.Post("/founded_keys", func(ren render.Render, req *http.Request) { type T struct { Name string `json:"team"` } t := T{} body, _ := ioutil.ReadAll(req.Body) json.Unmarshal(body, &t) steps, _ := qs.GetSteps(bson.M{"for_team": t.Name, "is_found": true}) ren.JSON(200, map[string]interface{}{"keys": steps}) }) type FoundKey struct { Name string `bson:"name" json:"name"` Found bool `bson:"found" json:"found"` Id string `json:"id"` Description string `json:"description"` } type TeamInfo struct { TeamName string `bson:"team_name" json:"team_name"` Keys []FoundKey `json:"keys"` Steps []Step `bson:"steps"` } r.Get("/info_page", func(ren render.Render, req *http.Request) { result := []TeamInfo{} err := qs.Steps.Pipe([]bson.M{ bson.M{"$group": bson.M{ "_id": "$for_team", "team_name": bson.M{"$first": "$for_team"}, "steps": bson.M{"$push": bson.M{ "_id": "$_id", "is_found": "$is_found", "next_key": "$next_key", "start_key": "$start_key", "description": "$description", }}}}, bson.M{"$sort": bson.M{ "team_name": 1}}, }).All(&result) if err != nil { log.Printf("QS Error at aggregate info page %v", err) } for ti, teamInfo := range result { steps := SortSteps(teamInfo.Steps) keys := []FoundKey{} for _, step := range steps { keys = append(keys, FoundKey{Name: step.StartKey, Found: step.IsFound, Id: step.ID.Hex(), Description: step.Description}) } result[ti].Keys = keys result[ti].Steps = []Step{} } ren.HTML(200, "info_page", map[string]interface{}{"teams": result}) }) r.Post("/info_page/update", func(ren render.Render, req *http.Request) { found_keys, err := qs.GetSteps(bson.M{"is_found": true}) if err != nil { ren.JSON(500, map[string]interface{}{"ok": false, "error": err.Error()}) } type UpdateKeyResult struct { Id string `json:"id"` } result := []UpdateKeyResult{} for _, key := range found_keys { result = append(result, UpdateKeyResult{Id: key.ID.Hex()}) } ren.JSON(200, map[string]interface{}{"ok": true, "foundKeys": result}) }) r.Post("/start_quest", func(ren render.Render, req *http.Request) { ren.JSON(200, map[string]interface{}{"ok": true}) }) r.Post("/stop_quest") //m.MapTo(r, (*martini.Routes)(nil)) log.Printf("Will start web server for quest at: %v", config.WebPort) m.Action(r.Handle) m.RunOnAddr(config.WebPort) }
func Run(addr string, db *d.MainDb, qs *quests.QuestStorage, vdh *voting.VotingDataHandler, ntf *ntf.Notifier, cfg c.Configuration) { m := martini.New() m.Use(w.NonJsonLogger()) m.Use(martini.Recovery()) m.Use(martini.Static("static")) m.Use(render.Renderer(render.Options{ Directory: "templates/console", //Layout: "console/layout", Extensions: []string{".tmpl", ".html"}, Charset: "UTF-8", IndentJSON: true, IndentXML: true, Funcs: []template.FuncMap{ template.FuncMap{ "eq_s": func(a, b string) bool { return a == b }, "stamp_date": func(t time.Time) string { return t.Format(time.Stamp) }, "chat_with": func(with string) string { result := fmt.Sprintf("/chat?with=%v", with) return result }, "me": func() string { return ME }, "is_message_": func(msg d.MessageWrapper, attrName string) bool { return msg.IsAttrPresent(attrName) }, "has_additional_data": func(msg d.MessageWrapper) bool { return len(msg.AdditionalData) > 0 }, "is_additional_data_valid": func(ad d.AdditionalDataElement) bool { return ad.Value != "" }, "from_slice": func(slice []string) string { return strings.Join(slice, " ") }, "clear": func(s string) string { return regexp.MustCompile("[^a-zA-Z0-9]+").ReplaceAllString(s, "") }, "is_auth": func(u interface{}) bool { log.Printf("Is auth user: %v", u) if u != nil { user := u.(w.User) return user.IsAuthenticated() } return false }, }, }, })) m.MapTo(db, (*d.DB)(nil)) r := martini.NewRouter() r = w.EnsureAuth(r, db) r.Get("/klichat", w.LoginRequired, w.AutHandler.CheckIncludeAnyRole(MANAGER), func(r render.Render, req *http.Request) { r.HTML(200, "index", w.AddCurrentUser(map[string]interface{}{}, req, db), render.HTMLOptions{Layout: "base"}) }) r.Group("/profile", func(r martini.Router) { type ProfileId struct { Id string `json:"id"` } pg_conf := cfg.Main.PGDatabase ph, err := NewProfileDbHandler(pg_conf.ConnString, cfg.Main.ConfigDatabase) if err != nil { panic(err) } r.Get("", w.LoginRequired, w.AutHandler.CheckIncludeAnyRole(MANAGER), func(render render.Render) { render.HTML(200, "profile", map[string]interface{}{}) }) r.Get("/all", func(render render.Render) { log.Printf("CS start querying for all profiles...") profiles, err := ph.GetAllProfiles() if err != nil { log.Printf("CS Error at getting all profiles: %v", err) render.JSON(500, map[string]interface{}{"success": false, "error": err}) } log.Printf("CS found %v profiles.", len(profiles)) render.JSON(200, map[string]interface{}{ "success": true, "profiles": profiles, }) }) r.Get("/link_types", func(render render.Render) { render.JSON(200, map[string]interface{}{"data": ph.GetContactLinkTypes()}) }) r.Post("/read", w.LoginRequired, w.AutHandler.CheckIncludeAnyRole(MANAGER), func(render render.Render, params martini.Params, req *http.Request) { data, err := ioutil.ReadAll(req.Body) if err != nil { log.Printf("error at reading post data %v", err) } log.Printf("CS READ data: %s", data) info := ProfileId{} err = json.Unmarshal(data, &info) if err != nil { log.Printf("CS READ error at unmarshal read data %v", err) render.JSON(500, map[string]interface{}{"error": err, "success": false}) return } profile, err := ph.GetProfile(info.Id) if err != nil { log.Printf("CS READ error at unmarshal read data %v", err) render.JSON(500, map[string]interface{}{"error": err, "success": false}) return } out, err := json.Marshal(profile) if err != nil { log.Printf("CS READ error at marshal data to out") render.JSON(500, map[string]interface{}{"error": err, "success": false}) } render.JSON(200, map[string]interface{}{"success": true, "data": out}) }) r.Post("/create", w.LoginRequired, w.AutHandler.CheckIncludeAnyRole(MANAGER), func(render render.Render, params martini.Params, req *http.Request) { data, err := ioutil.ReadAll(req.Body) if err != nil { log.Printf("error at reading post data %v", err) } log.Printf("CS CREATE data: %s", data) profile := &Profile{} err = json.Unmarshal(data, profile) if err != nil { log.Printf("CS CREATE error at unmarshal data at create profile %v", err) render.JSON(500, map[string]interface{}{"error": err, "success": false}) return } profile = ProfileTextTagClear(profile) log.Printf("CS CREATE profile: %+v", profile) profile, err = ph.InsertNewProfile(profile) if err != nil { log.Printf("CS CREATE DB are not available") render.JSON(500, map[string]interface{}{"error": err, "success": false}) } out, err := json.Marshal(profile) if err != nil { log.Printf("CS CREATE error at marshal data to out") render.JSON(500, map[string]interface{}{"error": err, "success": false}) } render.JSON(200, map[string]interface{}{"success": true, "data": out}) }) r.Post("/update", w.LoginRequired, w.AutHandler.CheckIncludeAnyRole(MANAGER), func(render render.Render, params martini.Params, req *http.Request) { data, err := ioutil.ReadAll(req.Body) log.Printf("CS UPDATE data: %s", data) if err != nil { log.Printf("CS UPDATE error at reading post data %v", err) render.JSON(500, map[string]interface{}{"error": err, "success": false}) return } profile := &Profile{} err = json.Unmarshal(data, profile) if err != nil { log.Printf("CS UPDATE error at unmarshal data at create profile %v", err) render.JSON(500, map[string]interface{}{"error": err, "success": false}) return } profile = ProfileTextTagClear(profile) log.Printf("CS UPDATE profile: %+v", profile) err = ph.UpdateProfile(profile) if err != nil { render.JSON(500, map[string]interface{}{"error": err, "success": false}) return } render.JSON(200, map[string]interface{}{"success": true}) }) r.Post("/delete", w.LoginRequired, w.AutHandler.CheckIncludeAnyRole(MANAGER), func(render render.Render, params martini.Params, req *http.Request) { data, err := ioutil.ReadAll(req.Body) if err != nil { log.Printf("CS DELETE error at reading post data %v", err) render.JSON(500, map[string]interface{}{"error": err, "success": false}) return } log.Printf("CS DELETE data: %s", data) info := ProfileId{} err = json.Unmarshal(data, &info) if err != nil { log.Printf("CS DELETE error at unmarshal delete data %v", err) render.JSON(500, map[string]interface{}{"error": err, "success": false}) return } err = ph.DeleteProfile(info.Id) if err != nil { log.Printf("CS DELETE error at which return storage %v", err) render.JSON(500, map[string]interface{}{"error": err, "success": false}) return } render.JSON(200, map[string]interface{}{"success": true}) }) r.Post("/upload_img/:profile_id", func(render render.Render, params martini.Params, req *http.Request) { profile_id := params["profile_id"] path := fmt.Sprintf("%v/%v", cfg.Console.ProfileImgPath, profile_id) file, handler, err := req.FormFile("img_file") defer file.Close() if err != nil { log.Printf("CS error at forming file %v", err) render.JSON(500, map[string]interface{}{"error": err, "success": false}) return } if !strings.Contains(handler.Header.Get("Content-Type"), "image") { render.JSON(200, map[string]interface{}{"error": "Вы загружаете не картинку", "success": false}) return } err = os.Mkdir(path, 0777) if err != nil { log.Printf("CS warn at mkdir %v", err) } profile, err := ph.GetProfile(profile_id) if err != nil { log.Printf("CS error at getting profile") render.JSON(500, map[string]interface{}{"error": err, "success": false}) return } if profile == nil { profile = &Profile{UserName: profile_id} } else { splitted := strings.Split(profile.ImageURL, "/") savedFname := splitted[len(splitted)-1] err = os.Remove(filepath.Join(path, savedFname)) if err != nil { log.Printf("CS Error at remove old icon ha ha ha") } } file_path := fmt.Sprintf("%v/%v", path, handler.Filename) f, err := os.OpenFile(file_path, os.O_WRONLY|os.O_CREATE, 0664) defer f.Close() if err != nil { log.Printf("CS error at open file %v", err) render.JSON(500, map[string]interface{}{"error": err, "success": false}) return } log.Printf("CS will save file at: [%v]", file_path) io.Copy(f, file) file_url := fmt.Sprintf("%v/%v/%v", cfg.Console.ProfileImgServer, profile_id, handler.Filename) log.Printf("CS will form image at: [%v]", file_url) profile.ImageURL = file_url ph.UpdateProfile(profile) render.JSON(200, map[string]interface{}{"success": true, "url": file_url}) }) r.Get("/employee/:phone", func(render render.Render, params martini.Params, req *http.Request) { phone := params["phone"] employee, err := ph.GetEmployeeByPhone(phone) if err != nil { log.Printf("CS Error getting employee by phone") render.JSON(500, map[string]interface{}{"error": err, "success": false}) return } render.JSON(200, map[string]interface{}{"success": true, "employee": employee}) }) r.Get("/all_groups", func(ren render.Render) { log.Printf("CS start querying for all groups") groups, err := ph.GetAllGroups() if err != nil { log.Printf("CS error at groups retrieve: %v", err) ren.JSON(500, map[string]interface{}{"error": err, "success": false}) return } log.Printf("CS forming next groups: %+v", groups) ren.JSON(200, map[string]interface{}{"success": true, "groups": groups}) }) r.Get("/all_features", func(ren render.Render) { log.Printf("CS start querying for all features") features, err := ph.GetAllFeatures() if err != nil { log.Printf("CS error at features retrieve: %v", err) ren.JSON(500, map[string]interface{}{"error": err, "success": false}) return } log.Printf("CS forming next features: %+v", features) ren.JSON(200, map[string]interface{}{"success": true, "features": features}) }) }) r.Group("/chat", func(r martini.Router) { r.Get("", w.LoginRequired, w.AutHandler.CheckIncludeAnyRole(MANAGER), func(r render.Render, params martini.Params, req *http.Request) { var with string result_data := map[string]interface{}{} query := req.URL.Query() for key, value := range query { if key == "with" && len(value) > 0 { with = value[0] log.Printf("CONSOLE CHAT: [with] == [%v]", with) break } } if with == "" { with = ALL } db.Messages.SetMessagesRead(with) collocutor := Collocutor{} var messages []d.MessageWrapper if with != ALL { user, _ := db.Users.GetUserById(with) if user != nil { messages, _ = db.Messages.GetMessages(bson.M{ "$or": []bson.M{ bson.M{"from": user.UserId}, bson.M{"to": user.UserId}, }, }) for i, _ := range messages { if messages[i].From != ME { messages[i].From = user.UserName } } collocutor.Name = user.UserName collocutor.Phone = user.Phone collocutor.Email = user.Email order_count, _ := db.Orders.Collection.Find(bson.M{"whom": user.UserId}).Count() resp := []OrdersInfo{} err := db.Orders.Collection.Pipe([]bson.M{ bson.M{"$match": bson.M{"whom": user.UserId}}, bson.M{"$group": bson.M{"_id": "$source", "count": bson.M{"$sum": 1}}}}).All(&resp) if err == nil { collocutor.Info.CountOrdersByProvider = resp } collocutor.Info.CountOrdersAll = order_count collocutor.InfoPresent = true } } if strings.Contains(with, ALL) { messages, _ = db.Messages.GetMessages(bson.M{"to": with}) } result_data["collocutor"] = collocutor result_data["with"] = with result_data["messages"] = messages if contacts, err := GetContacts(db); err == nil { result_data["contacts"] = contacts } log.Printf("CS result data :%+v", result_data) r.HTML(200, "chat", w.AddCurrentUser(result_data, req, db), render.HTMLOptions{Layout: "base"}) }) r.Post("/send", w.LoginRequired, w.AutHandler.CheckIncludeAnyRole(MANAGER), func(render render.Render, req *http.Request) { type MessageFromF struct { From string `json:"from"` To string `json:"to"` Body string `json:"body"` } data, err := ioutil.ReadAll(req.Body) if err != nil { log.Printf("CS QE E: errror at reading req body %v", err) render.JSON(500, map[string]interface{}{"error": err}) return } message := MessageFromF{} err = json.Unmarshal(data, &message) if err != nil { log.Printf("CS QE E: at unmarshal json messages %v\ndata:%s", err, data) render.JSON(500, map[string]interface{}{"error": err}) return } log.Printf("SEND MESSAGE: %+v", message) var messageSID string if message.From != "" && message.To != "" && message.Body != "" { if message.To == ALL { peoples, _ := db.Users.GetBy(bson.M{"user_id": bson.M{"$ne": message.From}}) ntf.SendMessageToPeople(peoples, message.Body) } else if message.To == "all_hash_writers" { peoples, _ := db.Users.GetBy(bson.M{"last_marker": bson.M{"$exists": true}}) ntf.SendMessageToPeople(peoples, message.Body) } else { user, _ := db.Users.GetUserById(message.To) if user != nil { db.Messages.SetMessagesRead(user.UserId) _, resultMessage, _ := ntf.NotifyText(message.To, message.Body) resultMessage, _ = db.Messages.GetMessageByMessageId(resultMessage.MessageID) messageSID = resultMessage.SID } } if err != nil { render.JSON(500, map[string]interface{}{"error": err}) } } else { render.Redirect("/chat") } render.JSON(200, map[string]interface{}{"ok": true, "message": d.NewMessageForWeb(messageSID, message.From, message.To, message.Body)}) }) r.Post("/messages_read", w.LoginRequired, w.AutHandler.CheckIncludeAnyRole(MANAGER), func(render render.Render, req *http.Request) { type Readed struct { From string `json:"from"` } data, err := ioutil.ReadAll(req.Body) if err != nil { log.Printf("CS QE E: errror at reading req body %v", err) render.JSON(500, map[string]interface{}{"error": err}) return } readed := Readed{} err = json.Unmarshal(data, &readed) if err != nil { log.Printf("CS QE E: at unmarshal json messages %v\ndata:%s", err, data) render.JSON(500, map[string]interface{}{"error": err}) return } err = db.Messages.SetMessagesRead(readed.From) if err != nil { log.Printf("CS QE E: at unmarshal json messages %v\ndata:%s", err, data) render.JSON(500, map[string]interface{}{"error": err}) return } render.JSON(200, map[string]interface{}{"ok": true}) }) r.Post("/unread_messages", func(render render.Render, req *http.Request) { type NewMessagesReq struct { For string `json:"m_for"` After int64 `json:"after"` } q := NewMessagesReq{} request_body, err := ioutil.ReadAll(req.Body) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": "can not read request body"}) return } err = json.Unmarshal(request_body, &q) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": fmt.Sprintf("can not unmarshal request body %v \n %s", err, request_body)}) return } query := bson.M{"time_stamp": bson.M{"$gt": q.After}} if q.For == "" { query["to"] = ME } else { query["from"] = q.For } messages, err := db.Messages.GetMessages(query) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": fmt.Sprintf("error in db: %v", err)}) return } result := []d.MessageWrapper{} for i, msg := range messages { if msg.From != ME { u, _ := db.Users.GetUserById(msg.From) if u.ShowedName != "" { messages[i].From = u.ShowedName } else { messages[i].From = u.UserName } result = append(result, messages[i]) } } render.JSON(200, map[string]interface{}{"messages": result, "next_": time.Now().Unix()}) }) r.Post("/contacts", func(render render.Render, req *http.Request) { type NewContactsReq struct { Exist []string `json:"exist"` } cr := NewContactsReq{} request_body, err := ioutil.ReadAll(req.Body) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": "can not read request body"}) return } err = json.Unmarshal(request_body, &cr) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": fmt.Sprintf("can not unmarshal request body %v \n %s", err, request_body)}) return } contacts, err := GetContacts(db) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": fmt.Sprintf("db err body %v", err)}) return } new_contacts := []usrs.Contact{} old_contacts := []usrs.Contact{} for _, contact := range contacts { if u.InS(contact.ID, cr.Exist) { if contact.NewMessagesCount > 0 { old_contacts = append(old_contacts, contact) } } else { new_contacts = append(new_contacts, contact) } } render.JSON(200, map[string]interface{}{ "ok": true, "new": new_contacts, "old": old_contacts, "next_": time.Now().Unix(), }) }) r.Delete("/delete_messages", w.LoginRequired, w.AutHandler.CheckIncludeAnyRole(MANAGER), func(params martini.Params, ren render.Render, req *http.Request) { type DeleteInfo struct { From string `json:"from"` To string `json:"to"` } data, err := ioutil.ReadAll(req.Body) if err != nil { log.Printf("CS QE E: errror at reading req body %v", err) ren.JSON(500, map[string]interface{}{"error": err}) return } dInfo := DeleteInfo{} err = json.Unmarshal(data, &dInfo) if err != nil { log.Printf("CS QE E: at unmarshal json messages %v\ndata:%s", err, data) ren.JSON(500, map[string]interface{}{"error": err}) return } count, err := db.Messages.DeleteMessages(dInfo.From, dInfo.To) if err != nil { ren.JSON(500, map[string]interface{}{"error": err}) return } ren.JSON(200, map[string]interface{}{"success": true, "deleted": count}) }) r.Post("/contacts_change", w.LoginRequired, w.AutHandler.CheckIncludeAnyRole(MANAGER), func(render render.Render, req *http.Request) { type NewContactName struct { Id string `json:"id"` NewName string `json:"new_name"` } ncn := NewContactName{} request_body, err := ioutil.ReadAll(req.Body) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": "can not read request body"}) return } err = json.Unmarshal(request_body, &ncn) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": fmt.Sprintf("can not unmarshal request body %v \n %s", err, request_body)}) return } err = db.Users.SetUserShowedName(ncn.Id, ncn.NewName) if err != nil { render.JSON(500, map[string]interface{}{"ok": false, "detail": err}) return } render.JSON(200, map[string]interface{}{"ok": true}) }) }) r.Get("/vote_result", w.LoginRequired, w.AutHandler.CheckIncludeAnyRole(MANAGER), func(ren render.Render, req *http.Request) { votes, err := vdh.GetTopVotes(-1) if err != nil { log.Printf("CS ERROR at retrieving votes %v", err) } ren.HTML(200, "vote_result", w.AddCurrentUser(map[string]interface{}{"votes": votes}, req, db), render.HTMLOptions{Layout: "base"}) }) r = EnsureWorkWithKeys(r, qs, db) r = EnsureWorkWithUsers(r, db) r.Get("/statistic", w.LoginRequired, w.AutHandler.CheckIncludeAnyRole(MANAGER), func(render render.Render) { err := EnsureStatistic(filepath.Join(martini.Root, "static", "tmp")) if err != nil { log.Printf("CS ERROR at formin statistics :( ") render.JSON(500, map[string]interface{}{"error": err}) } log.Printf("saved: %v", martini.Root) render.Redirect("/tmp/statistic.xlsx") }) r.Get("/logout", w.LoginRequired, func(user w.User, db d.DB, ren render.Render, req *http.Request, rw http.ResponseWriter) { err := db.UsersStorage().LogoutUser(user.UniqueId()) if err != nil { log.Printf("CONSOLE error at logout user: %v", err) } w.StopAuthSession(rw) ren.Redirect(w.AUTH_URL, 302) }) m.Action(r.Handle) m.RunOnAddr(addr) }