// Auth is a gin middleware that checks for session cookie and // handles permissions func Auth(authenticated bool) gin.HandlerFunc { return func(c *gin.Context) { // error if theres no secret set if Secret == "" { c.JSON(e.ErrorMessage(e.ErrInternalError)) c.Error(e.ErrNoSecret).SetMeta("auth.Auth") c.Abort() return } // set default anonymous user user := DefaultUser() // try and get the jwt cookie from the request cookie, err := c.Request.Cookie(CookieName) // parse jwt token if its there if err != http.ErrNoCookie { token, err := jwt.ParseWithClaims(cookie.Value, &TokenClaims{}, func(token *jwt.Token) (interface{}, error) { return validateToken(token, &user) }) // if theres some jwt error other than no token in request or the token is // invalid then return unauth // the client side should delete any saved JWT tokens on unauth error if err != nil || !token.Valid { // delete the cookie http.SetCookie(c.Writer, DeleteCookie()) c.JSON(e.ErrorMessage(e.ErrUnauthorized)) c.Error(err).SetMeta("user.Auth") c.Abort() return } } // check if user needed to be authenticated // this needs to be like this for routes that dont need auth // if we just check equality then logged in users wont be able // to view anon pages ;P if authenticated && !user.IsAuthenticated { c.JSON(e.ErrorMessage(e.ErrForbidden)) c.Error(e.ErrForbidden).SetMeta("user.Auth") c.Abort() return } // set user data for controllers c.Set("userdata", user) c.Next() } }
// ErrorController handles error messages for wrong routes func ErrorController(c *gin.Context) { c.JSON(e.ErrorMessage(e.ErrNotFound)) return }
// ValidateParams will loop through the route parameters to make sure theyre uint func ValidateParams() gin.HandlerFunc { return func(c *gin.Context) { if c.Params != nil { var params []uint for _, param := range c.Params { pid, err := ValidateParam(param.Value) if err != nil { c.JSON(e.ErrorMessage(e.ErrInvalidParam)) c.Error(err).SetMeta("validate.ValidateParams") c.Abort() return } params = append(params, pid) } c.Set("params", params) } c.Next() } }
// BoardLogController will get the the board audit log func BoardLogController(c *gin.Context) { // Get parameters from validate middleware params := c.MustGet("params").([]uint) if !c.MustGet("protected").(bool) { c.JSON(e.ErrorMessage(e.ErrInternalError)) c.Error(e.ErrInternalError).SetMeta("BoardLogController.protected") return } // Initialize model struct m := &models.BoardLogModel{ Ib: params[0], Page: params[1], } // Get the model which outputs JSON err := m.Get() if err == e.ErrNotFound { c.JSON(e.ErrorMessage(e.ErrNotFound)) c.Error(err).SetMeta("BoardLogController.Get") return } else if err != nil { c.JSON(e.ErrorMessage(e.ErrInternalError)) c.Error(err).SetMeta("BoardLogController.Get") return } // Marshal the structs into JSON output, err := json.Marshal(m.Result) if err != nil { c.JSON(e.ErrorMessage(e.ErrInternalError)) c.Error(err).SetMeta("BoardLogController.json.Marshal") return } c.Data(200, "application/json", output) return }
// Verify the sent csrf token func Verify() gin.HandlerFunc { return func(c *gin.Context) { // if this is a skippable method if skipMethods[c.Request.Method] { c.Next() return } // the token from the users cookie var csrfToken []byte // get the token from the cookie tokenCookie, err := c.Request.Cookie(CookieName) if err == nil { csrfToken = b64decode(tokenCookie.Value) } var sentToken string // Prefer the header over form value sentToken = c.Request.Header.Get(HeaderName) // Then POST values if len(sentToken) == 0 { sentToken = c.PostForm(FormFieldName) } // error if there was no csrf token or it isnt verified if csrfToken == nil || !verifyToken(csrfToken, b64decode(sentToken)) { c.JSON(e.ErrorMessage(e.ErrForbidden)) c.Error(e.ErrCsrfNotValid).SetMeta("csrf.Verify") c.Abort() return } c.Next() } }
// Protect will check to see if a user has the correct permissions // A route protected by this middleware needs an ib parameter func Protect() gin.HandlerFunc { return func(c *gin.Context) { // Get parameters from validate middleware params := c.MustGet("params").([]uint) // get userdata from session middleware userdata := c.MustGet("userdata").(User) // check if user is authorized if !userdata.IsAuthorized(params[0]) { c.JSON(e.ErrorMessage(e.ErrForbidden)) c.Error(e.ErrForbidden).SetMeta("user.Protect.IsAuthorized") c.Abort() return } // this route was protected c.Set("protected", true) c.Next() } }
// CloseThreadController will toggle a threads close bool func CloseThreadController(c *gin.Context) { // Get parameters from validate middleware params := c.MustGet("params").([]uint) // get userdata from user middleware userdata := c.MustGet("userdata").(user.User) if !c.MustGet("protected").(bool) { c.JSON(e.ErrorMessage(e.ErrInternalError)) c.Error(e.ErrInternalError).SetMeta("CloseThreadController.protected") return } // Initialize model struct m := &models.CloseModel{ Ib: params[0], ID: params[1], } // Check the record id and get further info err := m.Status() if err == e.ErrNotFound { c.JSON(e.ErrorMessage(e.ErrNotFound)) c.Error(err).SetMeta("CloseThreadController.Status") return } else if err != nil { c.JSON(e.ErrorMessage(e.ErrInternalError)) c.Error(err).SetMeta("CloseThreadController.Status") return } // toggle status err = m.Toggle() if err != nil { c.JSON(e.ErrorMessage(e.ErrInternalError)) c.Error(err).SetMeta("CloseThreadController.Toggle") return } // Delete redis stuff indexKey := fmt.Sprintf("%s:%d", "index", m.Ib) directoryKey := fmt.Sprintf("%s:%d", "directory", m.Ib) threadKey := fmt.Sprintf("%s:%d:%d", "thread", m.Ib, m.ID) err = redis.Cache.Delete(indexKey, directoryKey, threadKey) if err != nil { c.JSON(e.ErrorMessage(e.ErrInternalError)) c.Error(err).SetMeta("CloseThreadController.redis.Cache.Delete") return } var successMessage string // change response message depending on bool state if m.Closed { successMessage = audit.AuditOpenThread } else { successMessage = audit.AuditCloseThread } // response message c.JSON(http.StatusOK, gin.H{"success_message": successMessage}) // audit log audit := audit.Audit{ User: userdata.ID, Ib: m.Ib, Type: audit.ModLog, IP: c.ClientIP(), Action: successMessage, Info: fmt.Sprintf("%s", m.Name), } // submit audit err = audit.Submit() if err != nil { c.Error(err).SetMeta("CloseThreadController.audit.Submit") } return }
// DeleteTagController will delete a tag func DeleteTagController(c *gin.Context) { // Get parameters from validate middleware params := c.MustGet("params").([]uint) // get userdata from user middleware userdata := c.MustGet("userdata").(user.User) if !c.MustGet("protected").(bool) { c.JSON(e.ErrorMessage(e.ErrInternalError)) c.Error(e.ErrInternalError).SetMeta("DeleteTagController.protected") return } // Initialize model struct m := &models.DeleteTagModel{ Ib: params[0], ID: params[1], } // Check the record id and get further info err := m.Status() if err == e.ErrNotFound { c.JSON(e.ErrorMessage(e.ErrNotFound)) c.Error(err).SetMeta("DeleteTagController.Status") return } else if err != nil { c.JSON(e.ErrorMessage(e.ErrInternalError)) c.Error(err).SetMeta("DeleteTagController.Status") return } // Delete data err = m.Delete() if err != nil { c.JSON(e.ErrorMessage(e.ErrInternalError)) c.Error(err).SetMeta("DeleteTagController.Delete") return } // Delete redis stuff tagsKey := fmt.Sprintf("%s:%d", "tags", m.Ib) tagKey := fmt.Sprintf("%s:%d:%d", "tag", m.Ib, m.ID) imageKey := fmt.Sprintf("%s:%d", "image", m.Ib) err = redis.Cache.Delete(tagsKey, tagKey, imageKey) if err != nil { c.JSON(e.ErrorMessage(e.ErrInternalError)) c.Error(err).SetMeta("DeleteTagController.redis.Cache.Delete") return } // response message c.JSON(http.StatusOK, gin.H{"success_message": audit.AuditDeleteTag}) // audit log audit := audit.Audit{ User: userdata.ID, Ib: m.Ib, Type: audit.ModLog, IP: c.ClientIP(), Action: audit.AuditDeleteTag, Info: fmt.Sprintf("%s", m.Name), } // submit audit err = audit.Submit() if err != nil { c.Error(err).SetMeta("DeleteTagController.audit.Submit") } return }
// ResetPasswordController will reset an ip func ResetPasswordController(c *gin.Context) { var err error var rpf resetPasswordForm // Get parameters from validate middleware params := c.MustGet("params").([]uint) // get userdata from user middleware userdata := c.MustGet("userdata").(user.User) if !c.MustGet("protected").(bool) { c.JSON(e.ErrorMessage(e.ErrInternalError)) c.Error(e.ErrInternalError).SetMeta("ResetPasswordController.protected") return } err = c.Bind(&rpf) if err != nil { c.JSON(e.ErrorMessage(e.ErrInvalidParam)) c.Error(err).SetMeta("ResetPasswordController.Bind") return } // generate a random password password, hash, err := user.RandomPassword() if err != nil { c.JSON(e.ErrorMessage(e.ErrInternalError)) c.Error(err).SetMeta("ResetPasswordController.RandomPassword") return } // update the password in the database err = user.UpdatePassword(hash, rpf.UID) if err != nil { c.JSON(e.ErrorMessage(e.ErrInternalError)) c.Error(err).SetMeta("ResetPasswordController.UpdatePassword") return } // response message c.JSON(http.StatusOK, gin.H{"success_message": audit.AuditResetPassword, "password": password}) // audit log audit := audit.Audit{ User: userdata.ID, Ib: params[0], Type: audit.UserLog, IP: c.ClientIP(), Action: audit.AuditResetPassword, Info: fmt.Sprintf("%d", rpf.UID), } // submit audit err = audit.Submit() if err != nil { c.Error(err).SetMeta("ResetPasswordController.audit.Submit") } return }
// BanIPController will ban an ip func BanIPController(c *gin.Context) { var err error var bif banIPForm // Get parameters from validate middleware params := c.MustGet("params").([]uint) // get userdata from user middleware userdata := c.MustGet("userdata").(user.User) if !c.MustGet("protected").(bool) { c.JSON(e.ErrorMessage(e.ErrInternalError)) c.Error(e.ErrInternalError).SetMeta("BanIpController.protected") return } err = c.Bind(&bif) if err != nil { c.JSON(e.ErrorMessage(e.ErrInvalidParam)) c.Error(err).SetMeta("BanIpController.Bind") return } // Initialize model struct m := &models.BanIPModel{ Ib: params[0], Thread: params[1], ID: params[2], User: userdata.ID, Reason: bif.Reason, } // Check the record id and get further info err = m.Status() if err == e.ErrNotFound { c.JSON(e.ErrorMessage(e.ErrNotFound)) c.Error(err).SetMeta("BanIpController.Status") return } else if err != nil { c.JSON(e.ErrorMessage(e.ErrInternalError)) c.Error(err).SetMeta("BanIpController.Status") return } // add ban to database err = m.Post() if err != nil { c.JSON(e.ErrorMessage(e.ErrInternalError)) c.Error(err).SetMeta("BanIpController.Post") return } // ban the ip in cloudflare go u.CloudFlareBanIP(m.IP, m.Reason) // response message c.JSON(http.StatusOK, gin.H{"success_message": audit.AuditBanIP}) // audit log audit := audit.Audit{ User: userdata.ID, Ib: m.Ib, Type: audit.ModLog, IP: c.ClientIP(), Action: audit.AuditBanIP, Info: fmt.Sprintf("%s", m.Reason), } // submit audit err = audit.Submit() if err != nil { c.Error(err).SetMeta("BanIpController.audit.Submit") } return }
// UpdateTagController will update a tags properties func UpdateTagController(c *gin.Context) { var err error var utf updateTagForm // Get parameters from validate middleware params := c.MustGet("params").([]uint) // get userdata from user middleware userdata := c.MustGet("userdata").(user.User) if !c.MustGet("protected").(bool) { c.JSON(e.ErrorMessage(e.ErrInternalError)) c.Error(e.ErrInternalError).SetMeta("UpdateTagController.protected") return } err = c.Bind(&utf) if err != nil { c.JSON(e.ErrorMessage(e.ErrInvalidParam)) c.Error(err).SetMeta("UpdateTagController.Bind") return } // Set parameters to UpdateTagModel m := models.UpdateTagModel{ Ib: params[0], ID: utf.ID, Tag: utf.Tag, TagType: utf.Type, } // Validate input parameters err = m.ValidateInput() if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error_message": err.Error()}) c.Error(err).SetMeta("UpdateTagController.ValidateInput") return } // Check tag for duplicate err = m.Status() if err == e.ErrDuplicateTag { c.JSON(http.StatusBadRequest, gin.H{"error_message": err.Error()}) c.Error(err).SetMeta("UpdateTagController.Status") return } else if err != nil { c.JSON(e.ErrorMessage(e.ErrInternalError)) c.Error(err).SetMeta("UpdateTagController.Status") return } // Update data err = m.Update() if err != nil { c.JSON(e.ErrorMessage(e.ErrInternalError)) c.Error(err).SetMeta("UpdateTagController.Update") return } // Delete redis stuff tagsKey := fmt.Sprintf("%s:%d", "tags", m.Ib) tagKey := fmt.Sprintf("%s:%d:%d", "tag", m.Ib, m.ID) imageKey := fmt.Sprintf("%s:%d", "image", m.Ib) err = redis.Cache.Delete(tagsKey, tagKey, imageKey) if err != nil { c.JSON(e.ErrorMessage(e.ErrInternalError)) c.Error(err).SetMeta("UpdateTagController.redis.Cache.Delete") return } // response message c.JSON(http.StatusOK, gin.H{"success_message": audit.AuditUpdateTag}) // audit log audit := audit.Audit{ User: userdata.ID, Ib: m.Ib, Type: audit.ModLog, IP: c.ClientIP(), Action: audit.AuditUpdateTag, Info: fmt.Sprintf("%s", m.Tag), } // submit audit err = audit.Submit() if err != nil { c.Error(err).SetMeta("UpdateTagController.audit.Submit") } return }