// UpdateTask изменяет поля задания используя POST-параметры done и label. // Поля, для который не заданы значения в параметрах запроса, должны остаться // неизменными. // После выполнения запроса UpdateTask перенаправляет клиент на страницу списка. // POST /task/:id/update func UpdateTask(c *gin.Context) { td, _, ok := gettask(c) if !ok { return } label, ok := c.GetPostForm("label") if ok { td.Label = label } done, ok := c.GetPostForm("done") if ok { td.Done = (done != "0") } err := td.Save() if err != nil { ctl.RenderJSON(c, gin.H{ "status": "error", "error": err.Error(), }) return } ctl.RenderJSON(c, gin.H{ "status": "success", }) }
func gettask(c *gin.Context) (*todo.Todo, *todolist.TodoList, bool) { u, ok := user.FromContext(c) if !ok { ctl.Render403(c) return nil, nil, false } id, err := strconv.Atoi(c.Param("id")) if err != nil { ctl.Render404(c) return nil, nil, false } td, ok := todo.Find(uint(id)) if !ok { ctl.Render404(c) return nil, nil, false } l, ok := todolist.Find(td.TodoListID) if !ok { ctl.Render500(c) return nil, nil, false } if u.ID != l.UserID { ctl.Render403(c) return nil, nil, false } return td, l, true }
func roomGET(c *gin.Context) { roomid := c.Param("roomid") userid := fmt.Sprint(rand.Int31()) c.HTML(200, "chat_room", gin.H{ "roomid": roomid, "userid": userid, }) }
// DestroyList стирает список из базы и перенаправляет на главную. // POST /list/:id/destroy func DestroyList(c *gin.Context) { l, ok := getlist(c) if !ok { return } l.Destroy() c.Status(http.StatusOK) }
// DestroyTask стирает задание из списка и перенаправляет на страницу списка. // POST /task/:id/destroy func DestroyTask(c *gin.Context) { td, _, ok := gettask(c) if !ok { return } td.Destroy() c.Status(http.StatusOK) }
// RenderHTML отвечает на запрос кодом 200 и выполненным шаблоном. func RenderHTML(c *gin.Context, template string, data gin.H) { u, ok := user.FromContext(c) if data == nil { data = gin.H{} } data["LoggedIn"] = ok if ok { data["CurrentUser"] = u } c.HTML(http.StatusOK, template, data) }
// Login выполняет вход, используя параметры POST-запроса // name и password. // Пользователей, уже выполнивших вход, она перенаправляет на главную, // не перезаписывая сессию. // POST /login func Login(c *gin.Context) { _, ok := user.FromContext(c) if ok { ctl.Redirect(c, "/") return } name := c.PostForm("name") pas := c.PostForm("password") _, ok = user.Login(c, name, pas) if !ok { ctl.RenderHTML(c, "login.tmpl", gin.H{"Errors": []string{"Ошибка авторизации"}}) return } ctl.Redirect(c, "/") }
// Register регистрирует нового пользователя, используя параметры POST-запроса // name и password, и выполняет вход под его именем. // Пользователей, уже выполнивших вход, она перенаправляет на главную, // не перезаписывая сессию. // POST /register func Register(c *gin.Context) { _, ok := user.FromContext(c) if ok { ctl.Redirect(c, "/") return } name := c.PostForm("name") pas := c.PostForm("password") us, errs := user.Register(name, pas) if errs != nil { ctl.RenderHTML(c, "register.tmpl", gin.H{"Errors": errs}) return } us.AutoLogin(c) ctl.Redirect(c, "/") }
// Index возвращает главную страницу админской панели. // GET /admin func Index(c *gin.Context) { if !assertAccess(c) { return } page, err := strconv.Atoi(c.Query("p")) if err != nil { page = 1 } pcount := user.Pages(usersPerPage) ctl.RenderHTML(c, "admin_index.tmpl", gin.H{ "Users": user.FindPage(page, usersPerPage, user.ByVisitedAtDesc), "Pager": gin.H{ "Cur": page, "Max": pcount, "PathTmpl": "/admin?p=", }, }) }
// User возвращает страницу с информацией о пользователе. // GET /admin/u/:name func User(c *gin.Context) { if !assertAccess(c) { return } u, ok := user.Find(c.Param("name")) if !ok { ctl.Render404(c) return } u.LoadLists() for _, i := range u.Lists { i.LoadTodos() } // Шаблон ожидает заполненую структуру пользователя ctl.RenderHTML(c, "admin_user.tmpl", gin.H{ "User": u, }) }
// UpdateList изменяет заголовок списка на тот, который был получен // POST-параметре title и перенаправляет на страницу этого списка. // POST /list/:id/update func UpdateList(c *gin.Context) { l, ok := getlist(c) if !ok { return } l.Title = c.PostForm("title") err := l.Save() if err != nil { ctl.RenderJSON(c, gin.H{ "status": "error", "error": err.Error(), }) return } ctl.RenderJSON(c, gin.H{ "status": "success", }) }
func roomPOST(c *gin.Context) { roomid := c.Param("roomid") userid := c.PostForm("user") message := c.PostForm("message") room(roomid).Submit(userid + ": " + message) c.JSON(200, gin.H{ "status": "success", "message": message, }) }
// CreateTask создает новое задание в списке с текстом // из POST-параметра label и перенаправляет на страницу списка. // POST /list/:id/add func CreateTask(c *gin.Context) { l, ok := getlist(c) if !ok { return } err := l.Add(c.PostForm("label")) if err != nil { u, _ := user.FromContext(c) u.LoadLists() l.LoadTodos() ctl.RenderHTML(c, "todos_show.tmpl", gin.H{ "List": l, "AlertError": err.Error(), "Lists": u.Lists, }) return } ctl.Redirect(c, l.Path()) }
// CreateList создает новый список дел с заголовком из POST-параметра title // и перенаправляет на страницу этого списка. // POST /list-create func CreateList(c *gin.Context) { u, ok := user.FromContext(c) if !ok { ctl.Render403(c) return } l := todolist.New(c.PostForm("title")) l.UserID = u.ID err := l.Save() if err != nil { u.LoadLists() ctl.RenderHTML(c, "todos_index.tmpl", gin.H{ "Lists": u.Lists, "AlertError": err.Error(), }) return } ctl.Redirect(c, l.Path()) }
func dbFromContext(c *gin.Context) *dbSession { iid, exists := c.Get("session_id") if exists { id := iid.(string) s := &dbSession{} err := models.DB.Where("s_id = ?", id).Find(s).Error if err == nil { s.decode() return s } } key, ok := dbHasSession(c) if ok { s := &dbSession{} err := models.DB.Where("s_id = ?", key).Find(s).Error if err == nil { s.decode() c.Set("session_id", key) return s } } ses := dbSessionInit(c) c.Set("session_id", ses.ID()) return ses }
func getlist(c *gin.Context) (*todolist.TodoList, bool) { u, ok := user.FromContext(c) if !ok { ctl.Render403(c) return nil, false } id, err := strconv.Atoi(c.Param("id")) if err != nil { ctl.Render404(c) return nil, false } l, ok := todolist.Find(uint(id)) if !ok { ctl.Render404(c) return nil, false } if l.UserID != u.ID { ctl.Render403(c) return nil, false } return l, true }
func roomPOST(c *gin.Context) { roomid := c.Param("roomid") nick := c.Query("nick") message := c.PostForm("message") message = strings.TrimSpace(message) validMessage := len(message) > 1 && len(message) < 200 validNick := len(nick) > 1 && len(nick) < 14 if !validMessage || !validNick { c.JSON(400, gin.H{ "status": "failed", "error": "the message or nickname is too long", }) return } post := gin.H{ "nick": html.EscapeString(nick), "message": html.EscapeString(message), } messages.Add("inbound", 1) room(roomid).Submit(post) c.JSON(200, post) }
func stream(c *gin.Context) { roomid := c.Param("roomid") listener := openListener(roomid) defer closeListener(roomid, listener) c.Stream(func(w io.Writer) bool { c.SSEvent("message", <-listener) return true }) }
func streamRoom(c *gin.Context) { roomid := c.Param("roomid") listener := openListener(roomid) ticker := time.NewTicker(1 * time.Second) users.Add("connected", 1) defer func() { closeListener(roomid, listener) ticker.Stop() users.Add("disconnected", 1) }() c.Stream(func(w io.Writer) bool { select { case msg := <-listener: messages.Add("outbound", 1) c.SSEvent("message", msg) case <-ticker.C: c.SSEvent("stats", Stats()) } return true }) }
func rateLimit(c *gin.Context) { ip := c.ClientIP() value := int(ips.Add(ip, 1)) if value%50 == 0 { fmt.Printf("ip: %s, count: %d\n", ip, value) } if value >= 200 { if value%200 == 0 { fmt.Println("ip blocked") } c.Abort() c.String(503, "you were automatically banned :)") } }
func roomGET(c *gin.Context) { roomid := c.Param("roomid") nick := c.Query("nick") if len(nick) < 2 { nick = "" } if len(nick) > 13 { nick = nick[0:12] + "..." } c.HTML(200, "room_login.templ.html", gin.H{ "roomid": roomid, "nick": nick, "timestamp": time.Now().Unix(), }) }
func imFromContext(c *gin.Context) *imSession { iid, exists := c.Get("session_id") if exists { id := iid.(string) ses, ok := mapSession[id] if ok { return ses } } key, ok := hasSession(c) if ok { ses, ok := mapSession[key] if ok { c.Set("session_id", key) return ses } } ses := sessionInit(c) c.Set("session_id", ses.ID()) return ses }
// RenderJSON отвечает на запрос кодом 200 и данными data, закодированными в JSON. func RenderJSON(c *gin.Context, data interface{}) { c.JSON(http.StatusOK, data) }
// Render403 отвечает кодом 403 Forbidden. func Render403(c *gin.Context) { c.HTML(http.StatusForbidden, errTmpl, gin.H{ "Code": 403, "Msg": "Доступ запрещен :(", }) }
func roomDELETE(c *gin.Context) { roomid := c.Param("roomid") deleteBroadcast(roomid) }
// Render404 отвечает кодом 404 Not Found. func Render404(c *gin.Context) { c.HTML(http.StatusNotFound, errTmpl, gin.H{ "Code": 404, "Msg": "У нас нет такой странички :(", }) }
// Render500 отвечает кодом 500 Internal Server Error. func Render500(c *gin.Context) { c.HTML(http.StatusInternalServerError, errTmpl, gin.H{ "Code": 500, "Msg": "Внутренняя ошибка!", }) }
// Redirect выполняет перенаправление. func Redirect(c *gin.Context, location string) { c.Redirect(http.StatusFound, location) }
func index(c *gin.Context) { c.Redirect(301, "/room/hn") }