refactor: backend

This commit is contained in:
email
2022-02-03 15:32:03 +08:00
parent 3d8997a43a
commit d661134b03
42 changed files with 2601 additions and 1289 deletions

View File

@@ -1,113 +1,11 @@
package api
import (
"encoding/json"
"memos/api/e"
"memos/store"
"net/http"
"github.com/gorilla/mux"
)
func handleUserSignUp(w http.ResponseWriter, r *http.Request) {
type UserSignUpDataBody struct {
Username string `json:"username"`
Password string `json:"password"`
}
userSignup := UserSignUpDataBody{}
err := json.NewDecoder(r.Body).Decode(&userSignup)
if err != nil {
e.ErrorHandler(w, "REQUEST_BODY_ERROR", "Bad request")
return
}
usernameUsable, _ := store.CheckUsernameUsable(userSignup.Username)
if !usernameUsable {
json.NewEncoder(w).Encode(Response{
Succeed: false,
Message: "Username is existed",
Data: nil,
})
return
}
user, err := store.CreateNewUser(userSignup.Username, userSignup.Password)
if err != nil {
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
return
}
session, _ := SessionStore.Get(r, "session")
session.Values["user_id"] = user.Id
session.Save(r, w)
json.NewEncoder(w).Encode(Response{
Succeed: true,
Message: "",
Data: user,
})
type Login struct {
Name string
Password string
}
func handleUserSignIn(w http.ResponseWriter, r *http.Request) {
type UserSigninDataBody struct {
Username string `json:"username"`
Password string `json:"password"`
}
userSignin := UserSigninDataBody{}
err := json.NewDecoder(r.Body).Decode(&userSignin)
if err != nil {
e.ErrorHandler(w, "REQUEST_BODY_ERROR", "Bad request")
return
}
user, err := store.GetUserByUsernameAndPassword(userSignin.Username, userSignin.Password)
if err != nil {
json.NewEncoder(w).Encode(Response{
Succeed: false,
Message: "Username and password not allowed",
Data: nil,
})
return
}
session, _ := SessionStore.Get(r, "session")
session.Values["user_id"] = user.Id
session.Save(r, w)
json.NewEncoder(w).Encode(Response{
Succeed: true,
Message: "",
Data: user,
})
}
func handleUserSignOut(w http.ResponseWriter, r *http.Request) {
session, _ := SessionStore.Get(r, "session")
session.Values["user_id"] = ""
session.Save(r, w)
json.NewEncoder(w).Encode(Response{
Succeed: true,
Message: "",
Data: nil,
})
}
func RegisterAuthRoutes(r *mux.Router) {
authRouter := r.PathPrefix("/api/auth").Subrouter()
authRouter.Use(JSONResponseMiddleWare)
authRouter.HandleFunc("/signup", handleUserSignUp).Methods("POST")
authRouter.HandleFunc("/signin", handleUserSignIn).Methods("POST")
authRouter.HandleFunc("/signout", handleUserSignOut).Methods("POST")
type Signup struct {
Name string
Password string
}

View File

@@ -1,14 +0,0 @@
package e
var Codes = map[string]int{
"NOT_AUTH": 20001,
"REQUEST_BODY_ERROR": 40001,
"UPLOAD_FILE_ERROR": 40002,
"OVERLOAD_MAX_SIZE": 40003,
"NOT_FOUND": 40400,
"USER_NOT_FOUND": 40401,
"RESOURCE_NOT_FOUND": 40402,
"DATABASE_ERROR": 50001,
}

View File

@@ -1,50 +0,0 @@
package e
import (
"encoding/json"
"net/http"
)
type ServerError struct {
Code int
Message string
}
type ErrorResponse struct {
Succeed bool `json:"succeed"`
Message string `json:"message"`
StatusCode int `json:"statusCode"`
Data interface{} `json:"data"`
}
func getServerError(err string) ServerError {
code, exists := Codes[err]
println(err)
if !exists {
err = "BAD_REQUEST"
code = 40000
}
return ServerError{
Code: code,
Message: err,
}
}
func ErrorHandler(w http.ResponseWriter, err string, message string) {
serverError := getServerError(err)
res := ErrorResponse{
Succeed: false,
Message: message,
StatusCode: serverError.Code,
Data: nil,
}
statusCode := int(serverError.Code / 100)
w.WriteHeader(statusCode)
json.NewEncoder(w).Encode(res)
}

View File

@@ -1,115 +1,41 @@
package api
import (
"encoding/json"
"memos/api/e"
"memos/store"
"net/http"
type Memo struct {
Id int `jsonapi:"primary,memo"`
CreatedTs int64 `jsonapi:"attr,createdTs"`
UpdatedTs int64 `jsonapi:"attr,updatedTs"`
RowStatus string `jsonapi:"attr,rowStatus"`
"github.com/gorilla/mux"
)
func handleGetMyMemos(w http.ResponseWriter, r *http.Request) {
userId, _ := GetUserIdInSession(r)
urlParams := r.URL.Query()
deleted := urlParams.Get("deleted")
onlyDeletedFlag := deleted == "true"
memos, err := store.GetMemosByUserId(userId, onlyDeletedFlag)
if err != nil {
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
return
}
json.NewEncoder(w).Encode(Response{
Succeed: true,
Message: "",
Data: memos,
})
Content string `jsonapi:"attr,content"`
CreatorId int `jsonapi:"attr,creatorId"`
}
func handleCreateMemo(w http.ResponseWriter, r *http.Request) {
userId, _ := GetUserIdInSession(r)
type CreateMemoDataBody struct {
Content string `json:"content"`
}
createMemo := CreateMemoDataBody{}
err := json.NewDecoder(r.Body).Decode(&createMemo)
if err != nil {
e.ErrorHandler(w, "REQUEST_BODY_ERROR", "Bad request")
return
}
memo, err := store.CreateNewMemo(createMemo.Content, userId)
if err != nil {
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
return
}
json.NewEncoder(w).Encode(Response{
Succeed: true,
Message: "",
Data: memo,
})
type MemoCreate struct {
Content string `jsonapi:"attr,content"`
CreatorId int
}
func handleUpdateMemo(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
memoId := vars["id"]
type MemoPatch struct {
Id int
memoPatch := store.MemoPatch{}
err := json.NewDecoder(r.Body).Decode(&memoPatch)
if err != nil {
e.ErrorHandler(w, "REQUEST_BODY_ERROR", "Bad request")
return
}
memo, err := store.UpdateMemo(memoId, &memoPatch)
if err != nil {
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
return
}
json.NewEncoder(w).Encode(Response{
Succeed: true,
Message: "",
Data: memo,
})
Content *string
RowStatus *string
}
func handleDeleteMemo(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
memoId := vars["id"]
err := store.DeleteMemo(memoId)
if err != nil {
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
return
}
json.NewEncoder(w).Encode(Response{
Succeed: true,
Message: "",
Data: nil,
})
type MemoFind struct {
Id *int
CreatorId *int
}
func RegisterMemoRoutes(r *mux.Router) {
memoRouter := r.PathPrefix("/api/memo").Subrouter()
memoRouter.Use(JSONResponseMiddleWare)
memoRouter.Use(AuthCheckerMiddleWare)
memoRouter.HandleFunc("/all", handleGetMyMemos).Methods("GET")
memoRouter.HandleFunc("/", handleCreateMemo).Methods("PUT")
memoRouter.HandleFunc("/{id}", handleUpdateMemo).Methods("PATCH")
memoRouter.HandleFunc("/{id}", handleDeleteMemo).Methods("DELETE")
type MemoDelete struct {
Id *int `jsonapi:"primary,memo"`
CreatorId *int
}
type MemoService interface {
CreateMemo(create *MemoCreate) (*Memo, error)
PatchMemo(patch *MemoPatch) (*Memo, error)
FindMemoList(find *MemoFind) ([]*Memo, error)
FindMemo(find *MemoFind) (*Memo, error)
DeleteMemo(delete *MemoDelete) error
}

View File

@@ -1,36 +0,0 @@
package api
import (
"memos/api/e"
"net/http"
)
func AuthCheckerMiddleWare(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
session, _ := SessionStore.Get(r, "session")
if userId, ok := session.Values["user_id"].(string); !ok || userId == "" {
e.ErrorHandler(w, "NOT_AUTH", "Need authorize")
return
}
next.ServeHTTP(w, r)
})
}
func JSONResponseMiddleWare(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
next.ServeHTTP(w, r)
})
}
func CorsMiddleWare(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
next.ServeHTTP(w, r)
})
}

View File

@@ -1,113 +0,0 @@
package api
import (
"encoding/json"
"memos/api/e"
"memos/store"
"net/http"
"github.com/gorilla/mux"
)
func handleGetMyQueries(w http.ResponseWriter, r *http.Request) {
userId, _ := GetUserIdInSession(r)
queries, err := store.GetQueriesByUserId(userId)
if err != nil {
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
return
}
json.NewEncoder(w).Encode(Response{
Succeed: true,
Message: "",
Data: queries,
})
}
func handleCreateQuery(w http.ResponseWriter, r *http.Request) {
userId, _ := GetUserIdInSession(r)
type CreateQueryDataBody struct {
Title string `json:"title"`
Querystring string `json:"querystring"`
}
queryData := CreateQueryDataBody{}
err := json.NewDecoder(r.Body).Decode(&queryData)
if err != nil {
e.ErrorHandler(w, "REQUEST_BODY_ERROR", "Bad request")
return
}
query, err := store.CreateNewQuery(queryData.Title, queryData.Querystring, userId)
if err != nil {
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
return
}
json.NewEncoder(w).Encode(Response{
Succeed: true,
Message: "",
Data: query,
})
}
func handleUpdateQuery(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
queryId := vars["id"]
queryPatch := store.QueryPatch{}
err := json.NewDecoder(r.Body).Decode(&queryPatch)
if err != nil {
e.ErrorHandler(w, "REQUEST_BODY_ERROR", "Bad request")
return
}
query, err := store.UpdateQuery(queryId, &queryPatch)
if err != nil {
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
return
}
json.NewEncoder(w).Encode(Response{
Succeed: true,
Message: "",
Data: query,
})
}
func handleDeleteQuery(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
queryId := vars["id"]
err := store.DeleteQuery(queryId)
if err != nil {
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
return
}
json.NewEncoder(w).Encode(Response{
Succeed: true,
Message: "",
Data: nil,
})
}
func RegisterQueryRoutes(r *mux.Router) {
queryRouter := r.PathPrefix("/api/query").Subrouter()
queryRouter.Use(JSONResponseMiddleWare)
queryRouter.Use(AuthCheckerMiddleWare)
queryRouter.HandleFunc("/all", handleGetMyQueries).Methods("GET")
queryRouter.HandleFunc("/", handleCreateQuery).Methods("PUT")
queryRouter.HandleFunc("/{id}", handleUpdateQuery).Methods("PATCH")
queryRouter.HandleFunc("/{id}", handleDeleteQuery).Methods("DELETE")
}

View File

@@ -1,130 +1,40 @@
package api
import (
"encoding/json"
"io/ioutil"
"memos/api/e"
"memos/store"
"net/http"
"strings"
type Resource struct {
Id int `jsonapi:"primary,resource"`
CreatedTs int64 `jsonapi:"attr,createdTs"`
UpdatedTs int64 `jsonapi:"attr,updatedTs"`
"github.com/gorilla/mux"
)
Filename string `jsonapi:"attr,filename"`
Blob []byte `jsonapi:"attr,blob"`
Type string `jsonapi:"attr,type"`
Size int64 `jsonapi:"attr,size"`
func handleGetMyResources(w http.ResponseWriter, r *http.Request) {
userId, _ := GetUserIdInSession(r)
resources, err := store.GetResourcesByUserId(userId)
if err != nil {
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
return
}
json.NewEncoder(w).Encode(Response{
Succeed: true,
Message: "",
Data: resources,
})
CreatorId int `jsonapi:"attr,creatorId"`
}
func handleUploadResource(w http.ResponseWriter, r *http.Request) {
userId, _ := GetUserIdInSession(r)
type ResourceCreate struct {
Filename string `jsonapi:"attr,filename"`
Blob []byte `jsonapi:"attr,blob"`
Type string `jsonapi:"attr,type"`
Size int64 `jsonapi:"attr,size"`
err := r.ParseMultipartForm(5 << 20)
if err != nil {
e.ErrorHandler(w, "OVERLOAD_MAX_SIZE", "The max size of resource is 5Mb.")
return
}
file, handler, err := r.FormFile("file")
if err != nil {
e.ErrorHandler(w, "REQUEST_BODY_ERROR", "Bad request")
return
}
defer file.Close()
filename := handler.Filename
filetype := handler.Header.Get("Content-Type")
size := handler.Size
fileBytes, err := ioutil.ReadAll(file)
if err != nil {
e.ErrorHandler(w, "UPLOAD_FILE_ERROR", "Read file error")
return
}
resource, err := store.CreateResource(userId, filename, fileBytes, filetype, size)
if err != nil {
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
return
}
json.NewEncoder(w).Encode(Response{
Succeed: true,
Message: "Upload file succeed",
Data: resource,
})
CreatorId int `jsonapi:"attr,creatorId"`
}
func handleDeleteResource(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
resourceId := vars["id"]
err := store.DeleteResourceById(resourceId)
if err != nil {
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
return
}
json.NewEncoder(w).Encode(Response{
Succeed: true,
Message: "",
Data: nil,
})
type ResourceFind struct {
Id *int
CreatorId *int
Filename *string
}
func handleGetResource(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
resourceId := vars["id"]
filename := vars["filename"]
etag := `"` + resourceId + "/" + filename + `"`
w.Header().Set("Etag", etag)
w.Header().Set("Cache-Control", "max-age=2592000")
if match := r.Header.Get("If-None-Match"); match != "" {
if strings.Contains(match, etag) {
w.WriteHeader(http.StatusNotModified)
return
}
}
resource, err := store.GetResourceByIdAndFilename(resourceId, filename)
if err != nil {
e.ErrorHandler(w, "RESOURCE_NOT_FOUND", err.Error())
return
}
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "application/octet-stream")
w.Write(resource.Blob)
type ResourceDelete struct {
Id int
}
func RegisterResourceRoutes(r *mux.Router) {
resourceRouter := r.PathPrefix("/").Subrouter()
resourceRouter.Use(AuthCheckerMiddleWare)
resourceRouter.HandleFunc("/api/resource/all", handleGetMyResources).Methods("GET")
resourceRouter.HandleFunc("/api/resource/", handleUploadResource).Methods("PUT")
resourceRouter.HandleFunc("/api/resource/{id}", handleDeleteResource).Methods("DELETE")
resourceRouter.HandleFunc("/r/{id}/{filename}", handleGetResource).Methods("GET")
type ResourceService interface {
CreateResource(create *ResourceCreate) (*Resource, error)
FindResourceList(find *ResourceFind) ([]*Resource, error)
FindResource(find *ResourceFind) (*Resource, error)
DeleteResource(delete *ResourceDelete) error
}

View File

@@ -1,9 +0,0 @@
package api
import (
"memos/utils"
"github.com/gorilla/sessions"
)
var SessionStore = sessions.NewCookieStore([]byte(utils.GenUUID()))

53
api/shortcut.go Normal file
View File

@@ -0,0 +1,53 @@
package api
type Shortcut struct {
Id int `jsonapi:"primary,shortcut"`
CreatedTs int64 `jsonapi:"attr,createdTs"`
UpdatedTs int64 `jsonapi:"attr,updatedTs"`
Title string `jsonapi:"attr,title"`
Payload string `jsonapi:"attr,payload"`
PinnedTs int64 `jsonapi:"attr,pinnedTs"`
CreatorId int
}
type ShortcutCreate struct {
// Standard fields
CreatorId int
// Domain specific fields
Title string `jsonapi:"attr,title"`
Payload string `jsonapi:"attr,payload"`
}
type ShortcutPatch struct {
Id int
Title *string `jsonapi:"attr,title"`
Payload *string `jsonapi:"attr,payload"`
PinnedTs *int64
Pinned *bool `jsonapi:"attr,pinned"`
}
type ShortcutFind struct {
Id *int
// Standard fields
CreatorId *int
// Domain specific fields
Title *string `jsonapi:"attr,title"`
}
type ShortcutDelete struct {
Id int
}
type ShortcutService interface {
CreateShortcut(create *ShortcutCreate) (*Shortcut, error)
PatchShortcut(patch *ShortcutPatch) (*Shortcut, error)
FindShortcutList(find *ShortcutFind) ([]*Shortcut, error)
FindShortcut(find *ShortcutFind) (*Shortcut, error)
DeleteShortcut(delete *ShortcutDelete) error
}

View File

@@ -1,34 +0,0 @@
package api
import (
"net/http"
"os"
"path/filepath"
)
type SPAHandler struct {
StaticPath string
IndexPath string
}
func (h SPAHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
path, err := filepath.Abs(r.URL.Path)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
path = filepath.Join(h.StaticPath, path)
_, err = os.Stat(path)
if os.IsNotExist(err) {
// file does not exist, serve index.html
http.ServeFile(w, r, filepath.Join(h.StaticPath, h.IndexPath))
return
} else if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
http.FileServer(http.Dir(h.StaticPath)).ServeHTTP(w, r)
}

View File

@@ -1,149 +1,40 @@
package api
import (
"encoding/json"
"memos/api/e"
"memos/store"
"net/http"
type User struct {
Id int `jsonapi:"primary,user"`
CreatedTs int64 `jsonapi:"attr,createdTs"`
UpdatedTs int64 `jsonapi:"attr,updatedTs"`
"github.com/gorilla/mux"
)
func handleGetMyUserInfo(w http.ResponseWriter, r *http.Request) {
userId, _ := GetUserIdInSession(r)
user, err := store.GetUserById(userId)
if err != nil {
e.ErrorHandler(w, "USER_NOT_FOUND", err.Error())
return
}
json.NewEncoder(w).Encode(Response{
Succeed: true,
Message: "",
Data: user,
})
Name string `jsonapi:"attr,name"`
Password string
OpenId string `jsonapi:"attr,openId"`
}
func handleUpdateMyUserInfo(w http.ResponseWriter, r *http.Request) {
userId, _ := GetUserIdInSession(r)
updateUserPatch := store.UpdateUserPatch{}
err := json.NewDecoder(r.Body).Decode(&updateUserPatch)
if err != nil {
e.ErrorHandler(w, "REQUEST_BODY_ERROR", "Bad request")
return
}
if updateUserPatch.Username != nil {
usernameUsable, _ := store.CheckUsernameUsable(*updateUserPatch.Username)
if !usernameUsable {
json.NewEncoder(w).Encode(Response{
Succeed: false,
Message: "Username is existed",
Data: nil,
})
return
}
}
user, err := store.UpdateUser(userId, &updateUserPatch)
if err != nil {
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
return
}
json.NewEncoder(w).Encode(Response{
Succeed: true,
Message: "",
Data: user,
})
type UserCreate struct {
Name string `jsonapi:"attr,name"`
Password string `jsonapi:"attr,password"`
OpenId string `jsonapi:"attr,openId"`
}
func handleResetUserOpenId(w http.ResponseWriter, r *http.Request) {
userId, _ := GetUserIdInSession(r)
type UserPatch struct {
Id int
openId, err := store.ResetUserOpenId(userId)
Name *string `jsonapi:"attr,name"`
Password *string `jsonapi:"attr,password"`
OpenId *string
if err != nil {
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
return
}
json.NewEncoder(w).Encode(Response{
Succeed: true,
Message: "",
Data: openId,
})
ResetOpenId *bool `jsonapi:"attr,resetOpenId"`
}
func handleCheckUsername(w http.ResponseWriter, r *http.Request) {
type CheckUsernameDataBody struct {
Username string
}
type UserFind struct {
Id *int `jsonapi:"attr,id"`
checkUsername := CheckUsernameDataBody{}
err := json.NewDecoder(r.Body).Decode(&checkUsername)
if err != nil {
e.ErrorHandler(w, "REQUEST_BODY_ERROR", "Bad request")
return
}
usable, err := store.CheckUsernameUsable(checkUsername.Username)
if err != nil {
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
return
}
json.NewEncoder(w).Encode(Response{
Succeed: true,
Message: "",
Data: usable,
})
Name *string `jsonapi:"attr,name"`
OpenId *string
}
func handleValidPassword(w http.ResponseWriter, r *http.Request) {
type ValidPasswordDataBody struct {
Password string
}
userId, _ := GetUserIdInSession(r)
validPassword := ValidPasswordDataBody{}
err := json.NewDecoder(r.Body).Decode(&validPassword)
if err != nil {
e.ErrorHandler(w, "REQUEST_BODY_ERROR", "Bad request")
return
}
valid, err := store.CheckPasswordValid(userId, validPassword.Password)
if err != nil {
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
return
}
json.NewEncoder(w).Encode(Response{
Succeed: true,
Message: "",
Data: valid,
})
}
func RegisterUserRoutes(r *mux.Router) {
userRouter := r.PathPrefix("/api/user").Subrouter()
userRouter.Use(JSONResponseMiddleWare)
userRouter.Use(AuthCheckerMiddleWare)
userRouter.HandleFunc("/me", handleGetMyUserInfo).Methods("GET")
userRouter.HandleFunc("/me", handleUpdateMyUserInfo).Methods("PATCH")
userRouter.HandleFunc("/open_id/new", handleResetUserOpenId).Methods("POST")
userRouter.HandleFunc("/checkusername", handleCheckUsername).Methods("POST")
userRouter.HandleFunc("/validpassword", handleValidPassword).Methods("POST")
type UserService interface {
CreateUser(create *UserCreate) (*User, error)
PatchUser(patch *UserPatch) (*User, error)
FindUser(find *UserFind) (*User, error)
}

View File

@@ -1,23 +0,0 @@
package api
import (
"net/http"
)
type Response struct {
Succeed bool `json:"succeed"`
Message string `json:"message"`
Data interface{} `json:"data"`
}
func GetUserIdInSession(r *http.Request) (string, error) {
session, _ := SessionStore.Get(r, "session")
userId, ok := session.Values["user_id"].(string)
if !ok {
return "", http.ErrNoCookie
}
return userId, nil
}

View File

@@ -1,55 +0,0 @@
package api
import (
"encoding/json"
"memos/api/e"
"memos/store"
"net/http"
"github.com/gorilla/mux"
)
func handleCreateMemoByWH(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
openId := vars["openId"]
type CreateMemoDataBody struct {
Content string `json:"content"`
}
createMemo := CreateMemoDataBody{}
err := json.NewDecoder(r.Body).Decode(&createMemo)
if err != nil {
e.ErrorHandler(w, "REQUEST_BODY_ERROR", "Bad request")
return
}
user, err := store.GetUserByOpenId(openId)
if err != nil {
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
return
}
memo, err := store.CreateNewMemo(createMemo.Content, user.Id)
if err != nil {
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
return
}
json.NewEncoder(w).Encode(Response{
Succeed: true,
Message: "",
Data: memo,
})
}
func RegisterWebHooksRoutes(r *mux.Router) {
memoRouter := r.PathPrefix("/api/whs").Subrouter()
memoRouter.Use(JSONResponseMiddleWare)
memoRouter.HandleFunc("/memo/{openId}", handleCreateMemoByWH).Methods("POST")
}