migrate from github
This commit is contained in:
@@ -0,0 +1,323 @@
|
||||
package grpcserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/XingfenD/yoresee_doc/internal/dto"
|
||||
"github.com/XingfenD/yoresee_doc/internal/repository/user_repo"
|
||||
"github.com/XingfenD/yoresee_doc/internal/service/auth_service"
|
||||
"github.com/XingfenD/yoresee_doc/internal/service/invitation_service"
|
||||
"github.com/XingfenD/yoresee_doc/internal/status"
|
||||
"github.com/XingfenD/yoresee_doc/internal/utils"
|
||||
pb "github.com/XingfenD/yoresee_doc/pkg/gen/yoresee_doc/v1"
|
||||
)
|
||||
|
||||
type InvitationServiceServer struct {
|
||||
pb.UnimplementedInvitationServiceServer
|
||||
userRepo *user_repo.UserRepository
|
||||
}
|
||||
|
||||
func NewInvitationServiceServer(userRepo *user_repo.UserRepository) *InvitationServiceServer {
|
||||
return &InvitationServiceServer{
|
||||
userRepo: userRepo,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *InvitationServiceServer) requireAdmin(ctx context.Context) error {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return status.StatusTokenInvalid
|
||||
}
|
||||
isAdmin, err := auth_service.AuthSvc.IsAdmin(userExternalID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !isAdmin {
|
||||
return status.StatusPermissionDenied
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func parseOptionalTime(input *string) (*time.Time, error) {
|
||||
if input == nil || strings.TrimSpace(*input) == "" {
|
||||
return nil, nil
|
||||
}
|
||||
tm, err := time.Parse(time.RFC3339, *input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &tm, nil
|
||||
}
|
||||
|
||||
func (s *InvitationServiceServer) CreateInvitation(ctx context.Context, req *pb.CreateInvitationRequest) (*pb.CreateInvitationResponse, error) {
|
||||
if req == nil {
|
||||
return &pb.CreateInvitationResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.CreateInvitationResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || userExternalID == "" {
|
||||
return &pb.CreateInvitationResponse{Base: baseResponseFromStatus(status.StatusTokenInvalid)}, nil
|
||||
}
|
||||
|
||||
expiresAt, err := parseOptionalTime(req.ExpiresAt)
|
||||
if err != nil {
|
||||
return &pb.CreateInvitationResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
inv, err := invitation_service.InvitationSvc.CreateInvitation(&dto.CreateInvitationRequest{
|
||||
CreatorExternalID: userExternalID,
|
||||
MaxUsedCnt: req.MaxUsedCnt,
|
||||
ExpiresAt: expiresAt,
|
||||
Note: req.Note,
|
||||
})
|
||||
if err != nil {
|
||||
return &pb.CreateInvitationResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
user, _ := s.userRepo.GetByExternalID(userExternalID).Exec()
|
||||
resp := &dto.InvitationResponse{
|
||||
Code: inv.Code,
|
||||
CreatedByExternalID: userExternalID,
|
||||
CreatedByName: "",
|
||||
UsedCnt: inv.UsedCnt,
|
||||
MaxUsedCnt: inv.MaxUsedCnt,
|
||||
ExpiresAt: inv.ExpiresAt,
|
||||
CreatedAt: inv.CreatedAt,
|
||||
Disabled: inv.Disabled,
|
||||
Note: inv.Note,
|
||||
}
|
||||
if user != nil {
|
||||
if user.Nickname != "" {
|
||||
resp.CreatedByName = user.Nickname
|
||||
} else {
|
||||
resp.CreatedByName = user.Username
|
||||
}
|
||||
}
|
||||
|
||||
return &pb.CreateInvitationResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Invitation: toInvitationResponse(resp),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *InvitationServiceServer) ListInvitations(ctx context.Context, req *pb.ListInvitationsRequest) (*pb.ListInvitationsResponse, error) {
|
||||
if req == nil {
|
||||
return &pb.ListInvitationsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
onlyMine := req.OnlyMine != nil && req.GetOnlyMine()
|
||||
if !onlyMine {
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.ListInvitationsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
}
|
||||
|
||||
var creatorID *int64
|
||||
if onlyMine {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || strings.TrimSpace(userExternalID) == "" {
|
||||
return &pb.ListInvitationsResponse{Base: baseResponseFromStatus(status.StatusTokenInvalid)}, nil
|
||||
}
|
||||
id, err := s.userRepo.GetIDByExternalID(userExternalID).Exec()
|
||||
if err != nil {
|
||||
return &pb.ListInvitationsResponse{Base: baseResponseFromErr(status.StatusUserNotFound)}, nil
|
||||
}
|
||||
creatorID = utils.Of(id)
|
||||
}
|
||||
|
||||
sortArgs := dto.SortArgs{Field: "created_at", Desc: true}
|
||||
if req.OrderBy != nil {
|
||||
sortArgs.Field = req.GetOrderBy()
|
||||
}
|
||||
if req.OrderDesc != nil {
|
||||
sortArgs.Desc = req.GetOrderDesc()
|
||||
}
|
||||
|
||||
listReq := &dto.ListInvitationsReq{
|
||||
CreatorID: creatorID,
|
||||
MaxUsedCnt: req.MaxUsedCnt,
|
||||
ExpiresAtStart: req.ExpiresAtStart,
|
||||
ExpiresAtEnd: req.ExpiresAtEnd,
|
||||
CreatedAtStart: req.CreatedAtStart,
|
||||
CreatedAtEnd: req.CreatedAtEnd,
|
||||
Disabled: req.Disabled,
|
||||
OnlyMine: req.OnlyMine,
|
||||
Keyword: req.Keyword,
|
||||
SortArgs: sortArgs,
|
||||
Pagination: dto.Pagination{
|
||||
Page: int(req.Page),
|
||||
PageSize: int(req.PageSize),
|
||||
},
|
||||
}
|
||||
|
||||
invitations, total, err := invitation_service.InvitationSvc.ListInvitations(listReq)
|
||||
if err != nil {
|
||||
return &pb.ListInvitationsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
creatorIDs := make([]int64, 0, len(invitations))
|
||||
for _, inv := range invitations {
|
||||
creatorIDs = append(creatorIDs, inv.CreatedBy)
|
||||
}
|
||||
creatorMap, _ := s.userRepo.MGetUserByID(creatorIDs).Exec()
|
||||
|
||||
respInvites := make([]*pb.InvitationResponse, 0, len(invitations))
|
||||
for _, inv := range invitations {
|
||||
createdByExternalID := ""
|
||||
createdByName := ""
|
||||
if creator := creatorMap[inv.CreatedBy]; creator != nil {
|
||||
createdByExternalID = creator.ExternalID
|
||||
if creator.Nickname != "" {
|
||||
createdByName = creator.Nickname
|
||||
} else {
|
||||
createdByName = creator.Username
|
||||
}
|
||||
}
|
||||
resp := &dto.InvitationResponse{
|
||||
Code: inv.Code,
|
||||
CreatedByExternalID: createdByExternalID,
|
||||
CreatedByName: createdByName,
|
||||
UsedCnt: inv.UsedCnt,
|
||||
MaxUsedCnt: inv.MaxUsedCnt,
|
||||
ExpiresAt: inv.ExpiresAt,
|
||||
CreatedAt: inv.CreatedAt,
|
||||
Disabled: inv.Disabled,
|
||||
Note: inv.Note,
|
||||
}
|
||||
respInvites = append(respInvites, toInvitationResponse(resp))
|
||||
}
|
||||
|
||||
return &pb.ListInvitationsResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Invitations: respInvites,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *InvitationServiceServer) UpdateInvitation(ctx context.Context, req *pb.UpdateInvitationRequest) (*pb.UpdateInvitationResponse, error) {
|
||||
if req == nil || strings.TrimSpace(req.Code) == "" {
|
||||
return &pb.UpdateInvitationResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.UpdateInvitationResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
expiresAt, err := parseOptionalTime(req.ExpiresAt)
|
||||
if err != nil {
|
||||
return &pb.UpdateInvitationResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
|
||||
if err := invitation_service.InvitationSvc.UpdateInvitation(&dto.UpdateInvitationRequest{
|
||||
Code: req.Code,
|
||||
MaxUsedCnt: req.MaxUsedCnt,
|
||||
ExpiresAt: expiresAt,
|
||||
Disabled: req.Disabled,
|
||||
Note: req.Note,
|
||||
}); err != nil {
|
||||
return &pb.UpdateInvitationResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.UpdateInvitationResponse{Base: baseResponseFromErr(nil)}, nil
|
||||
}
|
||||
|
||||
func (s *InvitationServiceServer) DeleteInvitation(ctx context.Context, req *pb.DeleteInvitationRequest) (*pb.DeleteInvitationResponse, error) {
|
||||
if req == nil || strings.TrimSpace(req.Code) == "" {
|
||||
return &pb.DeleteInvitationResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.DeleteInvitationResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
if err := invitation_service.InvitationSvc.DeleteInvitation(&dto.DeleteInvitationRequest{Code: req.Code}); err != nil {
|
||||
return &pb.DeleteInvitationResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
return &pb.DeleteInvitationResponse{Base: baseResponseFromErr(nil)}, nil
|
||||
}
|
||||
|
||||
func (s *InvitationServiceServer) ListInvitationRecords(ctx context.Context, req *pb.ListInvitationRecordsRequest) (*pb.ListInvitationRecordsResponse, error) {
|
||||
if req == nil {
|
||||
return &pb.ListInvitationRecordsResponse{Base: baseResponseFromStatus(status.StatusParamError)}, nil
|
||||
}
|
||||
onlyMine := req.OnlyMine != nil && req.GetOnlyMine()
|
||||
if !onlyMine {
|
||||
if err := s.requireAdmin(ctx); err != nil {
|
||||
return &pb.ListInvitationRecordsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
}
|
||||
|
||||
var creatorID *int64
|
||||
if onlyMine {
|
||||
userExternalID, ok := ctx.Value("user_external_id").(string)
|
||||
if !ok || strings.TrimSpace(userExternalID) == "" {
|
||||
return &pb.ListInvitationRecordsResponse{Base: baseResponseFromStatus(status.StatusTokenInvalid)}, nil
|
||||
}
|
||||
id, err := s.userRepo.GetIDByExternalID(userExternalID).Exec()
|
||||
if err != nil {
|
||||
return &pb.ListInvitationRecordsResponse{Base: baseResponseFromErr(status.StatusUserNotFound)}, nil
|
||||
}
|
||||
creatorID = utils.Of(id)
|
||||
}
|
||||
|
||||
listReq := &dto.ListInvitationRecordsRequest{
|
||||
Code: req.Code,
|
||||
Status: req.Status,
|
||||
UsedAtStart: req.UsedAtStart,
|
||||
UsedAtEnd: req.UsedAtEnd,
|
||||
CreatorID: creatorID,
|
||||
OnlyMine: req.OnlyMine,
|
||||
Keyword: req.Keyword,
|
||||
Pagination: dto.Pagination{
|
||||
Page: int(req.Page),
|
||||
PageSize: int(req.PageSize),
|
||||
},
|
||||
}
|
||||
|
||||
records, total, err := invitation_service.InvitationSvc.ListInvitationRecords(listReq)
|
||||
if err != nil {
|
||||
return &pb.ListInvitationRecordsResponse{Base: baseResponseFromErr(err)}, nil
|
||||
}
|
||||
|
||||
userIDs := make([]int64, 0, len(records))
|
||||
for _, r := range records {
|
||||
if r.UsedByUserID != nil {
|
||||
userIDs = append(userIDs, *r.UsedByUserID)
|
||||
}
|
||||
}
|
||||
userMap, _ := s.userRepo.MGetUserByID(userIDs).Exec()
|
||||
|
||||
respRecords := make([]*pb.InvitationRecordResponse, 0, len(records))
|
||||
for _, r := range records {
|
||||
usedBy := r.UsedBy
|
||||
usedByExternalID := ""
|
||||
if r.UsedByUserID != nil {
|
||||
if user := userMap[*r.UsedByUserID]; user != nil {
|
||||
usedByExternalID = user.ExternalID
|
||||
if user.Nickname != "" {
|
||||
usedBy = user.Nickname
|
||||
} else if user.Username != "" {
|
||||
usedBy = user.Username
|
||||
}
|
||||
}
|
||||
}
|
||||
resp := &dto.InvitationRecordResponse{
|
||||
Code: r.Code,
|
||||
UsedBy: usedBy,
|
||||
UsedByExternalID: usedByExternalID,
|
||||
UsedAt: r.UsedAt,
|
||||
Status: r.Status,
|
||||
}
|
||||
respRecords = append(respRecords, toInvitationRecordResponse(resp))
|
||||
}
|
||||
|
||||
return &pb.ListInvitationRecordsResponse{
|
||||
Base: baseResponseFromErr(nil),
|
||||
Records: respRecords,
|
||||
Total: total,
|
||||
}, nil
|
||||
}
|
||||
Reference in New Issue
Block a user