mirror of
https://github.com/dnote/dnote
synced 2026-03-14 22:45:50 +01:00
324 lines
8.6 KiB
Go
324 lines
8.6 KiB
Go
/* Copyright (C) 2019, 2020, 2021 Monomax Software Pty Ltd
|
|
*
|
|
* This file is part of Dnote.
|
|
*
|
|
* Dnote is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Dnote is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with Dnote. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
package api
|
|
|
|
// import (
|
|
// "fmt"
|
|
// "net/http"
|
|
// "net/url"
|
|
// "strconv"
|
|
// "strings"
|
|
// "time"
|
|
//
|
|
// "github.com/dnote/dnote/pkg/server/database"
|
|
// "github.com/dnote/dnote/pkg/server/helpers"
|
|
// "github.com/dnote/dnote/pkg/server/middleware"
|
|
// "github.com/dnote/dnote/pkg/server/operations"
|
|
// "github.com/dnote/dnote/pkg/server/presenters"
|
|
// "github.com/gorilla/mux"
|
|
// "github.com/jinzhu/gorm"
|
|
// "github.com/pkg/errors"
|
|
// )
|
|
//
|
|
// type ftsParams struct {
|
|
// HighlightAll bool
|
|
// }
|
|
//
|
|
// func getHeadlineOptions(params *ftsParams) string {
|
|
// headlineOptions := []string{
|
|
// "StartSel=<dnotehl>",
|
|
// "StopSel=</dnotehl>",
|
|
// "ShortWord=0",
|
|
// }
|
|
//
|
|
// if params != nil && params.HighlightAll {
|
|
// headlineOptions = append(headlineOptions, "HighlightAll=true")
|
|
// } else {
|
|
// headlineOptions = append(headlineOptions, "MaxFragments=3, MaxWords=50, MinWords=10")
|
|
// }
|
|
//
|
|
// return strings.Join(headlineOptions, ",")
|
|
// }
|
|
//
|
|
// func selectFTSFields(conn *gorm.DB, search string, params *ftsParams) *gorm.DB {
|
|
// headlineOpts := getHeadlineOptions(params)
|
|
//
|
|
// return conn.Select(`
|
|
// notes.id,
|
|
// notes.uuid,
|
|
// notes.created_at,
|
|
// notes.updated_at,
|
|
// notes.book_uuid,
|
|
// notes.user_id,
|
|
// notes.added_on,
|
|
// notes.edited_on,
|
|
// notes.usn,
|
|
// notes.deleted,
|
|
// notes.encrypted,
|
|
// ts_headline('english_nostop', notes.body, plainto_tsquery('english_nostop', ?), ?) AS body
|
|
// `, search, headlineOpts)
|
|
// }
|
|
//
|
|
// func respondWithNote(w http.ResponseWriter, note database.Note) {
|
|
// presentedNote := presenters.PresentNote(note)
|
|
//
|
|
// middleware.RespondJSON(w, http.StatusOK, presentedNote)
|
|
// }
|
|
//
|
|
// func parseSearchQuery(q url.Values) string {
|
|
// searchStr := q.Get("q")
|
|
//
|
|
// return escapeSearchQuery(searchStr)
|
|
// }
|
|
//
|
|
// func getNoteBaseQuery(db *gorm.DB, noteUUID string, search string) *gorm.DB {
|
|
// var conn *gorm.DB
|
|
// if search != "" {
|
|
// conn = selectFTSFields(db, search, &ftsParams{HighlightAll: true})
|
|
// } else {
|
|
// conn = db
|
|
// }
|
|
//
|
|
// conn = conn.Where("notes.uuid = ? AND deleted = ?", noteUUID, false)
|
|
//
|
|
// return conn
|
|
// }
|
|
//
|
|
// func (a *API) getNote(w http.ResponseWriter, r *http.Request) {
|
|
// user, _, err := middleware.AuthWithSession(a.App.DB, r)
|
|
// if err != nil {
|
|
// middleware.DoError(w, "authenticating", err, http.StatusInternalServerError)
|
|
// return
|
|
// }
|
|
//
|
|
// vars := mux.Vars(r)
|
|
// noteUUID := vars["noteUUID"]
|
|
//
|
|
// note, ok, err := operations.GetNote(a.App.DB, noteUUID, &user)
|
|
// if !ok {
|
|
// middleware.RespondNotFound(w)
|
|
// return
|
|
// }
|
|
// if err != nil {
|
|
// middleware.DoError(w, "finding note", err, http.StatusInternalServerError)
|
|
// return
|
|
// }
|
|
//
|
|
// respondWithNote(w, note)
|
|
// }
|
|
//
|
|
// /**** getNotesHandler */
|
|
//
|
|
// // GetNotesResponse is a reponse by getNotesHandler
|
|
// type GetNotesResponse struct {
|
|
// Notes []presenters.Note `json:"notes"`
|
|
// Total int `json:"total"`
|
|
// }
|
|
//
|
|
// type dateRange struct {
|
|
// lower int64
|
|
// upper int64
|
|
// }
|
|
//
|
|
// func (a *API) getNotes(w http.ResponseWriter, r *http.Request) {
|
|
// user, ok := r.Context().Value(helpers.KeyUser).(database.User)
|
|
// if !ok {
|
|
// middleware.DoError(w, "No authenticated user found", nil, http.StatusInternalServerError)
|
|
// return
|
|
// }
|
|
// query := r.URL.Query()
|
|
//
|
|
// respondGetNotes(a.App.DB, user.ID, query, w)
|
|
// }
|
|
//
|
|
// func respondGetNotes(db *gorm.DB, userID int, query url.Values, w http.ResponseWriter) {
|
|
// q, err := parseGetNotesQuery(query)
|
|
// if err != nil {
|
|
// http.Error(w, err.Error(), http.StatusBadRequest)
|
|
// return
|
|
// }
|
|
//
|
|
// conn := getNotesBaseQuery(db, userID, q)
|
|
//
|
|
// var total int
|
|
// if err := conn.Model(database.Note{}).Count(&total).Error; err != nil {
|
|
// middleware.DoError(w, "counting total", err, http.StatusInternalServerError)
|
|
// return
|
|
// }
|
|
//
|
|
// notes := []database.Note{}
|
|
// if total != 0 {
|
|
// conn = orderGetNotes(conn)
|
|
// conn = database.PreloadNote(conn)
|
|
// conn = paginate(conn, q.Page)
|
|
//
|
|
// if err := conn.Find(¬es).Error; err != nil {
|
|
// middleware.DoError(w, "finding notes", err, http.StatusInternalServerError)
|
|
// return
|
|
// }
|
|
// }
|
|
//
|
|
// response := GetNotesResponse{
|
|
// Notes: presenters.PresentNotes(notes),
|
|
// Total: total,
|
|
// }
|
|
// middleware.RespondJSON(w, http.StatusOK, response)
|
|
// }
|
|
//
|
|
// type getNotesQuery struct {
|
|
// Year int
|
|
// Month int
|
|
// Page int
|
|
// Books []string
|
|
// Search string
|
|
// Encrypted bool
|
|
// }
|
|
//
|
|
// func parseGetNotesQuery(q url.Values) (getNotesQuery, error) {
|
|
// yearStr := q.Get("year")
|
|
// monthStr := q.Get("month")
|
|
// books := q["book"]
|
|
// pageStr := q.Get("page")
|
|
// encryptedStr := q.Get("encrypted")
|
|
//
|
|
// fmt.Println("books", books)
|
|
//
|
|
// var page int
|
|
// if len(pageStr) > 0 {
|
|
// p, err := strconv.Atoi(pageStr)
|
|
// if err != nil {
|
|
// return getNotesQuery{}, errors.Errorf("invalid page %s", pageStr)
|
|
// }
|
|
// if p < 1 {
|
|
// return getNotesQuery{}, errors.Errorf("invalid page %s", pageStr)
|
|
// }
|
|
//
|
|
// page = p
|
|
// } else {
|
|
// page = 1
|
|
// }
|
|
//
|
|
// var year int
|
|
// if len(yearStr) > 0 {
|
|
// y, err := strconv.Atoi(yearStr)
|
|
// if err != nil {
|
|
// return getNotesQuery{}, errors.Errorf("invalid year %s", yearStr)
|
|
// }
|
|
//
|
|
// year = y
|
|
// }
|
|
//
|
|
// var month int
|
|
// if len(monthStr) > 0 {
|
|
// m, err := strconv.Atoi(monthStr)
|
|
// if err != nil {
|
|
// return getNotesQuery{}, errors.Errorf("invalid month %s", monthStr)
|
|
// }
|
|
// if m < 1 || m > 12 {
|
|
// return getNotesQuery{}, errors.Errorf("invalid month %s", monthStr)
|
|
// }
|
|
//
|
|
// month = m
|
|
// }
|
|
//
|
|
// var encrypted bool
|
|
// if strings.ToLower(encryptedStr) == "true" {
|
|
// encrypted = true
|
|
// } else {
|
|
// encrypted = false
|
|
// }
|
|
//
|
|
// ret := getNotesQuery{
|
|
// Year: year,
|
|
// Month: month,
|
|
// Page: page,
|
|
// Search: parseSearchQuery(q),
|
|
// Books: books,
|
|
// Encrypted: encrypted,
|
|
// }
|
|
//
|
|
// return ret, nil
|
|
// }
|
|
//
|
|
// func getDateBounds(year, month int) (int64, int64) {
|
|
// var yearUpperbound, monthUpperbound int
|
|
//
|
|
// if month == 12 {
|
|
// monthUpperbound = 1
|
|
// yearUpperbound = year + 1
|
|
// } else {
|
|
// monthUpperbound = month + 1
|
|
// yearUpperbound = year
|
|
// }
|
|
//
|
|
// lower := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.UTC).UnixNano()
|
|
// upper := time.Date(yearUpperbound, time.Month(monthUpperbound), 1, 0, 0, 0, 0, time.UTC).UnixNano()
|
|
//
|
|
// return lower, upper
|
|
// }
|
|
//
|
|
// func getNotesBaseQuery(db *gorm.DB, userID int, q getNotesQuery) *gorm.DB {
|
|
// conn := db.Where(
|
|
// "notes.user_id = ? AND notes.deleted = ? AND notes.encrypted = ?",
|
|
// userID, false, q.Encrypted,
|
|
// )
|
|
//
|
|
// if q.Search != "" {
|
|
// conn = selectFTSFields(conn, q.Search, nil)
|
|
// conn = conn.Where("tsv @@ plainto_tsquery('english_nostop', ?)", q.Search)
|
|
// }
|
|
//
|
|
// if len(q.Books) > 0 {
|
|
// conn = conn.Joins("INNER JOIN books ON books.uuid = notes.book_uuid").
|
|
// Where("books.label in (?)", q.Books)
|
|
// }
|
|
//
|
|
// if q.Year != 0 || q.Month != 0 {
|
|
// dateLowerbound, dateUpperbound := getDateBounds(q.Year, q.Month)
|
|
// conn = conn.Where("notes.added_on >= ? AND notes.added_on < ?", dateLowerbound, dateUpperbound)
|
|
// }
|
|
//
|
|
// return conn
|
|
// }
|
|
//
|
|
// func orderGetNotes(conn *gorm.DB) *gorm.DB {
|
|
// return conn.Order("notes.updated_at DESC, notes.id DESC")
|
|
// }
|
|
//
|
|
// // escapeSearchQuery escapes the query for full text search
|
|
// func escapeSearchQuery(searchQuery string) string {
|
|
// return strings.Join(strings.Fields(searchQuery), "&")
|
|
// }
|
|
//
|
|
// func (a *API) legacyGetNotes(w http.ResponseWriter, r *http.Request) {
|
|
// user, ok := r.Context().Value(helpers.KeyUser).(database.User)
|
|
// if !ok {
|
|
// middleware.DoError(w, "No authenticated user found", nil, http.StatusInternalServerError)
|
|
// return
|
|
// }
|
|
//
|
|
// var notes []database.Note
|
|
// if err := a.App.DB.Where("user_id = ? AND encrypted = true", user.ID).Find(¬es).Error; err != nil {
|
|
// middleware.DoError(w, "finding notes", err, http.StatusInternalServerError)
|
|
// return
|
|
// }
|
|
//
|
|
// presented := presenters.PresentNotes(notes)
|
|
// middleware.RespondJSON(w, http.StatusOK, presented)
|
|
// }
|