electricity_bill_calc_service/controller/user.go

335 lines
13 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package controller
import (
"electricity_bill_calc/cache"
"electricity_bill_calc/exceptions"
"electricity_bill_calc/logger"
"electricity_bill_calc/model"
"electricity_bill_calc/repository"
"electricity_bill_calc/response"
"electricity_bill_calc/security"
"electricity_bill_calc/service"
"electricity_bill_calc/tools"
"electricity_bill_calc/vo"
"net/http"
"strconv"
"github.com/gofiber/fiber/v2"
"go.uber.org/zap"
)
var userLog = logger.Named("Handler", "User")
func InitializeUserHandlers(router *fiber.App) {
router.Delete("/login", security.MustAuthenticated, doLogout)
router.Post("/login", doLogin)
router.Get("/account", security.OPSAuthorize, searchUsers)
router.Post("/account", security.OPSAuthorize, createOPSAccount)
router.Get("/account/:uid", security.MustAuthenticated, fetchUserInformation)
router.Put("/account/:uid", security.OPSAuthorize, modifyUserInformation)
router.Put("/account/enabled/state", security.OPSAuthorize, changeUserState)
router.Get("/expiration", security.EnterpriseAuthorize, getAccountExpiration)
router.Post("/enterprise", security.OPSAuthorize, createEnterpriseAccount)
router.Get("/enterprise/quick/search", security.OPSAuthorize, quickSearchEnterprise)
router.Put("/password", resetUserPassword)
router.Delete("/password/:uid", security.OPSAuthorize, invalidUserPassword)
}
type _LoginForm struct {
Username string `json:"uname"`
Password string `json:"upass"`
Type int16 `json:"type"`
}
func doLogin(c *fiber.Ctx) error {
result := response.NewResult(c) //创建一个相应结果对象
loginData := new(_LoginForm) //创建一个解析登录表单数据的实体
if err := c.BodyParser(loginData); err != nil { //解析请求体中的Json数据到loginData里如果解析出错就返回错误
userLog.Error("表单解析失败!", zap.Error(err))
return result.Error(http.StatusInternalServerError, "表单解析失败。") //返回一个内部服务器错误的相应结果
}
var (
session *model.Session
err error
)
userLog.Info("有用户请求登录。", zap.String("username", loginData.Username), zap.Int16("type", loginData.Type)) //记录日志相关信息
if loginData.Type == model.USER_TYPE_ENT { //根据登录类型选择不同的处理方法
session, err = service.UserService.ProcessEnterpriseUserLogin(loginData.Username, loginData.Password) //企业用户
} else {
userLog.Info("该用户是管理用户")
session, err = service.UserService.ProcessManagementUserLogin(loginData.Username, loginData.Password) //管理用户
}
if err != nil {
if authError, ok := err.(*exceptions.AuthenticationError); ok { //检查错误是否为身份验证错误
if authError.NeedReset { //如果需要重置密码则返回对应结果
return result.LoginNeedReset()
}
return result.Error(int(authError.Code), authError.Message) //返回身份验证错误相应
} else {
userLog.Error("用户登录请求处理失败!", zap.Error(err))
return result.Error(http.StatusInternalServerError, err.Error()) //返回内部服务器错误
}
}
return result.LoginSuccess(session) //返回登录成功相应结果,包含会话信息
}
func doLogout(c *fiber.Ctx) error {
result := response.NewResult(c)
session, err := _retreiveSession(c)
if err != nil {
return result.Success("用户会话已结束。")
}
_, err = cache.ClearSession(session.Token)
if err != nil {
userLog.Error("用户登出处理失败!", zap.Error(err))
return result.Error(http.StatusInternalServerError, err.Error())
}
return result.Success("用户已成功登出系统。")
}
func searchUsers(c *fiber.Ctx) error {
result := response.NewResult(c)
requestPage, err := strconv.Atoi(c.Query("page", "1"))
if err != nil {
return result.NotAccept("查询参数[page]格式不正确。")
}
requestKeyword := c.Query("keyword")
requestUserType, err := strconv.Atoi(c.Query("type", "-1"))
if err != nil {
return result.NotAccept("查询参数[type]格式不正确。")
}
var requestUserStat *bool
state, err := strconv.ParseBool(c.Query("state"))
if err != nil {
requestUserStat = nil
} else {
requestUserStat = &state
}
users, total, err := repository.UserRepository.FindUser(
&requestKeyword,
int16(requestUserType),
requestUserStat,
uint(requestPage),
)
if err != nil {
return result.NotFound(err.Error())
}
return result.Success(
"已取得符合条件的用户集合。",
response.NewPagedResponse(requestPage, total).ToMap(),
fiber.Map{"accounts": users},
)
}
func getAccountExpiration(c *fiber.Ctx) error {
result := response.NewResult(c)
session, err := _retreiveSession(c)
if err != nil {
userLog.Error("未找到有效的用户会话。", zap.Error(err))
return result.Error(http.StatusInternalServerError, err.Error())
}
userDetail, err := repository.UserRepository.FindUserDetailById(session.Uid)
if err != nil {
return result.NotFound("未找到指定的用户档案")
}
return result.Success(
"已经取得用户的服务期限信息",
fiber.Map{"expiration": userDetail.ServiceExpiration.Format("2006-01-02")},
)
}
func createOPSAccount(c *fiber.Ctx) error {
userLog.Info("请求创建运维或监管账户。")
result := response.NewResult(c)
creationForm := new(vo.MGTAndOPSAccountCreationForm)
if err := c.BodyParser(creationForm); err != nil {
userLog.Error("表单解析失败!", zap.Error(err))
return result.UnableToParse("无法解析提交的数据。")
}
exists, err := repository.UserRepository.IsUsernameExists(creationForm.Username)
if err != nil {
userLog.Error("检查用户名是否已经被使用时发生错误!", zap.Error(err))
return result.Error(http.StatusInternalServerError, err.Error())
}
if exists {
return result.Conflict("指定的用户名已经被使用了。")
}
verifyCode, err := service.UserService.CreateUserAccount(creationForm.IntoUser(), creationForm.IntoUserDetail())
if err != nil {
userLog.Error("创建用户账户时发生错误!", zap.Error(err))
return result.Error(http.StatusInternalServerError, err.Error())
}
return result.Created("用户已经成功创建。", fiber.Map{"verify": verifyCode})
}
func fetchUserInformation(c *fiber.Ctx) error {
userLog.Info("请求获取用户详细信息。")
result := response.NewResult(c)
targetUserId := c.Params("uid")
exists, err := repository.UserRepository.IsUserExists(targetUserId)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
if !exists {
return result.NotFound("指定的用户不存在。")
}
userDetail, err := repository.UserRepository.FindUserDetailById(targetUserId)
if err != nil {
return result.Error(http.StatusInternalServerError, err.Error())
}
return result.Success("用户详细信息已获取到。", fiber.Map{"user": userDetail})
}
func modifyUserInformation(c *fiber.Ctx) error {
userLog.Info("请求修改用户详细信息。")
session, _ := _retreiveSession(c)
result := response.NewResult(c)
targetUserId := c.Params("uid")
exists, err := repository.UserRepository.IsUserExists(targetUserId)
if err != nil {
userLog.Error("检查用户是否存在时发生错误!", zap.Error(err))
return result.Error(http.StatusInternalServerError, err.Error())
}
if !exists {
return result.NotFound("指定的用户不存在。")
}
modificationForm := new(vo.UserDetailModificationForm)
if err := c.BodyParser(modificationForm); err != nil {
userLog.Error("表单解析失败!", zap.Error(err))
return result.UnableToParse("无法解析提交的数据。")
}
userLog.Debug("用户服务费修改表单:", zap.Any("form", modificationForm))
detailFormForUpdate, err := modificationForm.IntoModificationModel()
if err != nil {
userLog.Error("用户服务费解析转换失败!", zap.Error(err))
return result.UnableToParse("无法解析提交的数据,服务费格式不正确。")
}
if ok, err := repository.UserRepository.UpdateDetail(targetUserId, *detailFormForUpdate, &session.Uid); err != nil || !ok {
userLog.Error("更新用户详细信息失败!", zap.Error(err))
return result.Error(http.StatusInternalServerError, err.Error())
}
return result.Updated("指定用户的信息已经更新。")
}
func changeUserState(c *fiber.Ctx) error {
userLog.Info("请求修改用户状态。")
result := response.NewResult(c)
modificationForm := new(vo.UserStateChangeForm)
if err := c.BodyParser(modificationForm); err != nil {
userLog.Error("表单解析失败!", zap.Error(err))
return result.UnableToParse("无法解析提交的数据。")
}
exists, err := repository.UserRepository.IsUserExists(modificationForm.Uid)
if err != nil {
userLog.Error("检查用户是否存在时发生错误!", zap.Error(err))
return result.Error(http.StatusInternalServerError, err.Error())
}
if !exists {
return result.NotFound("指定的用户不存在。")
}
if ok, err := repository.UserRepository.ChangeState(modificationForm.Uid, modificationForm.Enabled); err != nil || !ok {
userLog.Error("更新用户状态失败!", zap.Error(err))
return result.NotAccept("无法更新用户状态。")
}
return result.Updated("用户的状态已经更新。")
}
func createEnterpriseAccount(c *fiber.Ctx) error {
userLog.Info("请求创建企业账户。")
result := response.NewResult(c)
creationForm := new(vo.EnterpriseAccountCreationForm)
if err := c.BodyParser(creationForm); err != nil {
userLog.Error("表单解析失败!", zap.Error(err))
return result.UnableToParse("无法解析提交的数据。")
}
exists, err := repository.UserRepository.IsUsernameExists(creationForm.Username)
if err != nil {
userLog.Error("检查用户名是否已经被使用时发生错误!", zap.Error(err))
return result.Error(http.StatusInternalServerError, err.Error())
}
if exists {
return result.Conflict("指定的用户名已经被使用了。")
}
userDetail, err := creationForm.IntoUserDetail()
if err != nil {
userLog.Error("转换用户详细档案时发生错误!", zap.Error(err))
return result.UnableToParse("无法解析提交的数据,服务费格式不正确。")
}
verifyCode, err := service.UserService.CreateUserAccount(creationForm.IntoUser(), userDetail)
if err != nil {
userLog.Error("创建用户账户时发生错误!", zap.Error(err))
return result.Error(http.StatusInternalServerError, err.Error())
}
return result.Created("用户已经成功创建。", fiber.Map{"verify": verifyCode})
}
func quickSearchEnterprise(c *fiber.Ctx) error {
userLog.Info("请求快速查询企业账户。")
result := response.NewResult(c)
keyword := c.Query("keyword")
limit := c.QueryInt("limit", 6)
if limit < 1 {
limit = 6
}
users, err := repository.UserRepository.SearchUsersWithLimit(nil, &keyword, uint(limit))
if err != nil {
userLog.Error("查询用户时发生错误!", zap.Error(err))
return result.Error(http.StatusInternalServerError, err.Error())
}
return result.Success("已查询到存在符合条件的企业", fiber.Map{"users": users})
}
func resetUserPassword(c *fiber.Ctx) error {
userLog.Info("请求重置用户密码。")
result := response.NewResult(c)
repasswordForm := new(vo.RepasswordForm)
if err := c.BodyParser(repasswordForm); err != nil {
userLog.Error("表单解析失败!", zap.Error(err))
return result.UnableToParse("无法解析提交的数据。")
}
user, err := repository.UserRepository.FindUserByUsername(repasswordForm.Username)
if err != nil {
userLog.Error("检查用户是否存在时发生错误!", zap.Error(err))
return result.Error(http.StatusInternalServerError, err.Error())
}
if user == nil {
return result.NotFound("指定的用户不存在。")
}
if !service.UserService.MatchUserPassword(user.Password, repasswordForm.VerifyCode) {
return result.Unauthorized("验证码不正确。")
}
ok, err := repository.UserRepository.UpdatePassword(user.Id, repasswordForm.NewPassword, false)
if err != nil {
userLog.Error("更新用户凭据时发生错误!", zap.Error(err))
return result.Error(http.StatusInternalServerError, err.Error())
}
if !ok {
return result.NotAccept("无法更新用户凭据。")
}
return result.Updated("用户凭据已经更新。")
}
func invalidUserPassword(c *fiber.Ctx) error {
userLog.Info("请求使用户凭据失效。")
result := response.NewResult(c)
uid := c.Params("uid")
exists, err := repository.UserRepository.IsUserExists(uid)
if err != nil {
userLog.Error("检查用户是否存在时发生错误!", zap.Error(err))
return result.Error(http.StatusInternalServerError, err.Error())
}
if !exists {
return result.NotFound("指定的用户不存在。")
}
verifyCode := tools.RandStr(10)
ok, err := repository.UserRepository.UpdatePassword(uid, verifyCode, true)
if err != nil {
userLog.Error("更新用户凭据时发生错误!", zap.Error(err))
return result.Error(http.StatusInternalServerError, err.Error())
}
if !ok {
return result.NotAccept("未能更新用户凭据。")
}
return result.Updated("用户凭据已经更新。", fiber.Map{"verify": verifyCode})
}