// Status handler for the /status route func OpenWebsocket(c *gin.Context) { userId := c.MustGet("request_user_id").(string) noteId := c.Param("note_id") in, note, err := db.GetNoteById(noteId) if log.Error(err) { c.Error(errors.NewISE()) return } if !in { c.Error(errors.NewHttp(http.StatusNotFound, "The requested note was not found")) return } if userId != note.Owner { c.Error(errors.NewHttp(http.StatusUnauthorized, "Only owners can open websockets into their notes")) return } conn, err := websocketUpgrader.Upgrade(c.Writer, c.Request, nil) if log.Error(err) { c.Error(errors.NewISE()) return } log.Info("Opening ws for user %v on %v", userId, note.Id) bundle := model.NewContext(userId, noteId) WrapWebsocket(conn, bundle) ws.ProcessMessages(bundle) }
func Error(c *gin.Context) { c.Next() id, _ := c.Get("request_id") // Log out every error we have encoutered (which in most cases is just 1) for _, ginError := range c.Errors { actError := ginError.Err log.InfoFields("Request error", log.Fields{ "request_id": id, "body": formatErrorBody(actError.Error()), }) } // Grab the last error and use that as the error we return to the client if len(c.Errors) > 0 { clientError := c.Errors[len(c.Errors)-1].Err // If it isn't an errors.Http type, assume it is a 500 and return that switch clientError.(type) { case errors.Http: break default: if c.IsAborted() { clientError = errors.NewHttp(c.Writer.Status(), formatErrorBody(clientError.Error())) } else { clientError = errors.NewHttp(http.StatusInternalServerError, "Unrecognized error") } } // Now write the error to the client c.JSON(clientError.(errors.Http).Code, clientError) } }
func RemoveUserSubscription(c *gin.Context) { userId := c.Param("user_id") if userId != c.MustGet("request_user_id").(string) { c.Error(errors.NewHttp(http.StatusUnauthorized, "Users can only delete their own subs")) return } notebookId := c.Param("notebook_id") sub := model.DbSubscription{ UserId: userId, NotebookId: notebookId, } section, err := db.GetSectionByNotebookId(sub.NotebookId) if log.Error(err) { c.Error(errors.NewISE()) return } course, err := db.GetCourseByCourseId(section.CourseId) if log.Error(err) { c.Error(errors.NewISE()) return } err = db.DeleteSubscription(sub) if log.Error(err) { c.Error(err) return } c.JSON(http.StatusOK, model.NewSubscriptionResponse(sub, course, section)) }
func GetUsersSubscriptions(c *gin.Context) { userId := c.Param("user_id") if userId != c.MustGet("request_user_id").(string) { c.Error(errors.NewHttp(http.StatusUnauthorized, "Users can only view the subscriptions of themselves")) return } subs, err := db.GetUserSubscriptions(userId) if log.Error(err) { c.Error(errors.NewISE()) return } subResponses := make([]model.SubscriptionResponse, 0) for _, sub := range subs { section, err := db.GetSectionByNotebookId(sub.NotebookId) if log.Error(err) { c.Error(errors.NewISE()) return } course, err := db.GetCourseByCourseId(section.CourseId) if log.Error(err) { c.Error(errors.NewISE()) return } subResponses = append(subResponses, model.NewSubscriptionResponse(sub, course, section)) } c.JSON(http.StatusOK, subResponses) }
func SetUserSchool(c *gin.Context) { userId := c.Param("user_id") if userId != c.MustGet("request_user_id").(string) { c.Error(errors.NewHttp(http.StatusUnauthorized, "Users can only modify themselves")) return } var request model.ModifySchoolRequest err := c.BindJSON(&request) if log.Error(err) { c.Error(err) return } _, user, err := db.GetUserById(userId) if log.Error(err) { c.Error(err) return } user.School = sql.NullString{ String: request.SchoolId, Valid: true, } err = db.UpdateUser(user) if log.Error(err) { c.Error(err) return } c.JSON(http.StatusOK, user) }
func GetNotebookById(id string) (model.DbNotebook, error) { var nb model.DbNotebook in, err := GenericGetOne(&nb, "select * from notebooks where id=$1", id) if !in { return nb, errors.NewHttp(http.StatusNotFound, "The notebook requested was not found") } return nb, err }
func GetNotebookNotes(c *gin.Context) { userId := c.MustGet("request_user_id").(string) notebookId := c.Param("notebook_id") // Confirm notebook exists _, err := db.GetNotebookById(notebookId) if err != nil { c.Error(err) return } // Check query params filterUserId := c.Query("user") filterUnjoined := c.Query("unjoined") // And execute those query params var notes []model.DbNote if filterUserId == "" && filterUnjoined == "" { notes, err = db.GetNotesInNotebook(notebookId) } else if filterUserId == "" { notes, err = db.GetUnjoinedNotesInNotebook(notebookId, userId) } else if filterUnjoined == "" { notes, err = db.GetNotesInNotebookByUser(notebookId, userId) } else { c.Error(errors.NewHttp(http.StatusBadRequest, "Cannot provide both unjoined and user parameters lol")) return } if log.Error(err) { c.Error(errors.NewISE()) return } // Transform the resultant list into hierarchial [topic -> []note] topicHash := make(map[string][]model.FullNoteResponse) for _, dbnote := range notes { if ar, in := topicHash[dbnote.TopicId]; in { topicHash[dbnote.TopicId] = append(ar, model.NewFullNoteResponse(dbnote)) } else { topicHash[dbnote.TopicId] = []model.FullNoteResponse{ model.NewFullNoteResponse(dbnote), } } } topicResponses := []model.TopicResponse{} for topicid, notelist := range topicHash { topicResponses = append(topicResponses, model.TopicResponse{ Id: topicid, Notes: notelist, }) } c.JSON(http.StatusOK, topicResponses) }
func GetUser(c *gin.Context) { userId := c.Param("user_id") if userId != c.MustGet("request_user_id").(string) { c.Error(errors.NewHttp(http.StatusUnauthorized, "Users can only view detailed information about themselves")) return } _, user, err := db.GetUserById(userId) if log.Error(err) { c.Error(errors.NewISE()) return } c.JSON(http.StatusOK, model.NewUserResponse(user)) }
func GetSingleSchool(c *gin.Context) { schoolId := c.Param("school_id") in, school, err := db.GetSchool(schoolId) if log.Error(err) { c.Error(errors.NewISE()) return } if !in { c.Error(errors.NewHttp(http.StatusNotFound, "School requested could not be found")) return } c.JSON(http.StatusOK, school) }
func SetUserEmail(c *gin.Context) { userId := c.Param("user_id") if userId != c.MustGet("request_user_id").(string) { c.Error(errors.NewHttp(http.StatusUnauthorized, "Users can only modify themselves")) return } newUserEmail := c.Param("email") _, user, err := db.GetUserById(userId) if log.Error(err) { c.Error(err) return } user.Email = newUserEmail err = db.UpdateUser(user) if log.Error(err) { c.Error(err) return } c.JSON(http.StatusOK, user) }
func SetUserUsername(c *gin.Context) { userId := c.Param("user_id") if userId != c.MustGet("request_user_id").(string) { c.Error(errors.NewHttp(http.StatusUnauthorized, "Users can only modify themselves")) return } newUserName := c.Param("username") _, user, err := db.GetUserById(userId) if log.Error(err) { c.Error(err) return } user.Username = sql.NullString{ String: newUserName, Valid: true, } err = db.UpdateUser(user) if log.Error(err) { c.Error(err) return } c.JSON(http.StatusOK, user) }
func ModifyUserSubscription(c *gin.Context) { userId := c.Param("user_id") if userId != c.MustGet("request_user_id").(string) { c.Error(errors.NewHttp(http.StatusUnauthorized, "Users can only modify subscriptions for themselves")) return } var request model.SubscriptionRequest err := c.BindJSON(&request) if log.Error(err) { c.Error(err) return } sub := model.DbSubscription{ UserId: userId, NotebookId: request.NotebookId, Name: sql.NullString{ String: request.Name, Valid: true, }, } err = db.UpdateSubscription(sub) if log.Error(err) { c.Error(errors.NewISE()) return } section, err := db.GetSectionByNotebookId(sub.NotebookId) if log.Error(err) { c.Error(errors.NewISE()) return } course, err := db.GetCourseByCourseId(section.CourseId) if log.Error(err) { c.Error(errors.NewISE()) return } c.JSON(http.StatusOK, model.NewSubscriptionResponse(sub, course, section)) }
func Login(c *gin.Context) { var returnCode int var request model.LoginRequest // Parse the user request err := c.BindJSON(&request) if log.Error(err) { c.Error(err) return } // Right now we assume that the user is logging in with Facebook fbUser, err := service.Facebook{}.GetCurrentUser(request.AccessToken) if log.Error(err) { c.Error(errors.NewHttp(errors.ISE, "Error contacting facebook api")) return } // Then get the user's profile picture fbPicture, err := service.Facebook{}.GetProfilePic(request.AccessToken) if log.Error(err) { c.Error(errors.NewHttp(errors.ISE, "Error contacting facebook api")) return } // See if the user is already a notion user in, dbUser, err := db.GetUserByFacebookId(fbUser.Id) if log.Error(err) { c.Error(errors.NewISE()) return } // If they are in the database, we just update their auth token if in { returnCode = http.StatusAccepted dbUser.FbAuthToken = request.AccessToken dbUser.FbProfilePic = fbPicture.Data.Url err = db.UpdateUser(dbUser) } else { returnCode = http.StatusCreated dbUser = model.DbUser{ Id: util.NewId(), Name: fbUser.Name, Email: fbUser.Email, Verified: false, AuthMethod: request.AuthMethod, FbUserId: fbUser.Id, FbAuthToken: request.AccessToken, FbProfilePic: fbPicture.Data.Url, } err = db.CreateUser(dbUser) } // Error check 'er yo if log.Error(err) { c.Error(errors.NewISE()) return } // Throw back the user object at the requester c.JSON(returnCode, model.NewUserResponse(dbUser)) }