From 3ea58a0cdc3e33191afd3eed846261041b5c8a7e Mon Sep 17 00:00:00 2001 From: Yang Luo Date: Thu, 11 Feb 2021 22:56:08 +0800 Subject: [PATCH] Add account APIs. --- controllers/account.go | 145 +++++++++++++++++++++++++++++++++++++++++ object/check.go | 23 +++++++ object/user.go | 9 +++ routers/router.go | 5 ++ util/json.go | 13 ++++ util/log.go | 58 +++++++++++++++++ util/time.go | 10 +++ 7 files changed, 263 insertions(+) create mode 100644 controllers/account.go create mode 100644 object/check.go create mode 100644 util/json.go create mode 100644 util/log.go create mode 100644 util/time.go diff --git a/controllers/account.go b/controllers/account.go new file mode 100644 index 00000000..effea743 --- /dev/null +++ b/controllers/account.go @@ -0,0 +1,145 @@ +package controllers + +import ( + "encoding/json" + + "github.com/casdoor/casdoor/object" + "github.com/casdoor/casdoor/util" +) + +type RegisterForm struct { + Organization string `json:"organization"` + Username string `json:"username"` + Password string `json:"password"` + Name string `json:"name"` + Email string `json:"email"` + Phone string `json:"phone"` +} + +type Response struct { + Status string `json:"status"` + Msg string `json:"msg"` + Data interface{} `json:"data"` +} + +// @Title Register +// @Description register a new user +// @Param username formData string true "The username to register" +// @Param password formData string true "The password" +// @Success 200 {object} controllers.api_controller.Response The Response object +// @router /register [post] +func (c *ApiController) Register() { + var resp Response + + if c.GetSessionUser() != "" { + resp = Response{Status: "error", Msg: "please log out first before signing up", Data: c.GetSessionUser()} + c.Data["json"] = resp + c.ServeJSON() + return + } + + var form RegisterForm + err := json.Unmarshal(c.Ctx.Input.RequestBody, &form) + if err != nil { + panic(err) + } + + msg := object.CheckUserRegister(form.Username, form.Password) + if msg != "" { + resp = Response{Status: "error", Msg: msg, Data: ""} + } else { + user := &object.User{ + Owner: form.Organization, + Name: form.Username, + CreatedTime: util.GetCurrentTime(), + Password: form.Password, + PasswordType: "plain", + DisplayName: form.Name, + Email: form.Email, + Phone: form.Phone, + } + object.AddUser(user) + + //c.SetSessionUser(user) + + util.LogInfo(c.Ctx, "API: [%s] is registered as new user", user) + resp = Response{Status: "ok", Msg: "注册成功", Data: user} + } + + c.Data["json"] = resp + c.ServeJSON() +} + +// @Title Login +// @Description login as a user +// @Param username formData string true "The username to login" +// @Param password formData string true "The password" +// @Success 200 {object} controllers.api_controller.Response The Response object +// @router /login [post] +func (c *ApiController) Login() { + var resp Response + + if c.GetSessionUser() != "" { + resp = Response{Status: "error", Msg: "please log out first before signing in", Data: c.GetSessionUser()} + c.Data["json"] = resp + c.ServeJSON() + return + } + + var form RegisterForm + err := json.Unmarshal(c.Ctx.Input.RequestBody, &form) + if err != nil { + panic(err) + } + + user, password := form.Username, form.Password + msg := object.CheckUserLogin(user, password) + + if msg != "" { + resp = Response{Status: "error", Msg: msg, Data: ""} + } else { + c.SetSessionUser(user) + + util.LogInfo(c.Ctx, "API: [%s] logged in", user) + resp = Response{Status: "ok", Msg: "", Data: user} + } + + c.Data["json"] = resp + c.ServeJSON() +} + +// @Title Logout +// @Description logout the current user +// @Success 200 {object} controllers.api_controller.Response The Response object +// @router /logout [post] +func (c *ApiController) Logout() { + var resp Response + + user := c.GetSessionUser() + util.LogInfo(c.Ctx, "API: [%s] logged out", user) + + c.SetSessionUser("") + + resp = Response{Status: "ok", Msg: "", Data: user} + + c.Data["json"] = resp + c.ServeJSON() +} + +func (c *ApiController) GetAccount() { + var resp Response + + if c.GetSessionUser() == "" { + resp = Response{Status: "error", Msg: "please sign in first", Data: c.GetSessionUser()} + c.Data["json"] = resp + c.ServeJSON() + return + } + + username := c.GetSessionUser() + userObj := object.GetUser(username) + resp = Response{Status: "ok", Msg: "", Data: util.StructToJson(userObj)} + + c.Data["json"] = resp + c.ServeJSON() +} diff --git a/object/check.go b/object/check.go new file mode 100644 index 00000000..b88f49c0 --- /dev/null +++ b/object/check.go @@ -0,0 +1,23 @@ +package object + +func CheckUserRegister(userId string, password string) string { + if len(userId) == 0 || len(password) == 0 { + return "username and password cannot be blank" + } else if HasUser(userId) { + return "username already exists" + } else { + return "" + } +} + +func CheckUserLogin(userId string, password string) string { + if !HasUser(userId) { + return "username does not exist, please sign up first" + } + + if !IsPasswordCorrect(userId, password) { + return "password incorrect" + } + + return "" +} diff --git a/object/user.go b/object/user.go index ca7df4aa..a31d92e6 100644 --- a/object/user.go +++ b/object/user.go @@ -60,6 +60,15 @@ func GetUser(id string) *User { return getUser(owner, name) } +func HasUser(id string) bool { + return GetUser(id) != nil +} + +func IsPasswordCorrect(userId string, password string) bool { + user := GetUser(userId) + return user.Password == password +} + func UpdateUser(id string, user *User) bool { owner, name := util.GetOwnerAndNameFromId(id) if getUser(owner, name) == nil { diff --git a/routers/router.go b/routers/router.go index 13ceb7cb..66430e93 100644 --- a/routers/router.go +++ b/routers/router.go @@ -33,6 +33,11 @@ func initAPI() { ) beego.AddNamespace(ns) + beego.Router("/api/register", &controllers.ApiController{}, "POST:Register") + beego.Router("/api/login", &controllers.ApiController{}, "POST:Login") + beego.Router("/api/logout", &controllers.ApiController{}, "POST:Logout") + beego.Router("/api/get-account", &controllers.ApiController{}, "GET:GetAccount") + beego.Router("/api/get-organizations", &controllers.ApiController{}, "GET:GetOrganizations") beego.Router("/api/get-organization", &controllers.ApiController{}, "GET:GetOrganization") beego.Router("/api/update-organization", &controllers.ApiController{}, "POST:UpdateOrganization") diff --git a/util/json.go b/util/json.go new file mode 100644 index 00000000..6adb06f1 --- /dev/null +++ b/util/json.go @@ -0,0 +1,13 @@ +package util + +import "encoding/json" + +func StructToJson(v interface{}) string { + //data, err := json.MarshalIndent(v, "", " ") + data, err := json.Marshal(v) + if err != nil { + panic(err) + } + + return string(data) +} diff --git a/util/log.go b/util/log.go new file mode 100644 index 00000000..6533c28a --- /dev/null +++ b/util/log.go @@ -0,0 +1,58 @@ +package util + +import ( + "fmt" + "net/http" + "strings" + + "github.com/astaxie/beego/context" + "github.com/astaxie/beego/logs" +) + +func GetIPInfo(clientIP string) string { + if clientIP == "" { + return "" + } + + ips := strings.Split(clientIP, ",") + res := "" + for i := range ips { + ip := strings.TrimSpace(ips[i]) + //desc := GetDescFromIP(ip) + ipstr := fmt.Sprintf("%s: %s", ip, "") + if i != len(ips) - 1 { + res += ipstr + " -> " + } else { + res += ipstr + } + } + + return res +} + +func getIPFromRequest(req *http.Request) string { + clientIP := req.Header.Get("x-forwarded-for") + if clientIP == "" { + ipPort := strings.Split(req.RemoteAddr, ":") + if len(ipPort) >= 1 && len(ipPort) <= 2 { + clientIP = ipPort[0] + } else if len(ipPort) > 2 { + idx := strings.LastIndex(req.RemoteAddr, ":") + clientIP = req.RemoteAddr[0:idx] + clientIP = strings.TrimLeft(clientIP, "[") + clientIP = strings.TrimRight(clientIP, "]") + } + } + + return GetIPInfo(clientIP) +} + +func LogInfo(ctx *context.Context, f string, v ...interface{}) { + ipString := fmt.Sprintf("(%s) ", getIPFromRequest(ctx.Request)) + logs.Info(ipString + f, v...) +} + +func LogWarning(ctx *context.Context, f string, v ...interface{}) { + ipString := fmt.Sprintf("(%s) ", getIPFromRequest(ctx.Request)) + logs.Warning(ipString + f, v...) +} diff --git a/util/time.go b/util/time.go new file mode 100644 index 00000000..088b10a4 --- /dev/null +++ b/util/time.go @@ -0,0 +1,10 @@ +package util + +import "time" + +func GetCurrentTime() string { + timestamp := time.Now().Unix() + tm := time.Unix(timestamp, 0) + return tm.Format(time.RFC3339) +} +