draft
This commit is contained in:
55
internal/modules/domains/handler.go
Normal file
55
internal/modules/domains/handler.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package domains
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
appv1 "stream.api/internal/gen/proto/app/v1"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
appv1.UnimplementedDomainsServiceServer
|
||||
module *Module
|
||||
}
|
||||
|
||||
var _ appv1.DomainsServiceServer = (*Handler)(nil)
|
||||
|
||||
func NewHandler(module *Module) *Handler { return &Handler{module: module} }
|
||||
|
||||
func (h *Handler) ListDomains(ctx context.Context, _ *appv1.ListDomainsRequest) (*appv1.ListDomainsResponse, error) {
|
||||
result, err := h.module.runtime.Authenticate(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
payload, err := h.module.ListDomains(ctx, ListDomainsQuery{UserID: result.UserID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return presentListDomainsResponse(payload), nil
|
||||
}
|
||||
|
||||
func (h *Handler) CreateDomain(ctx context.Context, req *appv1.CreateDomainRequest) (*appv1.CreateDomainResponse, error) {
|
||||
result, err := h.module.runtime.Authenticate(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
payload, err := h.module.CreateDomain(ctx, CreateDomainCommand{UserID: result.UserID, Name: req.GetName()})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return presentCreateDomainResponse(*payload), nil
|
||||
}
|
||||
|
||||
func (h *Handler) DeleteDomain(ctx context.Context, req *appv1.DeleteDomainRequest) (*appv1.MessageResponse, error) {
|
||||
result, err := h.module.runtime.Authenticate(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := h.module.DeleteDomain(ctx, DeleteDomainCommand{UserID: result.UserID, ID: req.GetId()}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return commonMessage("Domain deleted"), nil
|
||||
}
|
||||
|
||||
func commonMessage(message string) *appv1.MessageResponse {
|
||||
return &appv1.MessageResponse{Message: message}
|
||||
}
|
||||
69
internal/modules/domains/module.go
Normal file
69
internal/modules/domains/module.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package domains
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"stream.api/internal/database/model"
|
||||
"stream.api/internal/modules/common"
|
||||
)
|
||||
|
||||
type Module struct {
|
||||
runtime *common.Runtime
|
||||
}
|
||||
|
||||
func New(runtime *common.Runtime) *Module {
|
||||
return &Module{runtime: runtime}
|
||||
}
|
||||
|
||||
func (m *Module) ListDomains(ctx context.Context, queryValue ListDomainsQuery) (*ListDomainsResult, error) {
|
||||
var rows []model.Domain
|
||||
if err := m.runtime.DB().WithContext(ctx).Where("user_id = ?", queryValue.UserID).Order("created_at DESC").Find(&rows).Error; err != nil {
|
||||
m.runtime.Logger().Error("Failed to list domains", "error", err)
|
||||
return nil, status.Error(codes.Internal, "Failed to load domains")
|
||||
}
|
||||
items := make([]DomainView, 0, len(rows))
|
||||
for i := range rows {
|
||||
items = append(items, DomainView{Domain: &rows[i]})
|
||||
}
|
||||
return &ListDomainsResult{Items: items}, nil
|
||||
}
|
||||
|
||||
func (m *Module) CreateDomain(ctx context.Context, cmd CreateDomainCommand) (*DomainView, error) {
|
||||
name := common.NormalizeDomain(cmd.Name)
|
||||
if name == "" || !strings.Contains(name, ".") || strings.ContainsAny(name, "/ ") {
|
||||
return nil, status.Error(codes.InvalidArgument, "Invalid domain")
|
||||
}
|
||||
var count int64
|
||||
if err := m.runtime.DB().WithContext(ctx).Model(&model.Domain{}).Where("user_id = ? AND name = ?", cmd.UserID, name).Count(&count).Error; err != nil {
|
||||
m.runtime.Logger().Error("Failed to validate domain", "error", err)
|
||||
return nil, status.Error(codes.Internal, "Failed to create domain")
|
||||
}
|
||||
if count > 0 {
|
||||
return nil, status.Error(codes.InvalidArgument, "Domain already exists")
|
||||
}
|
||||
item := &model.Domain{ID: uuid.New().String(), UserID: cmd.UserID, Name: name}
|
||||
if err := m.runtime.DB().WithContext(ctx).Create(item).Error; err != nil {
|
||||
m.runtime.Logger().Error("Failed to create domain", "error", err)
|
||||
return nil, status.Error(codes.Internal, "Failed to create domain")
|
||||
}
|
||||
return &DomainView{Domain: item}, nil
|
||||
}
|
||||
|
||||
func (m *Module) DeleteDomain(ctx context.Context, cmd DeleteDomainCommand) error {
|
||||
if cmd.ID == "" {
|
||||
return status.Error(codes.NotFound, "Domain not found")
|
||||
}
|
||||
res := m.runtime.DB().WithContext(ctx).Where("id = ? AND user_id = ?", cmd.ID, cmd.UserID).Delete(&model.Domain{})
|
||||
if res.Error != nil {
|
||||
m.runtime.Logger().Error("Failed to delete domain", "error", res.Error)
|
||||
return status.Error(codes.Internal, "Failed to delete domain")
|
||||
}
|
||||
if res.RowsAffected == 0 {
|
||||
return status.Error(codes.NotFound, "Domain not found")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
18
internal/modules/domains/presenter.go
Normal file
18
internal/modules/domains/presenter.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package domains
|
||||
|
||||
import (
|
||||
appv1 "stream.api/internal/gen/proto/app/v1"
|
||||
"stream.api/internal/modules/common"
|
||||
)
|
||||
|
||||
func presentListDomainsResponse(result *ListDomainsResult) *appv1.ListDomainsResponse {
|
||||
items := make([]*appv1.Domain, 0, len(result.Items))
|
||||
for _, item := range result.Items {
|
||||
items = append(items, common.ToProtoDomain(item.Domain))
|
||||
}
|
||||
return &appv1.ListDomainsResponse{Domains: items}
|
||||
}
|
||||
|
||||
func presentCreateDomainResponse(view DomainView) *appv1.CreateDomainResponse {
|
||||
return &appv1.CreateDomainResponse{Domain: common.ToProtoDomain(view.Domain)}
|
||||
}
|
||||
25
internal/modules/domains/types.go
Normal file
25
internal/modules/domains/types.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package domains
|
||||
|
||||
import "stream.api/internal/database/model"
|
||||
|
||||
type ListDomainsQuery struct {
|
||||
UserID string
|
||||
}
|
||||
|
||||
type CreateDomainCommand struct {
|
||||
UserID string
|
||||
Name string
|
||||
}
|
||||
|
||||
type DeleteDomainCommand struct {
|
||||
UserID string
|
||||
ID string
|
||||
}
|
||||
|
||||
type DomainView struct {
|
||||
Domain *model.Domain
|
||||
}
|
||||
|
||||
type ListDomainsResult struct {
|
||||
Items []DomainView
|
||||
}
|
||||
Reference in New Issue
Block a user