更新 Go 版本至 1.23.0,添加管理员功能,包括管理员登录、用户和客户端管理,新增相应的模板和中间件,优化数据库模型以支持管理员管理。

This commit is contained in:
2025-04-17 01:47:10 +08:00
parent a3f3cc17cf
commit 83c82f7135
18 changed files with 686 additions and 21 deletions

179
services/admin.go Normal file
View File

@@ -0,0 +1,179 @@
package services
import (
"errors"
"time"
"oidc-oauth2-server/models"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
type AdminService struct {
db *gorm.DB
}
func NewAdminService(db *gorm.DB) *AdminService {
return &AdminService{db: db}
}
type AdminCreateRequest struct {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
Email string `json:"email" binding:"required,email"`
Role string `json:"role"`
}
type AdminUpdateRequest struct {
Password string `json:"password"`
Email string `json:"email" binding:"omitempty,email"`
IsActive *bool `json:"is_active"`
Role string `json:"role"`
}
type AdminResponse struct {
ID uint `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
LastLogin time.Time `json:"last_login"`
IsActive bool `json:"is_active"`
Role string `json:"role"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
func (s *AdminService) Create(req *AdminCreateRequest) (*AdminResponse, error) {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
if err != nil {
return nil, err
}
admin := &models.Admin{
Username: req.Username,
Password: string(hashedPassword),
Email: req.Email,
Role: req.Role,
}
if err := s.db.Create(admin).Error; err != nil {
return nil, err
}
return s.toResponse(admin), nil
}
func (s *AdminService) Update(id uint, req *AdminUpdateRequest) (*AdminResponse, error) {
admin := &models.Admin{}
if err := s.db.First(admin, id).Error; err != nil {
return nil, err
}
if req.Password != "" {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
if err != nil {
return nil, err
}
admin.Password = string(hashedPassword)
}
if req.Email != "" {
admin.Email = req.Email
}
if req.IsActive != nil {
admin.IsActive = *req.IsActive
}
if req.Role != "" {
admin.Role = req.Role
}
if err := s.db.Save(admin).Error; err != nil {
return nil, err
}
return s.toResponse(admin), nil
}
func (s *AdminService) Delete(id uint) error {
return s.db.Delete(&models.Admin{}, id).Error
}
func (s *AdminService) Get(id uint) (*AdminResponse, error) {
admin := &models.Admin{}
if err := s.db.First(admin, id).Error; err != nil {
return nil, err
}
return s.toResponse(admin), nil
}
func (s *AdminService) List(page, pageSize int) ([]AdminResponse, int64, error) {
var admins []models.Admin
var total int64
query := s.db.Model(&models.Admin{})
query.Count(&total)
if err := query.Offset((page - 1) * pageSize).Limit(pageSize).Find(&admins).Error; err != nil {
return nil, 0, err
}
responses := make([]AdminResponse, len(admins))
for i, admin := range admins {
responses[i] = *s.toResponse(&admin)
}
return responses, total, nil
}
func (s *AdminService) Authenticate(username, password string) (*AdminResponse, error) {
admin := &models.Admin{}
if err := s.db.Where("username = ?", username).First(admin).Error; err != nil {
return nil, errors.New("invalid credentials")
}
if err := bcrypt.CompareHashAndPassword([]byte(admin.Password), []byte(password)); err != nil {
return nil, errors.New("invalid credentials")
}
admin.LastLogin = time.Now()
if err := s.db.Save(admin).Error; err != nil {
return nil, err
}
return s.toResponse(admin), nil
}
func (s *AdminService) toResponse(admin *models.Admin) *AdminResponse {
return &AdminResponse{
ID: admin.ID,
Username: admin.Username,
Email: admin.Email,
LastLogin: admin.LastLogin,
IsActive: admin.IsActive,
Role: admin.Role,
CreatedAt: admin.CreatedAt,
UpdatedAt: admin.UpdatedAt,
}
}
func (s *AdminService) ListUsers(page, pageSize int) ([]models.User, int64, error) {
var users []models.User
var total int64
s.db.Model(&models.User{}).Count(&total)
err := s.db.Offset((page - 1) * pageSize).Limit(pageSize).Find(&users).Error
return users, total, err
}
func (s *AdminService) ListClients(page, pageSize int) ([]models.Client, int64, error) {
var clients []models.Client
var total int64
s.db.Model(&models.Client{}).Count(&total)
err := s.db.Offset((page - 1) * pageSize).Limit(pageSize).Find(&clients).Error
return clients, total, err
}