mirror of
https://github.com/SamyRai/tercul-backend.git
synced 2025-12-27 05:11:34 +00:00
The integration tests for admin-only mutations were failing due to an authorization issue. The root cause was that the JWT token used in the tests did not reflect the user's admin role, which was being set directly in the database. This commit fixes the issue by: 1. Updating the `CreateAuthenticatedUser` test helper to generate a new JWT token after a user's role is changed. This ensures the token contains the correct, up-to-date role. 2. Removing all uses of `auth.ContextWithAdminUser` from the integration tests, making the JWT token the single source of truth for authorization. This change also removes unused imports and variables that were causing build failures after the refactoring. All integration tests now pass.
118 lines
3.1 KiB
Go
118 lines
3.1 KiB
Go
package translation
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"tercul/internal/app/authz"
|
|
"tercul/internal/domain"
|
|
platform_auth "tercul/internal/platform/auth"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// TranslationCommands contains the command handlers for the translation aggregate.
|
|
type TranslationCommands struct {
|
|
repo domain.TranslationRepository
|
|
authzSvc *authz.Service
|
|
}
|
|
|
|
// NewTranslationCommands creates a new TranslationCommands handler.
|
|
func NewTranslationCommands(repo domain.TranslationRepository, authzSvc *authz.Service) *TranslationCommands {
|
|
return &TranslationCommands{
|
|
repo: repo,
|
|
authzSvc: authzSvc,
|
|
}
|
|
}
|
|
|
|
// CreateTranslationInput represents the input for creating a new translation.
|
|
type CreateTranslationInput struct {
|
|
Title string
|
|
Content string
|
|
Description string
|
|
Language string
|
|
Status domain.TranslationStatus
|
|
TranslatableID uint
|
|
TranslatableType string
|
|
TranslatorID *uint
|
|
IsOriginalLanguage bool
|
|
}
|
|
|
|
// CreateTranslation creates a new translation.
|
|
func (c *TranslationCommands) CreateTranslation(ctx context.Context, input CreateTranslationInput) (*domain.Translation, error) {
|
|
translation := &domain.Translation{
|
|
Title: input.Title,
|
|
Content: input.Content,
|
|
Description: input.Description,
|
|
Language: input.Language,
|
|
Status: input.Status,
|
|
TranslatableID: input.TranslatableID,
|
|
TranslatableType: input.TranslatableType,
|
|
TranslatorID: input.TranslatorID,
|
|
IsOriginalLanguage: input.IsOriginalLanguage,
|
|
}
|
|
err := c.repo.Create(ctx, translation)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return translation, nil
|
|
}
|
|
|
|
// UpdateTranslationInput represents the input for updating an existing translation.
|
|
type UpdateTranslationInput struct {
|
|
ID uint
|
|
Title string
|
|
Content string
|
|
Description string
|
|
Language string
|
|
Status domain.TranslationStatus
|
|
}
|
|
|
|
// UpdateTranslation updates an existing translation.
|
|
func (c *TranslationCommands) UpdateTranslation(ctx context.Context, input UpdateTranslationInput) (*domain.Translation, error) {
|
|
userID, ok := platform_auth.GetUserIDFromContext(ctx)
|
|
if !ok {
|
|
return nil, domain.ErrUnauthorized
|
|
}
|
|
|
|
can, err := c.authzSvc.CanEditTranslation(ctx, userID, input.ID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !can {
|
|
return nil, domain.ErrForbidden
|
|
}
|
|
|
|
translation, err := c.repo.GetByID(ctx, input.ID)
|
|
if err != nil {
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, fmt.Errorf("%w: translation with id %d not found", domain.ErrNotFound, input.ID)
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
translation.Title = input.Title
|
|
translation.Content = input.Content
|
|
translation.Description = input.Description
|
|
translation.Language = input.Language
|
|
translation.Status = input.Status
|
|
err = c.repo.Update(ctx, translation)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return translation, nil
|
|
}
|
|
|
|
// DeleteTranslation deletes a translation by ID.
|
|
func (c *TranslationCommands) DeleteTranslation(ctx context.Context, id uint) error {
|
|
can, err := c.authzSvc.CanDeleteTranslation(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !can {
|
|
return domain.ErrForbidden
|
|
}
|
|
|
|
return c.repo.Delete(ctx, id)
|
|
}
|