Skip to content

Commit

Permalink
Merge pull request #801 from traPtitech/domain-availability
Browse files Browse the repository at this point in the history
Domain availability
  • Loading branch information
motoki317 authored Dec 4, 2023
2 parents 399d043 + dda6f08 commit ae4c3c0
Show file tree
Hide file tree
Showing 9 changed files with 890 additions and 797 deletions.
2 changes: 2 additions & 0 deletions api/proto/neoshowcase/protobuf/gateway.proto
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ message AvailableDomain {
string domain = 1;
repeated string exclude_domains = 2;
bool auth_available = 3;
// already_bound ドメインが他のアプリケーションによって専有されているか
bool already_bound = 4;
}

message AvailablePort {
Expand Down
4 changes: 2 additions & 2 deletions cmd/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions dashboard/src/api/neoshowcase/protobuf/gateway_pb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,13 @@ export class AvailableDomain extends Message<AvailableDomain> {
*/
authAvailable = false;

/**
* already_bound ドメインが他のアプリケーションによって専有されているか
*
* @generated from field: bool already_bound = 4;
*/
alreadyBound = false;

constructor(data?: PartialMessage<AvailableDomain>) {
super();
proto3.util.initPartial(data, this);
Expand All @@ -190,6 +197,7 @@ export class AvailableDomain extends Message<AvailableDomain> {
{ no: 1, name: "domain", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 2, name: "exclude_domains", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true },
{ no: 3, name: "auth_available", kind: "scalar", T: 8 /* ScalarType.BOOL */ },
{ no: 4, name: "already_bound", kind: "scalar", T: 8 /* ScalarType.BOOL */ },
]);

static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): AvailableDomain {
Expand Down
2 changes: 1 addition & 1 deletion dashboard/src/components/WebsiteSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ export const WebsiteSettings = (props: WebsiteSettingsProps) => {
<AvailableDomainContainer>
使用可能なホスト
<AvailableDomainUl>
<For each={systemInfo()?.domains || []}>
<For each={systemInfo()?.domains.filter((ad) => !ad.alreadyBound) || []}>
{(domain) => (
<li>
{domain.domain}
Expand Down
14 changes: 14 additions & 0 deletions pkg/domain/app_website.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ type AvailableDomain struct {
Domain string
ExcludeDomains []string
AuthAvailable bool
AlreadyBound bool // Actual availability (whether domain is bound to a specific app or not)
}

type AvailableDomainSlice []*AvailableDomain
Expand All @@ -85,6 +86,19 @@ func (a *AvailableDomain) Validate() error {
return nil
}

func (a *AvailableDomain) SetAlreadyBound(existing []*Application) {
if strings.HasPrefix(a.Domain, "*.") {
// Wildcard domain cannot be bound to one app, it has infinite number of subdomains
a.AlreadyBound = false
} else {
a.AlreadyBound = lo.ContainsBy(existing, func(app *Application) bool {
return lo.ContainsBy(app.Websites, func(w *Website) bool {
return w.FQDN == a.Domain && w.PathPrefix == "/" // Intentional vague checking of http or https
})
})
}
}

func (a *AvailableDomain) Match(fqdn string) bool {
for _, excludeDomain := range a.ExcludeDomains {
if ContainsDomain(excludeDomain, fqdn) {
Expand Down
44 changes: 44 additions & 0 deletions pkg/domain/app_website_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,50 @@ func TestAvailableDomain_Validate(t *testing.T) {
}
}

func TestAvailableDomain_SetAlreadyBound(t *testing.T) {
tests := []struct {
name string
domain string
existing *Website
want bool
}{
{
name: "Wildcard cannot be bound to one app",
domain: "*.example.com",
existing: &Website{FQDN: "app.example.com", PathPrefix: "/"},
want: false,
},
{
name: "Bound to an app",
domain: "app.example.com",
existing: &Website{FQDN: "app.example.com", PathPrefix: "/"},
want: true,
},
{
name: "Bound to a different domain",
domain: "app.example.com",
existing: &Website{FQDN: "app2.example.com", PathPrefix: "/"},
want: false,
},
{
name: "Bound to path subset",
domain: "app.example.com",
existing: &Website{FQDN: "app.example.com", PathPrefix: "/prefix"},
want: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
a := &AvailableDomain{
Domain: tt.domain,
}
a.SetAlreadyBound([]*Application{{Websites: []*Website{tt.existing}}})
assert.Equal(t, tt.want, a.AlreadyBound)
})
}
}

func TestAvailableDomain_Match(t *testing.T) {
simpleTests := []struct {
name string
Expand Down
12 changes: 12 additions & 0 deletions pkg/infrastructure/grpc/controller_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (

type ControllerService struct {
backend domain.Backend
appRepo domain.ApplicationRepository
fetcher repofetcher.Service
cd cdservice.Service
builder domain.ControllerBuilderService
Expand All @@ -31,6 +32,7 @@ type ControllerService struct {

func NewControllerService(
backend domain.Backend,
appRepo domain.ApplicationRepository,
fetcher repofetcher.Service,
cd cdservice.Service,
builder domain.ControllerBuilderService,
Expand All @@ -41,6 +43,7 @@ func NewControllerService(
) pbconnect.ControllerServiceHandler {
return &ControllerService{
backend: backend,
appRepo: appRepo,
fetcher: fetcher,
cd: cd,
builder: builder,
Expand All @@ -53,7 +56,16 @@ func NewControllerService(

func (s *ControllerService) GetSystemInfo(_ context.Context, _ *connect.Request[emptypb.Empty]) (*connect.Response[pb.SystemInfo], error) {
domains := s.backend.AvailableDomains()
existingApps, err := s.appRepo.GetApplications(context.Background(), domain.GetApplicationCondition{})
if err != nil {
return nil, err
}
for _, ad := range domains {
ad.SetAlreadyBound(existingApps)
}

ports := s.backend.AvailablePorts()

res := connect.NewResponse(&pb.SystemInfo{
PublicKey: domain.Base64EncodedPublicKey(s.pubKey.Signer.PublicKey()) + " neoshowcase",
Ssh: &pb.SSHInfo{
Expand Down
Loading

0 comments on commit ae4c3c0

Please sign in to comment.