Example #1
0
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))
}
Example #2
0
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)
}
Example #3
0
// 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)
}
Example #4
0
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)
}
Example #5
0
func GetUnjoinedNotesInNotebook(notebookId, userId string) ([]model.DbNote, error) {
	// Was going to try and put this logic into sql but im bad at sql
	notes, err := GetNotesInNotebook(notebookId)
	if log.Error(err) {
		return notes, err
	}
	userTopics := []string{}
	for _, note := range notes {
		if note.Owner == userId {
			userTopics = append(userTopics, note.TopicId)
		}
	}
	unjoinedNotes := []model.DbNote{}
	for _, note := range notes {
		add := true
		for _, userTopic := range userTopics {
			if note.TopicId == userTopic {
				add = false
				break
			}
		}
		if add {
			unjoinedNotes = append(unjoinedNotes, note)
		}
	}
	return unjoinedNotes, err
}
Example #6
0
func GetAllSchools(c *gin.Context) {
	schools, err := db.GetAllSchools()
	if log.Error(err) {
		c.Error(errors.NewISE())
		return
	}
	c.JSON(http.StatusOK, schools)
}
Example #7
0
func DumpNoteCache() {
	ticker := time.Tick(5 * time.Second)
	for range ticker {
		for _, note := range NoteIdCache {
			if log.Error(db.UpdateNote(*note)) {
				continue
			}
		}
	}
}
Example #8
0
func HandleUpdate(frame map[string]interface{}, c *model.WsContext) error {
	var updateFrame model.WsUpdate
	err := util.FillStruct(&updateFrame, frame)
	if log.Error(err) {
		return err
	}
	log.Info("Processing update %+v", updateFrame)

	// Update the note content in our cache
	note := cache.GetNote(c.NoteId)
	note.Content, err = updateFrame.Update.Operations.Apply(note.Content)
	if log.Error(err) {
		return err
	}
	cache.Note(note)

	return nil

}
Example #9
0
func PostSchoolRequest(c *gin.Context) {
	var request model.SchoolRequestRequest
	err := c.BindJSON(&request)
	if log.Error(err) {
		c.Error(err)
		return
	}
	dbreq := model.DbSchoolRequest{
		Id:              util.NewId(),
		RequesterUserId: c.MustGet("request_user_id").(string),
		Name:            request.Name,
		Location:        request.Location,
	}
	err = db.CreateSchoolRequest(dbreq)
	if log.Error(err) {
		c.Error(err)
		return
	}
	c.JSON(http.StatusOK, dbreq)
}
Example #10
0
func (f Facebook) genericGet(endpoint string, struc interface{}, token string, params url.Values) error {
	params.Set("access_token", token)
	fullURL := fmt.Sprintf("%v%v?%v", FacebookBaseUrl, endpoint, params.Encode())
	resp, err := http.Get(fullURL)
	if log.Error(err) {
		return fmt.Errorf("ISE")
	}
	if resp.StatusCode == 400 {
		return fmt.Errorf("Facebook unauthorized")
	}
	bytes, err := ioutil.ReadAll(resp.Body)
	if log.Error(err) {
		return fmt.Errorf("ISE")
	}
	err = json.Unmarshal(bytes, &struc)
	if log.Error(err) {
		return fmt.Errorf("ISE")
	}
	return nil
}
Example #11
0
func EchoWebsocket(c *gin.Context) {
	conn, err := websocketUpgrader.Upgrade(c.Writer, c.Request, nil)
	if log.Error(err) {
		c.Error(errors.NewISE())
		return
	}
	for {
		typ, frame, _ := conn.ReadMessage()
		conn.WriteMessage(typ, frame)
	}
}
Example #12
0
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)
}
Example #13
0
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)
}
Example #14
0
func Note(n model.DbNote) {
	if oldNote, in := NoteIdCache[n.Id]; in {
		log.Error(db.UpdateNote(*oldNote))
	}
	NoteIdCache[n.Id] = &n
	if _, in := NoteTopicCache[n.TopicId]; in {
		NoteTopicCache[n.TopicId][n.Id] = &n
	} else {
		NoteTopicCache[n.TopicId] = make(map[string]*model.DbNote)
		NoteTopicCache[n.TopicId][n.Id] = &n
	}
}
Example #15
0
// Init creates a connection to the database
func Init() {
	log.Info("Establishing a connection to the database")
	db, err := sql.Open("postgres", config.PostgresURL())
	if log.Error(err) {
		os.Exit(1)
	}
	err = db.Ping()
	if log.Error(err) {
		os.Exit(1)
	}
	dbmap = &gorp.DbMap{Db: db, Dialect: gorp.PostgresDialect{}}
	dbmap.AddTableWithName(model.DbSchool{}, "schools").SetKeys(false, "Id")
	dbmap.AddTableWithName(model.DbCourse{}, "courses").SetKeys(false, "Id")
	dbmap.AddTableWithName(model.DbCourseSection{}, "sections").SetKeys(false, "Id")
	dbmap.AddTableWithName(model.DbUser{}, "users").SetKeys(false, "Id")
	dbmap.AddTableWithName(model.DbSchoolRequest{}, "school_requests").SetKeys(false, "Id")
	dbmap.AddTableWithName(model.DbNotebook{}, "notebooks").SetKeys(false, "Id")
	dbmap.AddTableWithName(model.DbTopic{}, "topics").SetKeys(false, "Id")
	dbmap.AddTableWithName(model.DbNote{}, "notes").SetKeys(false, "Id")
	dbmap.AddTableWithName(model.DbSubscription{}, "subscriptions").SetKeys(false, "UserId", "NotebookId")
}
Example #16
0
// model passed in is assumed to be a list
// because of this, a boolean is not returned; you can just check the length of the list
func GenericGet(model interface{}, sqls string, args ...interface{}) error {
	_, err := dbmap.Select(model, sqls, args...)
	if err != nil {
		switch err {
		case sql.ErrNoRows:
			return nil
		default:
			log.Error(err)
			return err
		}
	}
	return nil
}
Example #17
0
func GenericGetOne(model interface{}, sqls string, args ...interface{}) (bool, error) {
	err := dbmap.SelectOne(model, sqls, args...)
	if err != nil {
		switch err {
		case sql.ErrNoRows:
			return false, nil
		default:
			log.Error(err)
			return true, err
		}
	}
	return true, nil
}
Example #18
0
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)
}
Example #19
0
func GetCoursesForSchool(c *gin.Context) {
	schoolId := c.Param("school_id")
	courses, err := db.GetCoursesForSchool(schoolId)
	if log.Error(err) {
		c.Error(errors.NewISE())
		return
	}
	courseResponses := make([]model.CourseResponse, 0)
	for _, course := range courses {
		courseResponses = append(courseResponses, model.CourseResponseWithoutSchool(course))
	}
	c.JSON(http.StatusOK, courseResponses)
}
Example #20
0
func GetSectionsForCourse(c *gin.Context) {
	courseId := c.Param("course_id")
	sections, err := db.GetSectionsForCourse(courseId)
	if log.Error(err) {
		c.Error(errors.NewISE())
		return
	}
	sectionsResponse := make([]model.SectionResponse, 0)
	for _, section := range sections {
		sectionsResponse = append(sectionsResponse, model.SectionResponseWithoutCourse(section))
	}
	c.JSON(http.StatusOK, sectionsResponse)
}
Example #21
0
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))
}
Example #22
0
func WrapWebsocket(conn *websocket.Conn, bundle *model.WsContext) {
	// Read from WS, write to channel
	go func() {
		for {
			_, frameb, err := conn.ReadMessage()
			if log.Error(err) {
				bundle.Close <- true
				return
			}
			log.Info("Received: %v", string(frameb))
			frame := make(map[string]interface{})
			err = json.Unmarshal(frameb, &frame)
			if log.Error(err) {
				continue
			}
			bundle.Incoming <- frame
		}
	}()
	// Read from channel, write to WS
	go func() {
		for {
			select {
			case msg := <-bundle.Outgoing:
				b, err := json.Marshal(msg)
				if log.Error(err) {
					continue
				}
				log.Info("Sending: %v", string(b))
				err = conn.WriteMessage(1, b)
				if log.Error(err) {
					continue
				}
			case <-bundle.Close:
				return
			}
		}
	}()
}
Example #23
0
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)
}
Example #24
0
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))
}
Example #25
0
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))

}