Files
bj_power/bj_power_wms/internal/handler/auth.go
T
SunYF ae4c292487 feat: 完成产线MES系统全流程功能迭代与优化
本提交完成了多个核心模块的功能完善与业务对齐:
1. 工位终端:固定工位配置、移除自选工位逻辑、适配配置化工位号
2. MES核心:重构工位组合逻辑、新增工单/流程状态管理、补全报工/追溯逻辑
3. WMS客户端:新增修改密码功能、优化帮助弹窗逻辑
4. 文档与权限:补充完整操作手册、统一菜单名称与权限描述
5. 修复多业务校验:排产数量校验、工单状态校验、工位绑定规则
2026-08-31 12:58:28 +08:00

176 lines
4.9 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 handler
import (
"net/http"
"strings"
"time"
"bj_power_wms/ent/user"
"bj_power_wms/internal/svc"
"golang.org/x/crypto/bcrypt"
)
func healthHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
_, err := ctx.EntClient.User.Query().First(ctx0())
if err == nil || strings.Contains(err.Error(), "no rows") {
ok(w, map[string]any{
"status": "UP",
"time": time.Now().Format("2006-01-02 15:04:05"),
"service": "bj_power_wms",
})
return
}
fail(w, http.StatusServiceUnavailable, "database unavailable")
}
}
func loginHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req struct {
Username string `json:"username"`
Password string `json:"password"`
}
if err := parseJSON(r, &req); err != nil {
fail(w, http.StatusBadRequest, "参数错误")
return
}
if req.Username == "" || req.Password == "" {
fail(w, http.StatusBadRequest, "用户名和密码必填")
return
}
u, err := ctx.EntClient.User.Query().
Where(user.UsernameEQ(req.Username)).
Only(ctx0())
if err != nil {
fail(w, http.StatusUnauthorized, "用户名或密码错误")
return
}
if !u.IsActive {
fail(w, http.StatusForbidden, "账号已停用")
return
}
if bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(req.Password)) != nil {
fail(w, http.StatusUnauthorized, "用户名或密码错误")
return
}
ctx.EntClient.User.UpdateOneID(u.ID).SetLastLoginAt(time.Now().Unix()).ExecX(ctx0())
token, expireAt, err := SignToken(ctx, u.ID, u.Username, u.RealName, u.Role)
if err != nil {
fail(w, http.StatusInternalServerError, "签发 token 失败")
return
}
ok(w, map[string]any{
"token": token,
"expireAt": expireAt,
"user": map[string]any{"id": u.ID, "username": u.Username, "realName": u.RealName, "role": u.Role},
})
}
}
func registerHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req struct {
Username string `json:"username"`
Password string `json:"password"`
RealName string `json:"realName"`
Role string `json:"role"`
}
if err := parseJSON(r, &req); err != nil {
fail(w, http.StatusBadRequest, "参数错误")
return
}
if req.Username == "" || req.Password == "" {
fail(w, http.StatusBadRequest, "用户名和密码必填")
return
}
if len(req.Password) < 6 {
fail(w, http.StatusBadRequest, "密码至少 6 位")
return
}
exists, _ := ctx.EntClient.User.Query().Where(user.UsernameEQ(req.Username)).Exist(ctx0())
if exists {
fail(w, http.StatusConflict, "用户名已存在")
return
}
hash, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
if err != nil {
fail(w, http.StatusInternalServerError, err.Error())
return
}
u, err := ctx.EntClient.User.Create().
SetUsername(req.Username).
SetPassword(string(hash)).
SetNillableRealName(strPtr(req.RealName)).
SetRole(roleOrDefault(req.Role)).
Save(ctx0())
if err != nil {
fail(w, http.StatusInternalServerError, err.Error())
return
}
ok(w, map[string]any{"id": u.ID, "username": u.Username})
}
}
func roleOrDefault(r string) string {
switch r {
case "admin", "operator", "inspector":
return r
default:
return "operator"
}
}
// changePasswordHandler POST /api/user/change-password(需登录 JWT
// 当前登录用户修改自己的密码;登录人由中间件写入的 X-Username 头确定。
func changePasswordHandler(ctx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
username := strings.TrimSpace(r.Header.Get("X-Username"))
if username == "" {
fail(w, http.StatusUnauthorized, "未登录或登录状态缺失")
return
}
var req struct {
OldPassword string `json:"oldPassword"`
NewPassword string `json:"newPassword"`
}
if err := parseJSON(r, &req); err != nil {
fail(w, http.StatusBadRequest, "参数错误")
return
}
if req.OldPassword == "" || req.NewPassword == "" {
fail(w, http.StatusBadRequest, "请输入旧密码和新密码")
return
}
if len(req.NewPassword) < 6 {
fail(w, http.StatusBadRequest, "新密码长度至少 6 位")
return
}
u, err := ctx.EntClient.User.Query().
Where(user.UsernameEQ(username)).
Only(ctx0())
if err != nil {
fail(w, http.StatusNotFound, "用户不存在")
return
}
if bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(req.OldPassword)) != nil {
fail(w, http.StatusBadRequest, "旧密码不正确")
return
}
hash, err := bcrypt.GenerateFromPassword([]byte(req.NewPassword), bcrypt.DefaultCost)
if err != nil {
fail(w, http.StatusInternalServerError, "密码加密失败")
return
}
if err := ctx.EntClient.User.UpdateOneID(u.ID).SetPassword(string(hash)).Exec(ctx0()); err != nil {
fail(w, http.StatusInternalServerError, "密码保存失败")
return
}
ok(w, nil)
}
}