任务三

This commit is contained in:
Yvan 2026-01-07 11:04:29 +08:00
parent cd473c0e17
commit b63a296144
1 changed files with 0 additions and 243 deletions

View File

@ -1,243 +0,0 @@
package service
import (
"context"
"crypto/md5"
"encoding/hex"
"time"
v1 "kra/api/kratos/admin/v1"
"kra/internal/biz"
"kra/pkg/auth"
"github.com/go-kratos/kratos/v2/errors"
"go.einride.tech/aip/fieldmask"
"go.einride.tech/aip/filtering"
"go.einride.tech/aip/ordering"
"go.einride.tech/aip/pagination"
"google.golang.org/protobuf/types/known/emptypb"
"google.golang.org/protobuf/types/known/timestamppb"
)
func encodePassword(password string) string {
sum := md5.Sum([]byte(password))
return hex.EncodeToString(sum[:])
}
func convertAdmin(m *biz.Admin) *v1.Admin {
return &v1.Admin{
Id: m.ID,
Name: m.Name,
Email: m.Email,
Avatar: m.Avatar,
Access: m.Access,
CreateTime: timestamppb.New(m.CreateTime),
UpdateTime: timestamppb.New(m.UpdateTime),
}
}
// AdminService is a greeter service.
type AdminService struct {
v1.UnimplementedAdminServiceServer
uc *biz.AdminUsecase
}
// NewAdminService new a greeter service.
func NewAdminService(uc *biz.AdminUsecase) *AdminService {
return &AdminService{uc: uc}
}
// Current implements auth current admin retrieval.
func (s *AdminService) Current(ctx context.Context, req *emptypb.Empty) (*v1.Admin, error) {
a, ok := auth.FromContext(ctx)
if !ok {
return nil, auth.ErrUnauthorized
}
admin, err := s.uc.GetAdmin(ctx, a.UserID)
if err != nil {
return nil, err
}
return convertAdmin(admin), nil
}
// Login implements auth login.
func (s *AdminService) Login(ctx context.Context, req *v1.LoginRequest) (*v1.Admin, error) {
var (
err error
admin *biz.Admin
)
switch v := req.Identity.(type) {
case *v1.LoginRequest_Username:
admin, err = s.uc.LoginByUsername(ctx, v.Username, encodePassword(req.Password))
if err != nil {
return nil, err
}
case *v1.LoginRequest_Email:
admin, err = s.uc.LoginByEmail(ctx, v.Email, encodePassword(req.Password))
if err != nil {
return nil, err
}
default:
return nil, errors.BadRequest("AUTH", "unsupported identity type")
}
if err := auth.SetCookie(ctx, admin.ID, admin.Access, time.Now().Add(7*24*time.Hour)); err != nil {
return nil, err
}
return convertAdmin(admin), nil
}
// Logout implements auth logout.
func (s *AdminService) Logout(ctx context.Context, req *emptypb.Empty) (*emptypb.Empty, error) {
a, ok := auth.FromContext(ctx)
if !ok {
return nil, auth.ErrUnauthorized
}
if err := s.uc.Logout(ctx, a.UserID); err != nil {
return nil, err
}
if err := auth.DeleteCookie(ctx); err != nil {
return nil, err
}
return &emptypb.Empty{}, nil
}
// CreateAdmin implements admin creation.
func (s *AdminService) CreateAdmin(ctx context.Context, req *v1.CreateAdminRequest) (*v1.Admin, error) {
a, ok := auth.FromContext(ctx)
if !ok {
return nil, auth.ErrUnauthorized
}
if !a.HasAdminAccess() {
return nil, auth.ErrForbidden
}
admin, err := s.uc.CreateAdmin(ctx, &biz.Admin{
Name: req.Admin.Name,
Email: req.Admin.Email,
Password: req.Admin.Password,
Avatar: req.Admin.Avatar,
Access: req.Admin.Access,
})
if err != nil {
return nil, err
}
return convertAdmin(admin), nil
}
// UpdateAdmin implements admin update.
func (s *AdminService) UpdateAdmin(ctx context.Context, req *v1.UpdateAdminRequest) (*v1.Admin, error) {
a, ok := auth.FromContext(ctx)
if !ok {
return nil, auth.ErrUnauthorized
}
if !a.HasAdminAccess() {
return nil, auth.ErrForbidden
}
// Encode password if it's not empty
if req.Admin.Password != "" {
req.Admin.Password = encodePassword(req.Admin.Password)
}
admin, err := s.GetAdmin(ctx, &v1.GetAdminRequest{Id: req.Admin.Id})
if err != nil {
return nil, err
}
fieldmask.Update(req.UpdateMask, admin, req.Admin)
updated, err := s.uc.UpdateAdmin(ctx, &biz.Admin{
ID: admin.Id,
Name: admin.Name,
Email: admin.Email,
Password: admin.Password,
Avatar: admin.Avatar,
Access: admin.Access,
})
if err != nil {
return nil, err
}
return convertAdmin(updated), nil
}
// DeleteAdmin implements admin deletion.
func (s *AdminService) DeleteAdmin(ctx context.Context, req *v1.DeleteAdminRequest) (*emptypb.Empty, error) {
a, ok := auth.FromContext(ctx)
if !ok {
return nil, auth.ErrUnauthorized
}
if !a.HasAdminAccess() {
return nil, auth.ErrForbidden
}
if err := s.uc.DeleteAdmin(ctx, req.Id); err != nil {
return nil, err
}
return &emptypb.Empty{}, nil
}
// GetAdmin implements admin retrieval.
func (s *AdminService) GetAdmin(ctx context.Context, req *v1.GetAdminRequest) (*v1.Admin, error) {
a, ok := auth.FromContext(ctx)
if !ok {
return nil, auth.ErrUnauthorized
}
if !a.HasAdminAccess() {
return nil, auth.ErrForbidden
}
admin, err := s.uc.GetAdmin(ctx, req.Id)
if err != nil {
return nil, err
}
return convertAdmin(admin), nil
}
// ListAdmins implements admin listing with filtering, ordering, and pagination.
func (s *AdminService) ListAdmins(ctx context.Context, req *v1.ListAdminsRequest) (*v1.AdminSet, error) {
a, ok := auth.FromContext(ctx)
if !ok {
return nil, auth.ErrUnauthorized
}
if !a.HasAdminAccess() {
return nil, auth.ErrForbidden
}
declarations, err := filtering.NewDeclarations(
filtering.DeclareStandardFunctions(),
filtering.DeclareIdent("name", filtering.TypeString),
filtering.DeclareIdent("email", filtering.TypeString),
filtering.DeclareIdent("phone", filtering.TypeString),
filtering.DeclareIdent("create_time", filtering.TypeTimestamp),
)
if err != nil {
return nil, err
}
filter, err := filtering.ParseFilter(req, declarations)
if err != nil {
return nil, err
}
pageToken, err := pagination.ParsePageToken(req)
if err != nil {
return nil, err
}
orderBy, err := ordering.ParseOrderBy(req)
if err != nil {
return nil, err
}
if req.PageSize <= 0 {
req.PageSize = 20
}
admins, err := s.uc.ListAdmins(ctx,
biz.ListFilter(filter),
biz.ListOrderBy(orderBy),
biz.ListLimit(int(req.PageSize)),
biz.ListOffset(int(pageToken.Offset)),
)
if err != nil {
return nil, err
}
adminSet := &v1.AdminSet{
Admins: make([]*v1.Admin, 0, len(admins)),
}
if len(admins) >= int(req.PageSize) {
adminSet.NextPageToken = pageToken.Next(req).String()
}
for _, admin := range admins {
adminSet.Admins = append(adminSet.Admins, convertAdmin(admin))
}
return adminSet, nil
}