mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
update restful api
This commit is contained in:
42
api/auth.go
42
api/auth.go
@@ -2,7 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"memos/common/error"
|
||||
"memos/api/e"
|
||||
"memos/store"
|
||||
"net/http"
|
||||
|
||||
@@ -15,22 +15,34 @@ type UserSignUp struct {
|
||||
}
|
||||
|
||||
func handleUserSignUp(w http.ResponseWriter, r *http.Request) {
|
||||
var userSignup UserSignUp
|
||||
userSignup := UserSignUp{}
|
||||
err := json.NewDecoder(r.Body).Decode(&userSignup)
|
||||
|
||||
if err != nil {
|
||||
error.ErrorHandler(w, "REQUEST_BODY_ERROR")
|
||||
e.ErrorHandler(w, "REQUEST_BODY_ERROR", "Bad request")
|
||||
return
|
||||
}
|
||||
|
||||
user, err := store.CreateNewUser(userSignup.Username, userSignup.Password, "", "")
|
||||
|
||||
if err != nil {
|
||||
error.ErrorHandler(w, "")
|
||||
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(user)
|
||||
userIdCookie := &http.Cookie{
|
||||
Name: "user_id",
|
||||
Value: user.Id,
|
||||
Path: "/",
|
||||
MaxAge: 3600 * 24 * 30,
|
||||
}
|
||||
http.SetCookie(w, userIdCookie)
|
||||
|
||||
json.NewEncoder(w).Encode(Response{
|
||||
Succeed: true,
|
||||
Message: "",
|
||||
Data: user,
|
||||
})
|
||||
}
|
||||
|
||||
type UserSignin struct {
|
||||
@@ -39,38 +51,50 @@ type UserSignin struct {
|
||||
}
|
||||
|
||||
func handleUserSignIn(w http.ResponseWriter, r *http.Request) {
|
||||
var userSignin UserSignin
|
||||
userSignin := UserSignin{}
|
||||
err := json.NewDecoder(r.Body).Decode(&userSignin)
|
||||
|
||||
if err != nil {
|
||||
error.ErrorHandler(w, "")
|
||||
e.ErrorHandler(w, "REQUEST_BODY_ERROR", "Bad request")
|
||||
return
|
||||
}
|
||||
|
||||
user, err := store.GetUserByUsernameAndPassword(userSignin.Username, userSignin.Password)
|
||||
|
||||
if err != nil {
|
||||
error.ErrorHandler(w, "")
|
||||
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
userIdCookie := &http.Cookie{
|
||||
Name: "user_id",
|
||||
Value: user.Id,
|
||||
Path: "/",
|
||||
MaxAge: 3600 * 24 * 30,
|
||||
}
|
||||
http.SetCookie(w, userIdCookie)
|
||||
|
||||
json.NewEncoder(w).Encode(user)
|
||||
json.NewEncoder(w).Encode(Response{
|
||||
Succeed: true,
|
||||
Message: "",
|
||||
Data: user,
|
||||
})
|
||||
}
|
||||
|
||||
func handleUserSignOut(w http.ResponseWriter, r *http.Request) {
|
||||
userIdCookie := &http.Cookie{
|
||||
Name: "user_id",
|
||||
Value: "",
|
||||
Path: "/",
|
||||
MaxAge: 0,
|
||||
}
|
||||
http.SetCookie(w, userIdCookie)
|
||||
|
||||
json.NewEncoder(w).Encode(Response{
|
||||
Succeed: true,
|
||||
Message: "",
|
||||
Data: nil,
|
||||
})
|
||||
}
|
||||
|
||||
func RegisterAuthRoutes(r *mux.Router) {
|
||||
|
9
api/e/codes.go
Normal file
9
api/e/codes.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package e
|
||||
|
||||
var Codes = map[string]int{
|
||||
"NOT_AUTH": 20001,
|
||||
|
||||
"REQUEST_BODY_ERROR": 40001,
|
||||
|
||||
"DATABASE_ERROR": 50001,
|
||||
}
|
50
api/e/error.go
Normal file
50
api/e/error.go
Normal file
@@ -0,0 +1,50 @@
|
||||
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)
|
||||
}
|
66
api/memo.go
66
api/memo.go
@@ -2,7 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"memos/common/error"
|
||||
"memos/api/e"
|
||||
"memos/store"
|
||||
"net/http"
|
||||
|
||||
@@ -11,15 +11,22 @@ import (
|
||||
|
||||
func handleGetMyMemos(w http.ResponseWriter, r *http.Request) {
|
||||
userId, _ := GetUserIdInCookie(r)
|
||||
urlParams := r.URL.Query()
|
||||
deleted := urlParams.Get("deleted")
|
||||
onlyDeletedFlag := deleted == "true"
|
||||
|
||||
memos, err := store.GetMemosByUserId(userId)
|
||||
memos, err := store.GetMemosByUserId(userId, onlyDeletedFlag)
|
||||
|
||||
if err != nil {
|
||||
error.ErrorHandler(w, "DATABASE_ERROR")
|
||||
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(memos)
|
||||
json.NewEncoder(w).Encode(Response{
|
||||
Succeed: true,
|
||||
Message: "",
|
||||
Data: memos,
|
||||
})
|
||||
}
|
||||
|
||||
type CreateMemo struct {
|
||||
@@ -29,54 +36,77 @@ type CreateMemo struct {
|
||||
func handleCreateMemo(w http.ResponseWriter, r *http.Request) {
|
||||
userId, _ := GetUserIdInCookie(r)
|
||||
|
||||
var createMemo CreateMemo
|
||||
createMemo := CreateMemo{}
|
||||
err := json.NewDecoder(r.Body).Decode(&createMemo)
|
||||
|
||||
if err != nil {
|
||||
error.ErrorHandler(w, "")
|
||||
e.ErrorHandler(w, "REQUEST_BODY_ERROR", "Bad request")
|
||||
return
|
||||
}
|
||||
|
||||
memo, err := store.CreateNewMemo(createMemo.Content, userId)
|
||||
|
||||
if err != nil {
|
||||
error.ErrorHandler(w, "")
|
||||
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(memo)
|
||||
json.NewEncoder(w).Encode(Response{
|
||||
Succeed: true,
|
||||
Message: "",
|
||||
Data: memo,
|
||||
})
|
||||
}
|
||||
|
||||
func handleUpdateMemo(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
memoId := vars["id"]
|
||||
|
||||
userId, _ := GetUserIdInCookie(r)
|
||||
|
||||
var createMemo CreateMemo
|
||||
err := json.NewDecoder(r.Body).Decode(&createMemo)
|
||||
memoPatch := store.MemoPatch{}
|
||||
err := json.NewDecoder(r.Body).Decode(&memoPatch)
|
||||
|
||||
if err != nil {
|
||||
error.ErrorHandler(w, "")
|
||||
e.ErrorHandler(w, "REQUEST_BODY_ERROR", "Bad request")
|
||||
return
|
||||
}
|
||||
|
||||
memo, err := store.UpdateMemo(memoId, createMemo.Content, userId)
|
||||
memo, err := store.UpdateMemo(memoId, &memoPatch)
|
||||
|
||||
if err != nil {
|
||||
error.ErrorHandler(w, "")
|
||||
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(memo)
|
||||
json.NewEncoder(w).Encode(Response{
|
||||
Succeed: true,
|
||||
Message: "",
|
||||
Data: memo,
|
||||
})
|
||||
}
|
||||
|
||||
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,
|
||||
})
|
||||
}
|
||||
|
||||
func RegisterMemoRoutes(r *mux.Router) {
|
||||
memoRouter := r.PathPrefix("/api/memo").Subrouter()
|
||||
|
||||
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")
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"memos/common/error"
|
||||
"memos/api/e"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
@@ -10,10 +10,19 @@ func AuthCheckerMiddleWare(next http.Handler) http.Handler {
|
||||
userId, err := GetUserIdInCookie(r)
|
||||
|
||||
if err != nil || userId == "" {
|
||||
error.ErrorHandler(w, "NOT_AUTH")
|
||||
e.ErrorHandler(w, "NOT_AUTH", "Need authorize")
|
||||
return
|
||||
}
|
||||
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
110
api/query.go
Normal file
110
api/query.go
Normal file
@@ -0,0 +1,110 @@
|
||||
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, _ := GetUserIdInCookie(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,
|
||||
})
|
||||
}
|
||||
|
||||
type QueryPut struct {
|
||||
Title string `json:"title"`
|
||||
Querystring string `json:"querystring"`
|
||||
}
|
||||
|
||||
func handleCreateQuery(w http.ResponseWriter, r *http.Request) {
|
||||
userId, _ := GetUserIdInCookie(r)
|
||||
|
||||
queryPut := QueryPut{}
|
||||
err := json.NewDecoder(r.Body).Decode(&queryPut)
|
||||
|
||||
if err != nil {
|
||||
e.ErrorHandler(w, "REQUEST_BODY_ERROR", "Bad request")
|
||||
return
|
||||
}
|
||||
|
||||
query, err := store.CreateNewQuery(queryPut.Title, queryPut.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.HandleFunc("/all", handleGetMyQueries).Methods("GET")
|
||||
queryRouter.HandleFunc("/", handleCreateQuery).Methods("PUT")
|
||||
queryRouter.HandleFunc("/{id}", handleUpdateQuery).Methods("PATCH")
|
||||
queryRouter.HandleFunc("/{id}", handleDeleteQuery).Methods("DELETE")
|
||||
}
|
34
api/spa_handler.go
Normal file
34
api/spa_handler.go
Normal file
@@ -0,0 +1,34 @@
|
||||
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)
|
||||
}
|
90
api/user.go
90
api/user.go
@@ -2,7 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"memos/common/error"
|
||||
"memos/api/e"
|
||||
"memos/store"
|
||||
"net/http"
|
||||
|
||||
@@ -15,39 +15,95 @@ func handleGetMyUserInfo(w http.ResponseWriter, r *http.Request) {
|
||||
user, err := store.GetUserById(userId)
|
||||
|
||||
if err != nil {
|
||||
error.ErrorHandler(w, "DATABASE_ERROR")
|
||||
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(user)
|
||||
}
|
||||
|
||||
type UpdateUser struct {
|
||||
Username string `json:"username"`
|
||||
Password string `json:"password"`
|
||||
GithubName string `json:"githubName"`
|
||||
WxOpenId string `json:"wxOpenId"`
|
||||
json.NewEncoder(w).Encode(Response{
|
||||
Succeed: true,
|
||||
Message: "",
|
||||
Data: user,
|
||||
})
|
||||
}
|
||||
|
||||
func handleUpdateMyUserInfo(w http.ResponseWriter, r *http.Request) {
|
||||
userId, _ := GetUserIdInCookie(r)
|
||||
|
||||
user, err := store.GetUserById(userId)
|
||||
userPatch := store.UserPatch{}
|
||||
err := json.NewDecoder(r.Body).Decode(&userPatch)
|
||||
|
||||
if err != nil {
|
||||
error.ErrorHandler(w, "DATABASE_ERROR")
|
||||
e.ErrorHandler(w, "REQUEST_BODY_ERROR", "Bad request")
|
||||
return
|
||||
}
|
||||
|
||||
var updateUser UpdateUser
|
||||
err = json.NewDecoder(r.Body).Decode(&updateUser)
|
||||
user, err := store.UpdateUser(userId, &userPatch)
|
||||
|
||||
if err != nil {
|
||||
error.ErrorHandler(w, "REQUEST_BODY_ERROR")
|
||||
e.ErrorHandler(w, "DATABASE_ERROR", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(user)
|
||||
json.NewEncoder(w).Encode(Response{
|
||||
Succeed: true,
|
||||
Message: "",
|
||||
Data: user,
|
||||
})
|
||||
}
|
||||
|
||||
type CheckUsername struct {
|
||||
Username string
|
||||
}
|
||||
|
||||
func handleCheckUsername(w http.ResponseWriter, r *http.Request) {
|
||||
checkUsername := CheckUsername{}
|
||||
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,
|
||||
})
|
||||
}
|
||||
|
||||
type ValidPassword struct {
|
||||
Password string
|
||||
}
|
||||
|
||||
func handleValidPassword(w http.ResponseWriter, r *http.Request) {
|
||||
userId, _ := GetUserIdInCookie(r)
|
||||
validPassword := ValidPassword{}
|
||||
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) {
|
||||
@@ -57,4 +113,6 @@ func RegisterUserRoutes(r *mux.Router) {
|
||||
|
||||
userRouter.HandleFunc("/me", handleGetMyUserInfo).Methods("GET")
|
||||
userRouter.HandleFunc("/me", handleUpdateMyUserInfo).Methods("PATCH")
|
||||
userRouter.HandleFunc("/checkusername", handleCheckUsername).Methods("POST")
|
||||
userRouter.HandleFunc("/validpassword", handleValidPassword).Methods("POST")
|
||||
}
|
||||
|
10
api/utils.go
10
api/utils.go
@@ -4,8 +4,18 @@ import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type Response struct {
|
||||
Succeed bool `json:"succeed"`
|
||||
Message string `json:"message"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
func GetUserIdInCookie(r *http.Request) (string, error) {
|
||||
userIdCookie, err := r.Cookie("user_id")
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return userIdCookie.Value, err
|
||||
}
|
||||
|
Reference in New Issue
Block a user