mirror of
https://github.com/zitadel/zitadel.git
synced 2025-10-23 18:31:43 +00:00
triggers and backend
This commit is contained in:
3
backend/internal/service/doc.go
Normal file
3
backend/internal/service/doc.go
Normal file
@@ -0,0 +1,3 @@
|
||||
// package service contains the effective business logic of the application.
|
||||
// It is the layer that orchestrates the interaction between the domain and the port layer
|
||||
package service
|
11
backend/internal/service/domain.go
Normal file
11
backend/internal/service/domain.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package service
|
||||
|
||||
type DomainGenerator interface {
|
||||
GenerateDomain() (string, error)
|
||||
}
|
||||
|
||||
type Domain struct {
|
||||
Domain string
|
||||
IsPrimary bool
|
||||
IsGenerated bool
|
||||
}
|
5
backend/internal/service/id.go
Normal file
5
backend/internal/service/id.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package service
|
||||
|
||||
type IDGenerator interface {
|
||||
Generate() (id string, err error)
|
||||
}
|
161
backend/internal/service/instance.go
Normal file
161
backend/internal/service/instance.go
Normal file
@@ -0,0 +1,161 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/internal/port"
|
||||
)
|
||||
|
||||
type InstanceService struct {
|
||||
repo InstanceRepository
|
||||
domainRepo InstanceDomainRepository
|
||||
userRepo UserRepository
|
||||
memberRepo InstanceMemberRepository
|
||||
inviteRepo InviteInstanceMemberRepository
|
||||
|
||||
domainGenerator DomainGenerator
|
||||
idGenerator IDGenerator
|
||||
|
||||
pool port.Pool[Instance]
|
||||
}
|
||||
|
||||
var _ port.Object = Instance{}
|
||||
|
||||
type Instance struct {
|
||||
ID string `consistent:"id,pk"`
|
||||
Name string `consistent:"name"`
|
||||
State InstanceState `consistent:"state"`
|
||||
Domains []*Domain `consistent:"domains"`
|
||||
}
|
||||
|
||||
func (i Instance) Columns() []*port.Column {
|
||||
return []*port.Column{
|
||||
{Name: "id", Value: i.ID},
|
||||
{Name: "name", Value: i.Name},
|
||||
{Name: "state", Value: i.State},
|
||||
{Name: "domains", Value: i.Domains},
|
||||
}
|
||||
}
|
||||
|
||||
type InstanceState uint8
|
||||
|
||||
const (
|
||||
InstanceStateUnspecified InstanceState = iota
|
||||
InstanceStateActive
|
||||
InstanceStateRemoved
|
||||
)
|
||||
|
||||
// func NewInstance(
|
||||
// repo port.InstanceRepository,
|
||||
// domainGenerator port.DomainGenerator,
|
||||
// ) *Instance {
|
||||
// return &Instance{repo: repo}
|
||||
// }
|
||||
|
||||
type SetUpInstanceRequest struct {
|
||||
Name string
|
||||
CustomDomain *string
|
||||
|
||||
// Admin is the user to be created as the first user of the instance
|
||||
// If left empty an invite code will be returned to create the admin user
|
||||
Admin *CreateUserRequest
|
||||
}
|
||||
|
||||
type SetUpInstanceResponse struct {
|
||||
Instance *Instance
|
||||
// Admin is the user that was created as the first user of the instance
|
||||
// If the Admin field in the request was empty this field will be nil
|
||||
Admin *User
|
||||
// InviteCode is the invite code that can be used to create the admin user
|
||||
// If the Admin field in the request was not empty this field will be empty
|
||||
InviteCode string
|
||||
}
|
||||
|
||||
func (s *InstanceService) SetUpInstance(ctx context.Context, request *SetUpInstanceRequest) (response *SetUpInstanceResponse, err error) {
|
||||
instance := &Instance{
|
||||
Name: request.Name,
|
||||
State: InstanceStateActive,
|
||||
Domains: make([]*Domain, 0, 2),
|
||||
}
|
||||
if request.CustomDomain != nil {
|
||||
instance.Domains = append(instance.Domains, &Domain{
|
||||
Domain: *request.CustomDomain,
|
||||
IsPrimary: false,
|
||||
IsGenerated: false,
|
||||
},
|
||||
)
|
||||
}
|
||||
instance.ID, err = s.idGenerator.Generate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
generatedDomain, err := s.domainGenerator.GenerateDomain()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
instance.Domains = append(instance.Domains, &Domain{
|
||||
Domain: generatedDomain,
|
||||
IsPrimary: true,
|
||||
IsGenerated: true,
|
||||
})
|
||||
|
||||
var (
|
||||
user *User
|
||||
member *InstanceMember
|
||||
inviteCode string
|
||||
)
|
||||
|
||||
if request.Admin != nil {
|
||||
user = &User{
|
||||
Username: request.Admin.Username,
|
||||
}
|
||||
user.ID, err = s.idGenerator.Generate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
member = &InstanceMember{
|
||||
Member: Member{
|
||||
UserID: user.ID,
|
||||
},
|
||||
Roles: []InstanceMemberRole{InstanceMemberRoleOwner, InstanceMemberRoleAdmin},
|
||||
}
|
||||
}
|
||||
|
||||
tx, err := s.pool.Begin(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer tx.End(ctx, err)
|
||||
|
||||
if err = s.repo.CreateInstance(ctx, tx, instance); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = s.domainRepo.CreateInstanceDomains(ctx, tx, instance.ID, instance.Domains); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
inviteCode, err = s.inviteRepo.InviteInstanceMember(ctx, tx, InstanceMemberRoleOwner, InstanceMemberRoleAdmin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
if err = s.userRepo.CreateUser(ctx, tx, user); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = s.memberRepo.CreateInstanceMember(ctx, tx, member); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return &SetUpInstanceResponse{
|
||||
Instance: instance,
|
||||
Admin: user,
|
||||
InviteCode: inviteCode,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type InstanceRepository interface {
|
||||
// CreateInstance creates a new instance
|
||||
CreateInstance(ctx context.Context, executor port.Executor[Instance], instance *Instance) error
|
||||
}
|
4
backend/internal/service/instance_defaults.go
Normal file
4
backend/internal/service/instance_defaults.go
Normal file
@@ -0,0 +1,4 @@
|
||||
package service
|
||||
|
||||
type InstanceDefaultsRepository interface {
|
||||
}
|
14
backend/internal/service/instance_domain.go
Normal file
14
backend/internal/service/instance_domain.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/internal/port"
|
||||
)
|
||||
|
||||
type InstanceDomainRepository interface {
|
||||
// CreateInstanceDomain creates a new instance domain
|
||||
CreateInstanceDomain(ctx context.Context, executor port.Executor, instanceID string, domain *Domain) error
|
||||
// CreateInstanceDomains creates multiple instance domains
|
||||
CreateInstanceDomains(ctx context.Context, executor port.Executor, instanceID string, domains []*Domain) error
|
||||
}
|
30
backend/internal/service/instance_member.go
Normal file
30
backend/internal/service/instance_member.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/internal/port"
|
||||
)
|
||||
|
||||
type InstanceMember struct {
|
||||
Member
|
||||
Roles []InstanceMemberRole
|
||||
}
|
||||
|
||||
type InstanceMemberRole uint8
|
||||
|
||||
const (
|
||||
InstanceMemberRoleUnspecified InstanceMemberRole = iota
|
||||
InstanceMemberRoleOwner
|
||||
InstanceMemberRoleAdmin
|
||||
)
|
||||
|
||||
type InstanceMemberRepository interface {
|
||||
// CreateInstanceMember creates a new instance member
|
||||
CreateInstanceMember(ctx context.Context, executor port.Executor, member *InstanceMember) error
|
||||
}
|
||||
|
||||
type InviteInstanceMemberRepository interface {
|
||||
// InviteInstanceMember creates a new invite for an instance admin
|
||||
InviteInstanceMember(ctx context.Context, executor port.Executor, roles ...InstanceMemberRole) (code string, err error)
|
||||
}
|
5
backend/internal/service/member.go
Normal file
5
backend/internal/service/member.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package service
|
||||
|
||||
type Member struct {
|
||||
UserID string
|
||||
}
|
30
backend/internal/service/user.go
Normal file
30
backend/internal/service/user.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/zitadel/zitadel/backend/internal/port"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ID string `consistent:"id,pk"`
|
||||
InstanceID string `consistent:"instance_id,pk"`
|
||||
|
||||
Username string `consistent:"username"`
|
||||
}
|
||||
|
||||
func (u User) Columns() []*port.Column {
|
||||
return []*port.Column{
|
||||
{Name: "id", Value: u.ID},
|
||||
{Name: "username", Value: u.Username},
|
||||
}
|
||||
}
|
||||
|
||||
type CreateUserRequest struct {
|
||||
Username string
|
||||
}
|
||||
|
||||
type UserRepository interface {
|
||||
// CreateUser creates a new user
|
||||
CreateUser(ctx context.Context, executor port.Executor[User], user *User) error
|
||||
}
|
Reference in New Issue
Block a user